"use client";

import { useMemo, useState } from "react";
import {
  useReactTable,
  getCoreRowModel,
  getFilteredRowModel,
  getSortedRowModel,
  getPaginationRowModel,
  flexRender,
  type SortingState,
  type VisibilityState,
  type PaginationState,
} from "@tanstack/react-table";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/app/shadcn_components/ui/table";
import { Input } from "@/app/shadcn_components/ui/input";
import {
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/app/shadcn_components/ui/dropdown-menu";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
} from "@/app/shadcn_components/ui/select";
import { Search, SlidersHorizontal, ChevronLeft, ChevronRight, Download } from "lucide-react";
import { createPropertyTableColumns } from "./PropertyTableColumns";
import { STAGE_ORDER } from "./types";
import type { ClassifiedDeal, DocStatusMap, RemovalStatusByDeal, EffectiveRemovalState } from "./types";

// Human-readable labels for toggle dropdown
const COLUMN_LABELS: Record<string, string> = {
  landlordPropertyId: "Property Ref",
  uprn: "UPRN",
  projectCode: "Project",
  coordinator: "Coordinator",
  designer: "Designer",
  installer: "Installer",
  proposedMeasures: "Proposed Measures",
  approvedPackage: "Approved Package",
  actualMeasuresInstalled: "Installed Measures",
  preSapScore: "Pre-SAP",
  eiScore: "EI Score",
  eiScorePotential: "EI Score (Potential)",
  epcSapScore: "EPC SAP Score",
  epcSapScorePotential: "EPC SAP (Potential)",
  lodgementStatus: "Lodgement Status",
  designDate: "Design Date",
  fullLodgementDate: "Lodgement Date",
};

type DocFilter = "all" | "has_docs" | "incomplete" | "none";
type RemovalFilter = "all" | "pending_removal" | "removed" | "pending_re_addition";

interface PropertyTableProps {
  data: ClassifiedDeal[];
  onOpenDrawer: (dealId: string, uprn: string | null, landlordPropertyId: string | null, dealname: string | null) => void;
  onOpenDetail?: (deal: ClassifiedDeal) => void;
  showDocuments?: boolean;
  docStatusMap?: DocStatusMap;
  removalStatusByDeal?: RemovalStatusByDeal;
}

const CSV_FIELDS: { key: keyof ClassifiedDeal; label: string }[] = [
  { key: "dealname", label: "Address" },
  { key: "landlordPropertyId", label: "Property Ref" },
  { key: "uprn", label: "UPRN" },
  { key: "displayStage", label: "Stage" },
  { key: "projectCode", label: "Project" },
  { key: "coordinator", label: "Coordinator" },
  { key: "designer", label: "Designer" },
  { key: "installer", label: "Installer" },
  { key: "proposedMeasures", label: "Proposed Measures" },
  { key: "approvedPackage", label: "Approved Package" },
  { key: "actualMeasuresInstalled", label: "Installed Measures" },
  { key: "preSapScore", label: "Pre-SAP" },
  { key: "eiScore", label: "EI Score" },
  { key: "eiScorePotential", label: "EI Score (Potential)" },
  { key: "epcSapScore", label: "EPC SAP Score" },
  { key: "epcSapScorePotential", label: "EPC SAP (Potential)" },
  { key: "lodgementStatus", label: "Lodgement Status" },
  { key: "designDate", label: "Design Date" },
  { key: "fullLodgementDate", label: "Lodgement Date" },
];

function escapeCell(value: unknown): string {
  if (value === null || value === undefined) return "";
  const str =
    value instanceof Date
      ? value.toLocaleDateString("en-GB")
      : String(value);
  return str.includes(",") || str.includes('"') || str.includes("\n")
    ? `"${str.replace(/"/g, '""')}"`
    : str;
}

