import React, { forwardRef, useMemo, useRef, useEffect, useState, useImperativeHandle } from 'react';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import { Table, Pagination, Checkbox, Alert } from '@/components/ui';
import TableRowSkeleton from './loaders/TableRowSkeleton';
import Loading from './Loading';
import {
  useReactTable,
  getCoreRowModel,
  getFilteredRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  flexRender,
} from '@tanstack/react-table';
import { t } from 'i18next';
import useWindowSize from '@/components/ui/hooks/useWindowSize';

const { Tr, Th, Td, THead, TBody, Sorter } = Table;

const IndeterminateCheckbox = (props) => {
  const { indeterminate, onChange, onCheckBoxChange, onIndeterminateCheckBoxChange, ...rest } = props;

  const ref = useRef(null);

  useEffect(() => {
    if (typeof indeterminate === 'boolean') {
      ref.current.indeterminate = !rest.checked && indeterminate;
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [ref, indeterminate]);

  const handleChange = (e) => {
    onChange(e);
    onCheckBoxChange?.(e);
    onIndeterminateCheckBoxChange?.(e);
  };

  return <Checkbox className="mb-0" ref={ref} onChange={(_, e) => handleChange(e)} {...rest} />;
};

const DataTable = forwardRef((props, ref) => {
  const {
    skeletonAvatarColumns,
    columns: columnsProp,
    data,
    loading,
    onCheckBoxChange,
    onIndeterminateCheckBoxChange,
    onPaginationChange,
    // onSelectChange,
    onSort,
    //pageSizes,
    selectable,
    skeletonAvatarProps,
    pagingData,
  } = props;

  const { pageSize, pageIndex, total } = pagingData;
  const { screenSize, windowWidth } = useWindowSize();

  const [sorting, setSorting] = useState(null);

  // const pageSizeOption = useMemo(
  //   () =>
  //     pageSizes.map((number) => ({
  //       value: number,
  //       label: `${number} / page`,
  //     })),
  //   [pageSizes],
  // );

  const handleCheckBoxChange = (checked, row) => {
    if (!loading) {
      onCheckBoxChange?.(checked, row);
    }
  };

  const handleIndeterminateCheckBoxChange = (checked, rows) => {
    if (!loading) {
      onIndeterminateCheckBoxChange?.(checked, rows);
    }
  };

  const handlePaginationChange = (page) => {
    if (!loading) {
      onPaginationChange?.(page);
    }
  };

  // const handleSelectChange = (value) => {
  //   if (!loading) {
  //     onSelectChange?.(Number(value));
  //   }
  // };

  useEffect(() => {
    if (Array.isArray(sorting)) {
      const sortOrder = sorting.length > 0 ? (sorting[0].desc ? 'desc' : 'asc') : '';
      const id = sorting.length > 0 ? sorting[0].id : '';
      onSort?.({ order: sortOrder, key: id });
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [sorting]);

  const hasOldColumnMetaKey = columnsProp.some((col) => col.Header || col.accessor || col.Cell);

  const finalColumns = useMemo(() => {
    let columns = columnsProp;

    if (selectable) {
      return [
        {
          id: 'select',
          header: ({ table }) => (
            <IndeterminateCheckbox
              checked={table.getIsAllRowsSelected()}
              indeterminate={table.getIsSomeRowsSelected()}
              onChange={table.getToggleAllRowsSelectedHandler()}
              onIndeterminateCheckBoxChange={(e) => {
                handleIndeterminateCheckBoxChange(e.target.checked, table.getRowModel().rows);
              }}
            />
          ),
          cell: ({ row }) => (
            <IndeterminateCheckbox
              checked={row.getIsSelected()}
              disabled={!row.getCanSelect()}
              indeterminate={row.getIsSomeSelected()}
              onChange={row.getToggleSelectedHandler()}
              onCheckBoxChange={(e) => handleCheckBoxChange(e.target.checked, row.original)}
            />
          ),
        },
        ...columns,
      ];
    }

    if (screenSize === 'xs') {
      // Filter columns based on showOnMobile property
      return columns.filter((column) => column.showOnMobile || !column.hasOwnProperty('showOnMobile'));
    }

    return columns;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [columnsProp, selectable, screenSize, windowWidth]);

  const table = useReactTable({
    data,
    columns: hasOldColumnMetaKey ? [] : finalColumns,
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    getSortedRowModel: getSortedRowModel(),
    manualPagination: true,
    manualSorting: true,
    onSortingChange: setSorting,
    state: {
      sorting,
    },
  });

  const resetSorting = () => {
    table.resetSorting();
  };

  const resetSelected = () => {
    table.toggleAllRowsSelected(false);
  };

  useImperativeHandle(ref, () => ({
    resetSorting,
    resetSelected,
  }));

  if (hasOldColumnMetaKey) {
    const message =
      'You are using old react-table v7 column config, please use v8 column config instead, refer to our demo or https://tanstack.com/table/v8';

    if (process.env.NODE_ENV === 'development') {
      console.warn(message);
    }

    return <Alert>{message}</Alert>;
  }

  return (
    <Loading loading={loading && data.length !== 0} type="cover">
      <Table className="border">
        <THead>
          {table.getHeaderGroups().map((headerGroup) => (
            <Tr key={headerGroup.id}>
              {headerGroup.headers.map((header) => {
                return (
                  //border in right and bottom
                  <Th key={header.id} colSpan={header.colSpan} className="border-b border-gray-200 border-r ">
                    {header.isPlaceholder ? null : (
                      <div
                        className={classNames(
                          header.column.getCanSort() && 'cursor-pointer select-none point text-sm',
                          loading && 'pointer-events-none',
                        )}
                        onClick={header.column.getToggleSortingHandler()}
                      >
                        {flexRender(header.column.columnDef.header, header.getContext())}
                        {header.column.getCanSort() && <Sorter sort={header.column.getIsSorted()} />}
                      </div>
                    )}
                  </Th>
                );
              })}
            </Tr>
          ))}
        </THead>
        {loading && data.length === 0 ? (
          <TableRowSkeleton
            columns={finalColumns.length}
            rows={pagingData.pageSize}
            avatarInColumns={skeletonAvatarColumns}
            avatarProps={skeletonAvatarProps}
          />
        ) : (
          <TBody>
            {data.length > 0 &&
              table
                .getRowModel()
                .rows.slice(0, 10)
                .map((row) => {
                  return (
                    <Tr key={row.id}>
                      {row.getVisibleCells().map((cell) => {
                        return (
                          <Td key={cell.id} className="border p-2 ">
                            {flexRender(cell.column.columnDef.cell, cell.getContext())}
                          </Td>
                        );
                      })}
                    </Tr>
                  );
                })}
            {data.length === 0 && (
              <Tr>
                <Td colSpan={finalColumns.length} className="text-center  bg-gray-50 dark:bg-gray-700">
                  {t('NO_DATA')}
                </Td>
              </Tr>
            )}
          </TBody>
        )}
      </Table>
      <div className="flex items-center justify-between mt-4">
        <div>
          <span className="text-md ">{t('THE_TOTAL_NUMBER')}:</span>
          <span className="px-2  text-md ">{(total).toLocaleString()}</span>
        </div>
        <Pagination pageSize={pageSize} currentPage={pageIndex} total={total} onChange={handlePaginationChange} />
        {/* <div style={{ minWidth: 130 }}>
          <Select
            size="sm"
            menuPlacement="top"
            isSearchable={false}
            value={pageSizeOption.filter((option) => option.value === pageSize)}
            options={pageSizeOption}
            onChange={(option) => handleSelectChange(option.value)}
          />
            </div> */}
      </div>
    </Loading>
  );
});

DataTable.propTypes = {
  columns: PropTypes.array,
  data: PropTypes.array,
  loading: PropTypes.bool,
  onCheckBoxChange: PropTypes.func,
  onIndeterminateCheckBoxChange: PropTypes.func,
  onPaginationChange: PropTypes.func,
  onSelectChange: PropTypes.func,
  onSort: PropTypes.func,
  pageSizes: PropTypes.arrayOf(PropTypes.number),
  selectable: PropTypes.bool,
  skeletonAvatarColumns: PropTypes.arrayOf(PropTypes.number),
  skeletonAvatarProps: PropTypes.object,
  pagingData: PropTypes.shape({
    total: PropTypes.number,
    pageIndex: PropTypes.number,
    pageSize: PropTypes.number,
  }),
};

DataTable.defaultProps = {
  pageSizes: [10, 25, 50, 100],
  pagingData: {
    total: 0,
    pageIndex: 1,
    pageSize: 10,
  },
  data: [],
  columns: [],
  selectable: false,
  loading: false,
};

export default DataTable;
