"use client";

import * as React from "react";

import {
  getCoreRowModel,
  useReactTable,
  type Header,
} from "@tanstack/react-table";

import {
  DataTablePagination,
  DataTableShell,
  useServerPagination,
  type ServerPaginationMeta,
} from "@/app/dashboard/_components/data-table";
import { useMasterListFilters } from "@/hooks/use-master-list-filters";
import { useDebouncedValue } from "@/hooks/use-debounced-value";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { TableCell } from "@/components/ui/table";

import { businessTypeColumns } from "./columns";
import {
  type BusinessTypeFilters,
  type BusinessTypeRow,
} from "./schema";
import { exportBusinessTypesCsv } from "./export-csv";

type Props = {
  data: BusinessTypeRow[];
  initialFilters: BusinessTypeFilters;
  pagination: ServerPaginationMeta;
};

type TextDrafts = Pick<BusinessTypeFilters, "name">;

export function BusinessTypesTable({
  data,
  initialFilters,
  pagination: serverPagination,
}: Props) {
  const { filters, setFilter } = useMasterListFilters(initialFilters, ["name"] as const);
  const [drafts, setDrafts] = React.useState<TextDrafts>({ name: filters.name });
  const committedTextRef = React.useRef<TextDrafts>({ name: filters.name });
  const { pagination, onPaginationChange, totalCount } = useServerPagination(serverPagination);
  const debouncedName = useDebouncedValue(drafts.name, 300);

  React.useEffect(() => {
    setDrafts((draft) => ({
      name:
        draft.name === committedTextRef.current.name || draft.name === filters.name
          ? filters.name
          : draft.name,
    }));
    committedTextRef.current = {
      name: filters.name,
    };
  }, [filters.name]);

  React.useEffect(() => {
    if (debouncedName !== filters.name) {
      setFilter("name", debouncedName);
    }
  }, [debouncedName, filters.name, setFilter]);

  const table = useReactTable({
    data,
    columns: businessTypeColumns,
    state: { pagination },
    onPaginationChange,
    manualPagination: true,
    pageCount: serverPagination.pageCount,
    rowCount: totalCount,
    getCoreRowModel: getCoreRowModel(),
    getRowId: (row) => String(row.id),
  });

  const updateDraft = (value: string) => {
    setDrafts({ name: value });
  };

  return (
    <div className="space-y-4">
      <div className="flex justify-end">
        <Button
          type="button"
          variant="secondary"
          size="sm"
          onClick={() => exportBusinessTypesCsv(data)}
        >
          Export filtered
        </Button>
      </div>

      <DataTableShell
        table={table}
        columnCount={businessTypeColumns.length}
        emptyMessage="No business types match your filters."
        renderFilterCell={(header) => renderFilterCell(header, drafts.name, updateDraft)}
      />

      <DataTablePagination
        table={table}
        totalRows={totalCount}
        itemNoun="business type"
        idPrefix="business-types"
      />
    </div>
  );
}

function renderFilterCell(
  header: Header<BusinessTypeRow, unknown>,
  name: string,
  updateDraft: (value: string) => void,
) {
  if (header.column.id !== "name") {
    return null;
  }

  return (
    <TableCell key={header.id} className="p-2">
      <Input
        value={name}
        onChange={(event) => updateDraft(event.target.value)}
        placeholder="Name"
        className="h-8 bg-background text-xs"
      />
    </TableCell>
  );
}
