import { keepPreviousData, useQuery } from "@tanstack/react-query";
import {
  ColumnFiltersState,
  createColumnHelper,
  flexRender,
  getCoreRowModel,
  PaginationState,
  useReactTable,
} from "@tanstack/react-table";
import { useState } from "react";
import { DebounceInput } from "react-debounce-input";

const PageSize = 30;

async function loader(page = 0, category: string | undefined = "") {
  const url = new URL("http://localhost:9000/transactions");
  url.search = new URLSearchParams({
    limit: String(PageSize),
    offset: String(page * PageSize),
    ...(category !== "" && { category: category }),
  }).toString();

  return await fetch(url).then((response) => response.json());
}

type Transaction = {
  id: number;
  date: string;
  description: string;
  value: number;
  category: string;
};

const columnHelper = createColumnHelper<Transaction>();

const columns = [
  columnHelper.accessor("date", {
    enableColumnFilter: false,
  }),
  columnHelper.accessor("description", {
    enableColumnFilter: false,
  }),
  columnHelper.accessor("value", {
    enableColumnFilter: false,
  }),
  columnHelper.accessor("category", {}),
];

export default function Transactions() {
  const [pagination, setPagination] = useState<PaginationState>({
    pageIndex: 0,
    pageSize: PageSize,
  });
  const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([
    {
      id: "category",
      value: "",
    },
  ]);

  const { data, isPending, isError } = useQuery({
    queryKey: ["transactions", pagination.pageIndex, columnFilters],
    queryFn: () =>
      loader(
        pagination.pageIndex,
        columnFilters.find((filter) => filter.id == "category")!.value as string
      ),
    placeholderData: keepPreviousData,
  });

  const table = useReactTable({
    columns,
    data,
    getCoreRowModel: getCoreRowModel(),
    manualPagination: true,
    manualFiltering: true,
    // rowCount: , // TODO: get this from the server
    pageCount: -1,
    onPaginationChange: setPagination,
    onColumnFiltersChange: setColumnFilters,
    state: {
      pagination,
      columnFilters,
    },
  });

  if (isPending) {
    return <div>Loading...</div>;
  }

  if (isError) {
    return <div>Error loading transactions</div>;
  }

  return (
    <>
      <table>
        <thead>
          {table.getHeaderGroups().map((headerGroup) => (
            <tr key={headerGroup.id}>
              {headerGroup.headers.map((header) => (
                <th key={header.id}>
                  {header.isPlaceholder ? null : (
                    <>
                      {flexRender(
                        header.column.columnDef.header,
                        header.getContext()
                      )}
                      {header.column.getCanFilter() ? (
                        <div>
                          <DebounceInput
                            debounceTimeout={275}
                            onChange={(e) =>
                              header.column.setFilterValue(e.target.value)
                            }
                          />
                        </div>
                      ) : null}
                    </>
                  )}
                </th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody>
          {table.getRowModel().rows.map((row) => (
            <tr key={row.id}>
              {row.getVisibleCells().map((cell) => (
                <td key={cell.id}>
                  {flexRender(cell.column.columnDef.cell, cell.getContext())}
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
      <div>
        <button
          onClick={() => table.firstPage()}
          disabled={!table.getCanPreviousPage()}
        >
          First
        </button>
        <button
          onClick={() => table.previousPage()}
          disabled={!table.getCanPreviousPage()}
        >
          Previous
        </button>
        <button
          onClick={() => table.nextPage()}
          disabled={!table.getCanNextPage()}
        >
          Next
        </button>
        <button
          onClick={() => table.lastPage()}
          disabled={!table.getCanNextPage()}
        >
          Last
        </button>
      </div>
      <div>Page {table.getState().pagination.pageIndex + 1}</div>
    </>
  );
}
