// data-table.tsx
"use client";

import * as React from "react";
import { Funnel, ChevronLeft, ChevronRight, SearchX } from "lucide-react";
import {
  ColumnDef,
  flexRender,
  getCoreRowModel,
  getSortedRowModel,
  getPaginationRowModel,
  getFilteredRowModel,
  useReactTable,
  SortingState,
  ColumnFiltersState,
  Table as TanstackTable,
} from "@tanstack/react-table";

import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";

import { PRIMARY_COLOR } from "@/lib/common";

const DEFAULT_PAGE_SIZE = 15;

interface DataTableProps<TData> {
  columns: ColumnDef<TData, any>[];
  data: TData[];
  pageSize?: number;
}

function useFilterVisibility(containerRef: React.RefObject<HTMLDivElement | null>) {
  const [visibleFilters, setVisibleFilters] = React.useState<Record<string, boolean>>({});

  const toggleFilter = React.useCallback((columnId: string) => {
    setVisibleFilters((prev) => {
      const isCurrentlyVisible = !!prev[columnId];
      return {
        ...Object.fromEntries(Object.keys(prev).map((key) => [key, false])),
        [columnId]: !isCurrentlyVisible,
      };
    });
  }, []);

  React.useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      const target = event.target as Node;
      if (containerRef.current && containerRef.current.contains(target)) return;
      setVisibleFilters({});
    };
    const handleScroll = () => setVisibleFilters({});

    document.addEventListener("click", handleClickOutside);
    window.addEventListener("scroll", handleScroll, { passive: true });
    return () => {
      document.removeEventListener("click", handleClickOutside);
      window.removeEventListener("scroll", handleScroll);
    };
  }, [containerRef]);

  return { visibleFilters, toggleFilter };
}

interface FilterInputProps {
  value: string;
  onChange: (value: string) => void;
}

function FilterInput({ value, onChange }: FilterInputProps) {
  return (
    <div
      className="absolute left-0 top-full z-20 mt-1.5 w-52 rounded-xl border border-slate-200 bg-white p-3 shadow-lg ring-1 ring-black/5"
      onClick={(e) => e.stopPropagation()}
    >
      <input
        autoFocus
        className="w-full rounded-lg border border-slate-200 bg-slate-50 px-2.5 py-1.5 text-xs text-slate-700 placeholder:text-slate-400 focus:border-[#428B4D] focus:bg-white focus:outline-none focus:ring-2 focus:ring-[#428B4D]/20"
        type="text"
        value={value}
        onClick={(e) => e.stopPropagation()}
        onChange={(e) => onChange(e.target.value)}
        placeholder="Filter…"
      />
    </div>
  );
}

interface PaginationProps<TData> {
  table: TanstackTable<TData>;
  totalRows: number;
}

function Pagination<TData>({ table, totalRows }: PaginationProps<TData>) {
  const { pageIndex, pageSize } = table.getState().pagination;
  const filteredCount = table.getFilteredRowModel().rows.length;
  const from = pageIndex * pageSize + 1;
  const to = Math.min((pageIndex + 1) * pageSize, filteredCount);
  const pageCount = table.getPageCount();

  return (
    <div className="flex items-center justify-between gap-3 px-1">
      <p className="text-[11px] text-slate-400 tabular-nums">
        {filteredCount > 0 ? (
          <>
            <span className="font-semibold text-slate-600">{from}–{to}</span>
            {" "}of{" "}
            <span className="font-semibold text-slate-600">{filteredCount}</span>
            {filteredCount !== totalRows && (
              <span className="text-slate-400"> (filtered from {totalRows})</span>
            )}
          </>
        ) : (
          "No results"
        )}
      </p>
      <div className="flex items-center gap-1.5">
        <button
          onClick={() => table.previousPage()}
          disabled={!table.getCanPreviousPage()}
          className="inline-flex h-7 w-7 items-center justify-center rounded-lg border border-slate-200 bg-white text-slate-500 shadow-sm transition-all hover:border-[#428B4D]/40 hover:text-[#428B4D] disabled:cursor-not-allowed disabled:opacity-40"
          aria-label="Previous page"
        >
          <ChevronLeft className="h-3.5 w-3.5" />
        </button>
        <span className="text-[11px] font-semibold tabular-nums text-slate-500">
          {pageIndex + 1} / {Math.max(pageCount, 1)}
        </span>
        <button
          onClick={() => table.nextPage()}
          disabled={!table.getCanNextPage()}
          className="inline-flex h-7 w-7 items-center justify-center rounded-lg border border-slate-200 bg-white text-slate-500 shadow-sm transition-all hover:border-[#428B4D]/40 hover:text-[#428B4D] disabled:cursor-not-allowed disabled:opacity-40"
          aria-label="Next page"
        >
          <ChevronRight className="h-3.5 w-3.5" />
        </button>
      </div>
    </div>
  );
}

