"use client";

import { useMemo, useState } from "react";
import { useMutation } from "@tanstack/react-query";
import {
  useReactTable,
  getCoreRowModel,
  getFilteredRowModel,
  getSortedRowModel,
  getPaginationRowModel,
  flexRender,
  type SortingState,
  type PaginationState,
  type ColumnDef,
} 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 {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/app/shadcn_components/ui/popover";
import { Search, Download, ChevronLeft, ChevronRight, ChevronDown } from "lucide-react";
import type { ClassifiedDeal, HubspotDeal } from "./types";

const NO_COMMENT_PLACEHOLDER =
  "Damp & mould discovered — no note from coordinator";
const COMMENT_PREVIEW_LIMIT = 60;

function DampMouldBadgeCell({ value }: { value: unknown }) {
  const isYes =
    typeof value === "string" && value.trim().toLowerCase() === "yes";

  if (!isYes) return null;

  return (
    <span className="inline-flex items-center gap-1 rounded-full bg-red-100 px-2 py-0.5 text-xs font-semibold text-red-700 border border-red-200">
      Damp & Mould
    </span>
  );
}

function RemovalFlagChip({ label, tooltip }: { label: string; tooltip: string }) {
  return (
    <span
      title={tooltip}
      className="inline-flex items-center rounded-full bg-slate-100 px-2 py-0.5 text-[10px] font-semibold text-slate-600 border border-slate-200 cursor-help"
    >
      {label}
    </span>
  );
}

function DealNameCell({ deal }: { deal: ClassifiedDeal }) {
  const name = deal.dealname;
  const isRemovedFromProgram = deal.batch === "Removed from Program";

  return (
    <div className="flex items-center gap-2 flex-wrap">
      <span className="text-sm text-gray-800">
        {name ?? <span className="text-gray-300">—</span>}
      </span>
      {isRemovedFromProgram && (
        <RemovalFlagChip
          label="Removed from Program"
          tooltip="This property has been removed from the project. If an outcome is set above, it is real history; no further action expected."
        />
      )}
    </div>
  );
}

function DampMouldCommentCell({ value }: { value: unknown }) {
  const comment = typeof value === "string" ? value.trim() : "";

  if (!comment) {
    return (
      <span className="text-sm italic text-gray-500">
        {NO_COMMENT_PLACEHOLDER}
      </span>
    );
  }

  const preview =
    comment.length > COMMENT_PREVIEW_LIMIT
      ? comment.slice(0, COMMENT_PREVIEW_LIMIT).trimEnd() + "…"
      : comment;

  return (
    <Popover>
      <PopoverTrigger asChild>
        <button
          type="button"
          className="group inline-flex items-center gap-1 text-left text-sm text-gray-800 hover:text-brandblue underline-offset-2 hover:underline focus:outline-none focus:underline"
        >
          <span>{preview}</span>
          <ChevronDown className="h-3.5 w-3.5 shrink-0 text-gray-400 group-hover:text-brandblue" />
        </button>
      </PopoverTrigger>
      <PopoverContent
        align="start"
        className="w-80 max-w-[90vw] whitespace-pre-wrap break-words text-sm text-gray-800"
      >
        {comment}
      </PopoverContent>
    </Popover>
  );
}

interface DrillDownTableProps {
  data: ClassifiedDeal[];
  columns?: (keyof HubspotDeal)[];
  columnLabels?: Partial<Record<keyof HubspotDeal, string>>;
}

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;
}

function PhotoDownloadButton({ url }: { url: string }) {
  const { mutate: download, isPending } = useMutation({
    mutationFn: async () => {
      const key = url.split(".amazonaws.com/")[1];
      if (!key) throw new Error("Invalid S3 key");
      const res = await fetch("/api/sign-s3-url", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ key }),
      });
      if (!res.ok) throw new Error("Failed to get signed URL");
      const data = await res.json();
      return data.url as string;
    },
    onSuccess: (signedUrl) => {
      window.open(signedUrl, "_blank");
    },
  });

  return (
    <button
      onClick={() => download()}
      disabled={isPending}
      className="flex items-center gap-1.5 px-2.5 py-1.5 bg-brandblue/5 text-brandblue text-xs font-medium rounded-lg hover:bg-brandblue/10 border border-brandblue/20 hover:border-brandblue/40 transition-all duration-150 active:scale-95 disabled:opacity-60 disabled:cursor-not-allowed"
    >
      <Download className="w-3.5 h-3.5" />
      {isPending ? "Preparing…" : "Download"}
    </button>
  );
}

