import React, { useMemo } from "react";
import { ArrowUpIcon, ArrowDownIcon } from "@heroicons/react/24/solid";

import {
  useReactTable,
  getCoreRowModel,
  getFilteredRowModel,
  getPaginationRowModel,
  ColumnDef,
  flexRender,
  getSortedRowModel,
  Table as ReactTable,
  CellContext,
  HeaderContext,
} from "@tanstack/react-table";
import Checkbox from "../checkbox/checkbox";

export interface TableProps<TData = any> {
  data: TData[];
  columns: ColumnDef<TData>[];
  enableRowSelection?: boolean;
  enableSorting?: boolean;
  cellProps?: (
    context: CellContext<TData, any>
  ) => React.HTMLProps<HTMLTableCellElement>;
  headerCellProps?: (
    context: HeaderContext<TData, any>
  ) => React.HTMLProps<HTMLTableCellElement>;
  header?: (table: ReactTable<TData>) => React.ReactNode;
  footer?: (table: ReactTable<TData>) => React.ReactNode;
}

export function Table({
  data,
  columns,
  enableRowSelection = false,
  enableSorting = false,
  cellProps = () => ({}),
  headerCellProps = () => ({}),
  header = () => null,
  footer = () => null,
}: TableProps) {
  const table = useReactTable({
    data,
    columns: columns,
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getSortedRowModel: enableSorting ? getSortedRowModel() : undefined,
    getPaginationRowModel: getPaginationRowModel(),
    debugTable: true,
  });

  return (
    <div className="border border-gray-200 rounded-lg overflow-hidden">
      <div>{header(table)}</div>
      <div className="overflow-auto">
        <table className="w-full border-t border-b border-gray-200">
          <thead>
            {table.getHeaderGroups().map((headerGroup, headerGroupIndex) => (
              <tr key={headerGroup.id}>
                {headerGroup.headers.map((header, headerIndex) => {
                  return (
                    <th
                      key={header.id}
                      colSpan={header.colSpan}
                      className={`bg-gray-50 border-t border-gray-200 px-6 py-3 text-xs font-Inter font-normal text-gray-500 ${
                        header.subHeaders.length ? "text-center" : "text-left"
                      }`}
                      {...headerCellProps(header.getContext())}
                    >
                      {header.isPlaceholder ? null : (
                        <div
                          {...(enableSorting
                            ? {
                                className: `${
                                  header.column.getCanSort()
                                    ? "cursor-pointer select-none flex"
                                    : "flex"
                                }`,
                                onClick:
                                  header.column.getToggleSortingHandler(),
                              }
                            : {})}
                        >
                          <div className="flex items-center">
                            {enableRowSelection &&
                              headerGroupIndex ===
                                table.getHeaderGroups().length - 1 &&
                              headerIndex === 0 && (
                                <Checkbox
                                  id="row_select"
                                  name="row_select"
                                  color="danger"
                                  size="small"
                                  {...{
                                    checked: table.getIsAllRowsSelected(),
                                    indeterminate:
                                      table.getIsSomeRowsSelected(),
                                    onChange:
                                      table.getToggleAllRowsSelectedHandler(),
                                  }}
                                />
                              )}
                            {flexRender(
                              header.column.columnDef.header,
                              header.getContext()
                            )}
                            {{
                              asc: (
                                <ArrowUpIcon className="text-gray-700 w-3 ml-1" />
                              ),
                              desc: (
                                <ArrowDownIcon className="text-gray-700 w-3 ml-1" />
                              ),
                            }[header.column.getIsSorted() as string] ?? null}
                          </div>
                        </div>
                      )}
                    </th>
                  );
                })}
              </tr>
            ))}
          </thead>
          <tbody>
            {table.getRowModel().rows.map((row) => {
              return (
                <tr key={row.id}>
                  {row.getVisibleCells().map((cell, cellIndex) => {
                    return (
                      <td
                        key={cell.id}
                        className={`px-6 py-4 text-sm font-normal font-Inter text-gray-500 text-left border-t border-gray-200`}
                        {...cellProps(cell.getContext())}
                      >
                        <div className="flex items-center">
                          {enableRowSelection && cellIndex === 0 && (
                            <Checkbox
                              id="row_select"
                              name="row_select"
                              color="info"
                              size="small"
                              {...{
                                checked: row.getIsSelected(),
                                indeterminate: row.getIsSomeSelected(),
                                onChange: row.getToggleSelectedHandler(),
                              }}
                            />
                          )}
                          {flexRender(
                            cell.column.columnDef.cell,
                            cell.getContext()
                          )}
                        </div>
                      </td>
                    );
                  })}
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
      <div>{footer(table)}</div>
    </div>
  );
}

export default Table;