export default function PropertyTable({ data, onOpenDrawer, onOpenDetail, showDocuments = false, docStatusMap = {}, removalStatusByDeal = {} }: PropertyTableProps) {
  const [globalFilter, setGlobalFilter] = useState("");
  const [stageFilter, setStageFilter] = useState<string>("all");
  const [docFilter, setDocFilter] = useState<DocFilter>("all");
  const [removalFilter, setRemovalFilter] = useState<RemovalFilter>("all");
  const [sorting, setSorting] = useState<SortingState>([]);
  const [pagination, setPagination] = useState<PaginationState>({
    pageIndex: 0,
    pageSize: 25,
  });
  const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({
    designer: false,
    installer: false,
    proposedMeasures: false,
    approvedPackage: false,
    actualMeasuresInstalled: false,
    preSapScore: false,
    eiScore: false,
    eiScorePotential: false,
    epcSapScore: false,
    epcSapScorePotential: false,
    lodgementStatus: false,
    designDate: false,
    fullLodgementDate: false,
  });

  // Pre-filter by stage, doc status, and removal status before TanStack gets it
  const filteredData = useMemo(() => {
    let result = data;
    if (stageFilter !== "all") {
      result = result.filter((d) => d.displayStage === stageFilter);
    }
    if (docFilter !== "all") {
      result = result.filter((d) => {
        const status = docStatusMap[d.dealId];
        if (docFilter === "none") return !status || !status.hasSurveyDocs;
        if (docFilter === "has_docs") return !!status?.hasSurveyDocs;
        if (docFilter === "incomplete") return !!status?.hasSurveyDocs && !status.isSurveyComplete;
        return true;
      });
    }
    if (removalFilter !== "all") {
      result = result.filter((d) => {
        const state: EffectiveRemovalState = (d.dealId ? removalStatusByDeal[d.dealId] : undefined) ?? "none";
        return state === removalFilter;
      });
    }
    return result;
  }, [data, stageFilter, docFilter, docStatusMap, removalFilter, removalStatusByDeal]);

  const columns = useMemo(
    () => createPropertyTableColumns(onOpenDrawer, showDocuments, docStatusMap, onOpenDetail, removalStatusByDeal),
    [onOpenDrawer, showDocuments, docStatusMap, onOpenDetail, removalStatusByDeal]
  );

  const table = useReactTable({
    data: filteredData,
    columns,
    state: {
      globalFilter,
      sorting,
      pagination,
      columnVisibility,
    },
    onGlobalFilterChange: setGlobalFilter,
    onSortingChange: setSorting,
    onPaginationChange: setPagination,
    onColumnVisibilityChange: setColumnVisibility,
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    globalFilterFn: "includesString",
  });

  const downloadCsv = () => {
    const rows = table.getFilteredRowModel().rows;
    const header = CSV_FIELDS.map((f) => f.label).join(",");
    const body = rows
      .map((row) =>
        CSV_FIELDS.map((f) => escapeCell(row.original[f.key])).join(",")
      )
      .join("\n");
    const blob = new Blob([header + "\n" + body], { type: "text/csv;charset=utf-8;" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "properties.csv";
    a.click();
    URL.revokeObjectURL(url);
  };

  const toggleableColumns = table
    .getAllColumns()
    .filter((col) => col.getCanHide() && COLUMN_LABELS[col.id]);

  const pageCount = table.getPageCount();
  const currentPage = table.getState().pagination.pageIndex + 1;
  const totalFiltered = table.getFilteredRowModel().rows.length;

  return (
    <div className="space-y-3">
      {/* Toolbar */}
      <div className="flex flex-col sm:flex-row gap-3 items-start sm:items-center">
        {/* Search */}
        <div className="relative flex-1 min-w-0">
          <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400 pointer-events-none" />
          <Input
            value={globalFilter}
            onChange={(e) => {
              setGlobalFilter(e.target.value);
              setPagination((p) => ({ ...p, pageIndex: 0 }));
            }}
            placeholder="Search address, UPRN, coordinator…"
            className="pl-9 h-9 text-sm border-gray-200 focus:border-brandblue/40 focus:ring-brandblue/20"
          />
        </div>

        {/* Stage filter */}
        <Select
          value={stageFilter}
          onValueChange={(v) => {
            setStageFilter(v);
            setPagination((p) => ({ ...p, pageIndex: 0 }));
          }}
        >
          <SelectTrigger className="h-9 w-[180px] text-sm border-gray-200 shrink-0">
            {stageFilter === "all"
              ? "All stages"
              : stageFilter}
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="all">All stages</SelectItem>
            {STAGE_ORDER.map((stage) => (
              <SelectItem key={stage} value={stage}>
                {stage}
              </SelectItem>
            ))}
            <SelectItem value="Queries">Queries</SelectItem>
          </SelectContent>
        </Select>

        {/* Removal status filter */}
        <Select
          value={removalFilter}
          onValueChange={(v) => {
            setRemovalFilter(v as RemovalFilter);
            setPagination((p) => ({ ...p, pageIndex: 0 }));
          }}
        >
          <SelectTrigger className="h-9 w-[180px] text-sm border-gray-200 shrink-0">
            {removalFilter === "all"
              ? "All properties"
              : removalFilter === "pending_removal"
                ? "Pending removal"
                : removalFilter === "removed"
                  ? "Removed"
                  : "Pending re-addition"}
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="all">All properties</SelectItem>
            <SelectItem value="pending_removal">Pending removal</SelectItem>
            <SelectItem value="removed">Removed</SelectItem>
            <SelectItem value="pending_re_addition">Pending re-addition</SelectItem>
          </SelectContent>
        </Select>

        {/* Docs filter */}
        {showDocuments && (
          <Select
            value={docFilter}
            onValueChange={(v) => {
              setDocFilter(v as DocFilter);
              setPagination((p) => ({ ...p, pageIndex: 0 }));
            }}
          >
            <SelectTrigger className="h-9 w-[160px] text-sm border-gray-200 shrink-0">
              {docFilter === "all"
                ? "All docs"
                : docFilter === "has_docs"
                  ? "Has docs"
                  : docFilter === "incomplete"
                    ? "Incomplete docs"
                    : "No docs"}
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="all">All docs</SelectItem>
              <SelectItem value="has_docs">Has docs</SelectItem>
              <SelectItem value="incomplete">Incomplete docs</SelectItem>
              <SelectItem value="none">No docs</SelectItem>
            </SelectContent>
          </Select>
        )}

        {/* Download CSV */}
        <button
          onClick={downloadCsv}
          className="inline-flex items-center gap-2 h-9 px-3 rounded-lg border border-gray-200 bg-white text-sm font-medium text-gray-600 hover:border-brandblue/30 hover:text-brandblue transition-colors shrink-0"
        >
          <Download className="h-3.5 w-3.5" />
          CSV
        </button>

        {/* Column visibility */}
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <button className="inline-flex items-center gap-2 h-9 px-3 rounded-lg border border-gray-200 bg-white text-sm font-medium text-gray-600 hover:border-brandblue/30 hover:text-brandblue transition-colors shrink-0">
              <SlidersHorizontal className="h-3.5 w-3.5" />
              Columns
            </button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end" className="w-52">
            <DropdownMenuLabel className="text-xs text-gray-500 sticky top-0 bg-white z-10">
              Toggle columns
            </DropdownMenuLabel>
            <DropdownMenuSeparator />
            <div className="relative">
              <div className="max-h-72 overflow-y-auto">
                {toggleableColumns.map((col) => (
                  <DropdownMenuCheckboxItem
                    key={col.id}
                    checked={col.getIsVisible()}
                    onCheckedChange={(val) => col.toggleVisibility(val)}
                    className="text-sm"
                  >
                    {COLUMN_LABELS[col.id] ?? col.id}
                  </DropdownMenuCheckboxItem>
                ))}
              </div>
              <div className="pointer-events-none absolute bottom-0 left-0 right-0 h-8 bg-gradient-to-t from-white to-transparent" />
            </div>
          </DropdownMenuContent>
        </DropdownMenu>
      </div>

      {/* Result count */}
      <p className="text-xs text-gray-400">
        Showing{" "}
        <span className="font-semibold text-gray-600">
          {Math.min(
            table.getState().pagination.pageSize,
            totalFiltered - table.getState().pagination.pageIndex * table.getState().pagination.pageSize
          )}
        </span>{" "}
        of{" "}
        <span className="font-semibold text-gray-600">{totalFiltered}</span>{" "}
        {stageFilter !== "all" ? `"${stageFilter}" ` : ""}
        {docFilter !== "all" ? `(${docFilter === "has_docs" ? "has docs" : docFilter === "incomplete" ? "incomplete docs" : "no docs"}) ` : ""}
        propert{totalFiltered === 1 ? "y" : "ies"}
      </p>

      {/* Table */}
      <div className="rounded-xl border border-gray-200 overflow-hidden shadow-sm">
        <div className="overflow-x-auto">
          <Table>
            <TableHeader>
              {table.getHeaderGroups().map((headerGroup) => (
                <TableRow
                  key={headerGroup.id}
                  className="bg-gray-50/80 hover:bg-gray-50/80 border-b border-gray-200"
                >
                  {headerGroup.headers.map((header) => (
                    <TableHead
                      key={header.id}
                      className="h-10 px-4 first:pl-5 last:pr-5"
                    >
                      {header.isPlaceholder
                        ? null
                        : flexRender(
                            header.column.columnDef.header,
                            header.getContext()
                          )}
                    </TableHead>
                  ))}
                </TableRow>
              ))}
            </TableHeader>
            <TableBody>
              {table.getRowModel().rows.length ? (
                table.getRowModel().rows.map((row, i) => (
                  <TableRow
                    key={row.id}
                    className={`border-b border-gray-100 transition-colors hover:bg-brandlightblue/10 ${
                      i % 2 === 0 ? "bg-white" : "bg-gray-50/30"
                    }`}
                  >
                    {row.getVisibleCells().map((cell) => (
                      <TableCell
                        key={cell.id}
                        className="py-3 px-4 first:pl-5 last:pr-5"
                      >
                        {flexRender(
                          cell.column.columnDef.cell,
                          cell.getContext()
                        )}
                      </TableCell>
                    ))}
                  </TableRow>
                ))
              ) : (
                <TableRow>
                  <TableCell
                    colSpan={columns.length}
                    className="h-32 text-center text-sm text-gray-400"
                  >
                    No properties match the current filters.
                  </TableCell>
                </TableRow>
              )}
            </TableBody>
          </Table>
        </div>
      </div>

      {/* Pagination */}
      {pageCount > 1 && (
        <div className="flex items-center justify-between pt-1">
          <div className="flex items-center gap-2">
            <span className="text-xs text-gray-500">Rows per page:</span>
            <Select
              value={String(table.getState().pagination.pageSize)}
              onValueChange={(v) =>
                table.setPageSize(Number(v))
              }
            >
              <SelectTrigger className="h-7 w-16 text-xs border-gray-200">
                {table.getState().pagination.pageSize}
              </SelectTrigger>
              <SelectContent>
                {[10, 25, 50, 100].map((n) => (
                  <SelectItem key={n} value={String(n)} className="text-xs">
                    {n}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          <div className="flex items-center gap-3">
            <span className="text-xs text-gray-500">
              Page {currentPage} of {pageCount}
            </span>
            <div className="flex gap-1">
              <button
                onClick={() => table.previousPage()}
                disabled={!table.getCanPreviousPage()}
                className="h-7 w-7 flex items-center justify-center rounded-lg border border-gray-200 text-gray-500 hover:border-brandblue/30 hover:text-brandblue disabled:opacity-30 disabled:cursor-not-allowed transition-colors"
              >
                <ChevronLeft className="h-3.5 w-3.5" />
              </button>
              <button
                onClick={() => table.nextPage()}
                disabled={!table.getCanNextPage()}
                className="h-7 w-7 flex items-center justify-center rounded-lg border border-gray-200 text-gray-500 hover:border-brandblue/30 hover:text-brandblue disabled:opacity-30 disabled:cursor-not-allowed transition-colors"
              >
                <ChevronRight className="h-3.5 w-3.5" />
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