function PhotoDownloadCell({ value }: { value: unknown }) {
  let urls: string[] = [];

  if (typeof value === "string") {
    try {
      const parsed = JSON.parse(value);
      urls = Array.isArray(parsed) ? parsed : [value];
    } catch {
      urls = value.split(/[\s,]+/).filter((u) => u.startsWith("http"));
    }
  } else if (Array.isArray(value)) {
    urls = value as string[];
  }

  if (urls.length === 0) return <span className="text-gray-400 text-xs">No photos</span>;

  return (
    <div className="flex flex-wrap gap-1.5">
      {urls.map((url, idx) => (
        <PhotoDownloadButton key={idx} url={url} />
      ))}
    </div>
  );
}

export default function DrillDownTable({
  data,
  columns: columnKeys,
  columnLabels,
}: DrillDownTableProps) {
  const [globalFilter, setGlobalFilter] = useState("");
  const [sorting, setSorting] = useState<SortingState>([]);
  const [pagination, setPagination] = useState<PaginationState>({
    pageIndex: 0,
    pageSize: 25,
  });

  const visibleKeys: (keyof HubspotDeal)[] = columnKeys?.length
    ? columnKeys
    : (Object.keys(data?.[0] || {}) as (keyof HubspotDeal)[]);

  const columns = useMemo<ColumnDef<ClassifiedDeal>[]>(
    () =>
      visibleKeys.map((key) => ({
        accessorKey: key as string,
        id: key as string,
        header: () => (
          <span className="text-xs font-semibold uppercase tracking-wide text-gray-500">
            {columnLabels?.[key] ?? (key as string)}
          </span>
        ),
        cell: ({ row }) => {
          const value = row.original[key as keyof ClassifiedDeal];
          if (key === "dealname") {
            return <DealNameCell deal={row.original} />;
          }
          if (key === "majorConditionIssuePhotosS3") {
            return <PhotoDownloadCell value={value} />;
          }
          if (key === "dampMouldAndRepairComments") {
            return <DampMouldCommentCell value={value} />;
          }
          if (key === "dampMouldFlag") {
            return <DampMouldBadgeCell value={value} />;
          }
          return (
            <span className="text-sm text-gray-800">
              {value != null ? String(value) : (
                <span className="text-gray-300">—</span>
              )}
            </span>
          );
        },
      })),
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [visibleKeys.join(","), columnLabels],
  );

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

  const downloadCsv = () => {
    const rows = table.getFilteredRowModel().rows;
    const exportKeys = visibleKeys.filter((k) => k !== "majorConditionIssuePhotosS3");
    const header = exportKeys
      .map((k) => columnLabels?.[k] ?? (k as string))
      .join(",");
    const body = rows
      .map((row) =>
        exportKeys.map((k) => escapeCell(row.original[k as keyof ClassifiedDeal])).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 = "data.csv";
    a.click();
    URL.revokeObjectURL(url);
  };

  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 gap-3 items-center">
        <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…"
            className="pl-9 h-9 text-sm border-gray-200 focus:border-brandblue/40 focus:ring-brandblue/20"
          />
        </div>
        <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>
      </div>

      {/* Row count */}
      <p className="text-xs text-gray-400">
        Showing{" "}
        <span className="font-semibold text-gray-600">{totalFiltered}</span>{" "}
        {totalFiltered === 1 ? "row" : "rows"}
      </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-24 text-center text-sm text-gray-400"
                  >
                    No results found.
                  </TableCell>
                </TableRow>
              )}
            </TableBody>
          </Table>
        </div>
      </div>

      {/* Pagination */}
      {pageCount > 1 && (
        <div className="flex items-center justify-between pt-1">
          <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>
  );
}
