import React from 'react';
import PropTypes from 'prop-types';

import { SORT_ASC, SORT_DESC } from '@/modules/@common/constants/sort';

import TableCellActions$ from './components/TableCellActions/TableCellActions';
import {
  Checkbox,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TablePagination,
  TableRow,
  TableScroll,
  TableSortLabel,
  Tooltip,
} from '@/mui/components';

function CommonTable({
  size = 'large',
  sortOrder = SORT_ASC,
  selected = [],
  enableBulkActions = false,
  bulkActionsIndeterminate = undefined,
  bulkActionsChecked = undefined,
  inverseScroll = false,
  paginationHide = false,
  stickyHeader = false,
  onSelectDeselectAllRows = (v) => v,
  onSelectDeselectRow = (v) => v,
  onFilter = (v) => v,
  ...props
}) {
  return (
    <TableContainer>
      <TableScroll inverseScroll={inverseScroll}>
        <Table size={size ?? 'large'} stickyHeader={stickyHeader}>
          <TableHead>
            <TableRow>
              {enableBulkActions && (
                <TableCell padding="checkbox" align="center">
                  <Checkbox
                    color="primary"
                    inputProps={{
                      'aria-label': 'select all desserts',
                    }}
                    indeterminate={
                      bulkActionsIndeterminate ?? (!!selected.length && selected.length < props.data.length)
                    }
                    checked={bulkActionsChecked ?? (!!props.data.length && selected.length === props.data.length)}
                    onChange={({ target: { checked } }) => {
                      onSelectDeselectAllRows(checked);
                    }}
                  />
                </TableCell>
              )}

              {props.configHeaders.map((header) => {
                let { padding } = header;

                if (!padding && !header.label) {
                  padding = 'checkbox';
                }

                return (
                  <TableCell
                    colSpan={header.colspan}
                    key={header.id}
                    padding={padding}
                    width={header.width ?? 'inherit'}
                    align={header.align ?? 'left'}
                    data-id={`header-${header.id}`}
                    sortDirection={props.sortBy === header.id ? sortOrder : false}
                    noWrap
                    className={header.className ?? ''}
                  >
                    <Tooltip title={header.tooltip} disableInteractive>
                      {header.sortable ? (
                        <TableSortLabel
                          active={props.sortBy === header.id}
                          direction={props.sortBy === header.id ? sortOrder : SORT_ASC}
                          onClick={() =>
                            onFilter({
                              sortBy: header.id,
                              sortOrder: sortOrder === SORT_ASC ? SORT_DESC : SORT_ASC,
                              page: 1,
                            })
                          }
                        >
                          {header.label}
                        </TableSortLabel>
                      ) : (
                        <div>{header.label}</div>
                      )}
                    </Tooltip>
                  </TableCell>
                );
              })}
            </TableRow>
            {props.configSubHeaders?.length > 0 && (
              <TableRow>
                {enableBulkActions && (
                  <TableCell padding="checkbox" align="center">
                    <Checkbox
                      color="primary"
                      inputProps={{
                        'aria-label': 'select all desserts',
                      }}
                      indeterminate={
                        bulkActionsIndeterminate ?? (!!selected.length && selected.length < props.data.length)
                      }
                      checked={bulkActionsChecked ?? (!!props.data.length && selected.length === props.data.length)}
                      onChange={({ target: { checked } }) => {
                        onSelectDeselectAllRows(checked);
                      }}
                    />
                  </TableCell>
                )}

                {props.configSubHeaders.map((header) => {
                  let { padding } = header;

                  if (!padding && !header.label) {
                    padding = 'checkbox';
                  }

                  return (
                    <TableCell
                      key={header.id}
                      padding={padding}
                      width={header.width ?? 'inherit'}
                      align={header.align ?? 'left'}
                      data-id={`header-${header.id}`}
                      sortDirection={props.sortBy === header.id ? sortOrder : false}
                      noWrap
                      className={header.className ?? ''}
                    >
                      <Tooltip title={header.tooltip} disableInteractive>
                        {header.sortable ? (
                          <TableSortLabel
                            active={props.sortBy === header.id}
                            direction={props.sortBy === header.id ? sortOrder : SORT_ASC}
                            onClick={() =>
                              onFilter({
                                sortBy: header.id,
                                sortOrder: sortOrder === SORT_ASC ? SORT_DESC : SORT_ASC,
                                page: 1,
                              })
                            }
                          >
                            {header.label}
                          </TableSortLabel>
                        ) : (
                          <div>{header.label}</div>
                        )}
                      </Tooltip>
                    </TableCell>
                  );
                })}
              </TableRow>
            )}
          </TableHead>
          <TableBody>{props.data.map((row) => props.configRenderRow(row, selected, onSelectDeselectRow))}</TableBody>
        </Table>
      </TableScroll>
      {props.totalCount > 0 && !paginationHide && (
        <TablePagination
          size={size === 'small' ? 'small' : 'medium'}
          component="div"
          rowsPerPageOptions={[10, 15, 25]}
          count={props.totalCount}
          page={props.page}
          rowsPerPage={props.rowsPerPage}
          onPageChange={(event, selectedPage) => onFilter({ page: selectedPage })}
          onRowsPerPageChange={(event) =>
            onFilter({
              pageSize: parseInt(event.target.value, 10),
              page: 1,
            })
          }
        />
      )}
    </TableContainer>
  );
}

CommonTable.propTypes = {
  size: PropTypes.oneOf(['small', 'large']),
  configHeaders: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
  configSubHeaders: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
  enableBulkActions: PropTypes.bool,
  bulkActionsIndeterminate: PropTypes.bool,
  bulkActionsChecked: PropTypes.bool,
  inverseScroll: PropTypes.bool,
  configRenderRow: PropTypes.func.isRequired,
  selected: PropTypes.arrayOf(PropTypes.number),
  data: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
  sortBy: PropTypes.string.isRequired,
  sortOrder: PropTypes.oneOf([SORT_ASC, SORT_DESC]),
  totalCount: PropTypes.number.isRequired,
  page: PropTypes.number.isRequired,
  rowsPerPage: PropTypes.number.isRequired,
  paginationHide: PropTypes.bool,
  stickyHeader: PropTypes.bool,

  onSelectDeselectAllRows: PropTypes.func,
  onSelectDeselectRow: PropTypes.func,
  onFilter: PropTypes.func,
};

export const TableCellActions = TableCellActions$;

export default CommonTable;
