import { useState, useCallback } from 'react';
import { SelectChangeEvent } from '@mui/material';

export type ReturnType = {
  dense: boolean;
  page: number;
  orderBy: string;
  rowsPerPage: number;
  order: 'asc' | 'desc';
  selected: string[];
  onSelectRow: (inputValue: string) => void;
  onSelectAllRows: (checked: boolean, inputValue: string[]) => void;
  onSort: (id: string) => void;
  onChangePage: (event: unknown, newPage: number) => void;
  onChangeDense: (event: React.ChangeEvent<HTMLInputElement>) => void;
  onChangeRowsPerPage: (event: SelectChangeEvent<number>) => void;
  onResetPage: VoidFunction;
};

export type UseTableProps = {
  defaultDense?: boolean;
  defaultOrder?: 'asc' | 'desc';
  defaultOrderBy?: string;
  defaultSelected?: string[];
  defaultRowsPerPage?: number;
  defaultCurrentPage?: number;
};

export default function useTable(props?: UseTableProps): ReturnType {
  const [dense, setDense] = useState(!!props?.defaultDense);
  const [page, setPage] = useState(props?.defaultCurrentPage || 0);
  const [orderBy, setOrderBy] = useState(props?.defaultOrderBy || 'id');
  const [rowsPerPage, setRowsPerPage] = useState(props?.defaultRowsPerPage || 20);
  const [order, setOrder] = useState<'asc' | 'desc'>(props?.defaultOrder || 'desc');
  const [selected, setSelected] = useState<string[]>(props?.defaultSelected || []);

  const onSort = useCallback(
    (id: string) => {
      const isAsc = orderBy === id && order === 'asc';
      if (id !== '') {
        setOrder(isAsc ? 'desc' : 'asc');
        setOrderBy(id);
      }
    },
    [order, orderBy]
  );

  const onSelectRow = useCallback(
    (inputValue: string) => {
      const newSelected = selected.includes(inputValue)
        ? selected.filter((value) => value !== inputValue)
        : [...selected, inputValue];

      setSelected(newSelected);
    },
    [selected]
  );

  const onChangeRowsPerPage = useCallback((event: SelectChangeEvent<number>) => {
    const size = parseInt(event.target.value as string, 10);
    if (!isNaN(size) && size > 0) {
      setPage(0);
      setRowsPerPage(size);
    }
  }, []);

  const onChangeDense = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
    setDense(event.target.checked);
  }, []);

  const onSelectAllRows = useCallback((checked: boolean, inputValue: string[]) => {
    if (checked) {
      setSelected(inputValue);
      return;
    }
    setSelected([]);
  }, []);

  const onChangePage = useCallback((event: unknown, newPage: number) => {
    setPage(newPage);
  }, []);

  const onResetPage = useCallback(() => {
    setPage(0);
  }, []);

  return {
    dense,
    page,
    orderBy,
    rowsPerPage,
    order,
    selected,
    onSelectRow,
    onSelectAllRows,
    onSort,
    onChangePage,
    onChangeDense,
    onChangeRowsPerPage,
    onResetPage,
  };
}