export function DataTable<TData>({ columns, data, pageSize = DEFAULT_PAGE_SIZE }: DataTableProps<TData>) {
  const [sorting, setSorting] = React.useState<SortingState>([]);
  const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]);
  const containerRef = React.useRef<HTMLDivElement | null>(null);
  const { visibleFilters, toggleFilter } = useFilterVisibility(containerRef);

  const table = useReactTable({
    data,
    columns,
    state: { sorting, columnFilters },
    onSortingChange: setSorting,
    onColumnFiltersChange: setColumnFilters,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    initialState: { pagination: { pageSize } },
  });

  const rows = table.getRowModel().rows;

  return (
    <div ref={containerRef} className="flex flex-col gap-3">
      {/* Table */}
      <div className="overflow-hidden rounded-2xl border border-slate-200/80 bg-white shadow-sm">
        <div className="overflow-x-auto">
          <Table className="min-w-full text-sm">
            <TableHeader>
              {table.getHeaderGroups().map((headerGroup) => (
                <TableRow key={headerGroup.id} className="border-b border-slate-100 bg-slate-50/70 hover:bg-slate-50/70">
                  {headerGroup.headers.map((header) => {
                    const columnId = header.column.id;
                    const showFilter = visibleFilters[columnId];
                    const isFiltered = !!header.column.getFilterValue();

                    return (
                      <TableHead
                        key={header.id}
                        className="px-4 py-3 text-left select-none"
                        onClick={() => toggleFilter(columnId)}
                      >
                        {header.isPlaceholder ? null : (
                          <div className="relative flex items-center justify-between gap-2 cursor-pointer">
                            <span className="text-[10px] font-semibold uppercase tracking-widest text-slate-500 truncate">
                              {flexRender(header.column.columnDef.header, header.getContext())}
                            </span>
                            {header.column.getCanFilter() && (
                              <Funnel
                                className={`h-3 w-3 flex-shrink-0 transition-colors ${
                                  isFiltered ? "text-[#428B4D]" : "text-slate-300 hover:text-[#428B4D]"
                                }`}
                                onClick={(e) => { e.stopPropagation(); toggleFilter(columnId); }}
                              />
                            )}
                            {header.column.getCanFilter() && showFilter && (
                              <FilterInput
                                value={(header.column.getFilterValue() ?? "") as string}
                                onChange={(value) => header.column.setFilterValue(value)}
                              />
                            )}
                          </div>
                        )}
                      </TableHead>
                    );
                  })}
                </TableRow>
              ))}
            </TableHeader>

            <TableBody>
              {rows.length > 0 ? (
                rows.map((row, rowIndex) => (
                  <TableRow
                    key={row.id}
                    className={`border-b border-slate-50 transition-colors last:border-0 ${
                      rowIndex % 2 === 0 ? "bg-white" : "bg-slate-50/40"
                    } hover:bg-[#428B4D]/5`}
                  >
                    {row.getVisibleCells().map((cell) => (
                      <TableCell key={cell.id} className="px-4 py-2.5 text-xs text-slate-700">
                        {flexRender(cell.column.columnDef.cell, cell.getContext())}
                      </TableCell>
                    ))}
                  </TableRow>
                ))
              ) : (
                <TableRow>
                  <TableCell colSpan={columns.length} className="h-40 text-center">
                    <div className="flex flex-col items-center justify-center gap-2 text-slate-400">
                      <SearchX className="h-8 w-8 opacity-40" />
                      <p className="text-sm font-medium">No results found</p>
                      <p className="text-xs">Try adjusting your filters</p>
                    </div>
                  </TableCell>
                </TableRow>
              )}
            </TableBody>
          </Table>
        </div>
      </div>

      {/* Pagination */}
      <Pagination table={table} totalRows={data.length} />
    </div>
  );
}
