import { useListSearch } from "@/hooks/useListSearch";
import {
  ColumnDef,
  flexRender,
  getCoreRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  PaginationState,
  useReactTable,
} from "@tanstack/react-table";
import clsx from "clsx";
import { useState } from "react";
import { BsArrowDown, BsArrowUp } from "react-icons/bs";
import Button from "../Low/Button";

interface Props<T> {
  data: T[];
  columns: ColumnDef<any, any>[];
  searchFields: string[][];
  size?: number;
  onDownload?: (rows: T[]) => void;
  isDownloadLoading?: boolean;
  searchPlaceholder?: string;
  isLoading?: boolean;
}

export default function Table<T>({
  data,
  columns,
  searchFields,
  size = 16,
  onDownload,
  isDownloadLoading,
  searchPlaceholder,
  isLoading,
}: Props<T>) {
  const [pagination, setPagination] = useState<PaginationState>({
    pageIndex: 0,
    pageSize: size,
  });

  const { rows, renderSearch } = useListSearch<T>(
    searchFields,
    data,
    searchPlaceholder
  );

  const table = useReactTable({
    data: rows,
    columns,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    onPaginationChange: setPagination,
    state: {
      pagination,
    },
  });

  return (
    <div className="w-full flex flex-col gap-2">
      <div className="w-full flex gap-2 items-end">
        {renderSearch()}
        {onDownload && (
          <Button
            isLoading={isDownloadLoading}
            className="w-full max-w-[200px] mb-1"
            variant="outline"
            onClick={() => onDownload(rows)}
          >
            Download
          </Button>
        )}
      </div>

      <div className="w-full flex gap-2 justify-between items-center">
        <div className="flex items-center gap-4 w-fit">
          <Button
            className="w-[200px] h-fit"
            disabled={!table.getCanPreviousPage()}
            onClick={() => table.previousPage()}
          >
            Previous Page
          </Button>
        </div>
        <div className="flex items-center gap-4 w-fit">
          <span className="flex items-center gap-1">
            <div>Page</div>
            <strong>
              {table.getState().pagination.pageIndex + 1} of{" "}
              {table.getPageCount().toLocaleString()}
            </strong>
            <div>| Total: {table.getRowCount().toLocaleString()}</div>
          </span>
          <Button
            className="w-[200px]"
            disabled={!table.getCanNextPage()}
            onClick={() => table.nextPage()}
          >
            Next Page
          </Button>
        </div>
      </div>

      <table className="rounded-xl bg-mti-purple-ultralight/40 w-full">
        <thead>
          {table.getHeaderGroups().map((headerGroup) => (
            <tr key={headerGroup.id}>
              {headerGroup.headers.map((header) => (
                <th
                  className="py-4 px-4 text-left"
                  key={header.id}
                  colSpan={header.colSpan}
                >
                  <div
                    className={clsx(
                      header.column.getCanSort() &&
                        "cursor-pointer select-none",
                      "flex items-center gap-2"
                    )}
                    onClick={header.column.getToggleSortingHandler()}
                  >
                    {flexRender(
                      header.column.columnDef.header,
                      header.getContext()
                    )}
                    {{
                      asc: <BsArrowUp />,
                      desc: <BsArrowDown />,
                    }[header.column.getIsSorted() as string] ?? null}
                  </div>
                </th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody className="px-2 w-full">
          {table.getRowModel().rows.map((row) => (
            <tr
              className="odd:bg-white even:bg-mti-purple-ultralight/40 rounded-lg py-2"
              key={row.id}
            >
              {row.getVisibleCells().map((cell) => (
                <td className="px-4 py-2 items-center w-fit" key={cell.id}>
                  {flexRender(cell.column.columnDef.cell, cell.getContext())}
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
      {isLoading ? (
        <div className="min-h-screen flex justify-center items-start">
          <span className="loading loading-infinity w-32" />
        </div>
      ) : (
        rows.length === 0 && (
          <div className="w-full flex justify-center items-start">
            <span className="text-xl text-gray-500">No data found...</span>
          </div>
        )
      )}
    </div>
  );
}
