"use client";

import React, { useMemo, useState, useTransition } from "react";
import { useRouter } from "next/navigation";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/app/shadcn_components/ui/table";
import { Input } from "@/app/shadcn_components/ui/input";
import { Badge } from "@/app/shadcn_components/ui/badge";
import { Button } from "@/app/shadcn_components/ui/button";
import { Checkbox } from "@/app/shadcn_components/ui/checkbox";
import { Search, CheckSquare, ListChecks, Loader2, X, Layers } from "lucide-react";
import { STAGE_COLORS } from "./types";
import type { ClassifiedDeal, ApprovalsByDeal } from "./types";
import { parseMeasures } from "@/app/lib/parseMeasures";
import { filterMeasureRows } from "./measureFilters";
import { MEASURE_NAMES } from "@/app/lib/measureDocumentRequirements";

type Mode = "chip-click" | "instruct";

type Props = {
  data: ClassifiedDeal[];
  approvalsByDeal: ApprovalsByDeal;
  instructedMeasuresByDeal: Record<string, string[]>;
  portfolioId: string;
  isApprover: boolean;
};

// ── Approval status badge ────────────────────────────────────────────────────

function ApprovalStatus({ proposed, approved }: { proposed: string[]; approved: string[] }) {
  if (proposed.length === 0) return null;
  const approvedSet = new Set(approved);
  const approvedCount = proposed.filter((m) => approvedSet.has(m)).length;

  if (approvedCount === 0) {
    return (
      <Badge className="bg-amber-50 text-amber-700 border border-amber-200 text-xs">
        Pending
      </Badge>
    );
  }
  if (approvedCount === proposed.length) {
    return (
      <Badge className="bg-emerald-50 text-emerald-700 border border-emerald-200 text-xs">
        Fully Approved
      </Badge>
    );
  }
  return (
    <Badge className="bg-blue-50 text-blue-700 border border-blue-200 text-xs">
      {approvedCount}/{proposed.length} Approved
    </Badge>
  );
}

// ── Bulk approve modal ───────────────────────────────────────────────────────

type BulkApproveModalProps = {
  selected: Array<{ dealId: string; dealname: string | null; measureName: string }>;
  portfolioId: string;
  onClose: () => void;
  onSuccess: () => void;
};

function BulkApproveModal({ selected, portfolioId, onClose, onSuccess }: BulkApproveModalProps) {
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const groupedByDeal = useMemo(() => {
    const map = new Map<string, { dealname: string | null; measures: string[] }>();
    for (const item of selected) {
      const existing = map.get(item.dealId);
      if (existing) {
        existing.measures.push(item.measureName);
      } else {
        map.set(item.dealId, { dealname: item.dealname, measures: [item.measureName] });
      }
    }
    return map;
  }, [selected]);

  async function handleConfirm() {
    setSubmitting(true);
    setError(null);
    try {
      const res = await fetch(`/api/portfolio/${portfolioId}/bulk-approvals`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          changes: selected.map((s) => ({
            hubspotDealId: s.dealId,
            measureName: s.measureName,
            approved: true,
          })),
        }),
      });
      const data = await res.json();
      if (!res.ok || !data.ok) {
        setError(data.error ?? "Failed to approve measures");
        return;
      }
      onSuccess();
    } catch {
      setError("Network error — please try again");
    } finally {
      setSubmitting(false);
    }
  }

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-sm">
      <div className="bg-white rounded-2xl shadow-2xl w-full max-w-lg mx-4 p-6 space-y-4">
        <div className="flex items-center justify-between">
          <h2 className="text-base font-semibold text-gray-800">Confirm bulk approval</h2>
          <button onClick={onClose} className="text-gray-400 hover:text-gray-600">
            <X className="h-4 w-4" />
          </button>
        </div>

        <p className="text-sm text-gray-500">
          Approving <span className="font-medium text-gray-800">{selected.length} measure{selected.length !== 1 ? "s" : ""}</span> across{" "}
          <span className="font-medium text-gray-800">{groupedByDeal.size} propert{groupedByDeal.size !== 1 ? "ies" : "y"}</span>.
        </p>

        <div className="max-h-56 overflow-y-auto space-y-2">
          {[...groupedByDeal.entries()].map(([dealId, { dealname, measures }]) => (
            <div key={dealId} className="rounded-lg border border-gray-100 p-3 space-y-1.5">
              <p className="text-xs font-medium text-gray-700">{dealname ?? dealId}</p>
              <div className="flex flex-wrap gap-1">
                {measures.map((m) => (
                  <span key={m} className="px-2 py-0.5 rounded-full text-xs bg-emerald-50 border border-emerald-200 text-emerald-700">
                    {m}
                  </span>
                ))}
              </div>
            </div>
          ))}
        </div>

        {error && <p className="text-xs text-red-600">{error}</p>}

        <div className="flex justify-end gap-2 pt-2">
          <Button variant="outline" size="sm" onClick={onClose} disabled={submitting}>
            Cancel
          </Button>
          <Button
            size="sm"
            onClick={handleConfirm}
            disabled={submitting}
            className="bg-emerald-600 hover:bg-emerald-700 text-white"
          >
            {submitting ? <Loader2 className="h-4 w-4 animate-spin mr-1.5" /> : null}
            Approve {selected.length} measure{selected.length !== 1 ? "s" : ""}
          </Button>
        </div>
      </div>
    </div>
  );
}

// ── Bulk instruct modal ──────────────────────────────────────────────────────

type BulkInstructModalProps = {
  selectedDealIds: string[];
  deals: ClassifiedDeal[];
  portfolioId: string;
  onClose: () => void;
  onSuccess: () => void;
};

function BulkInstructModal({ selectedDealIds, deals, portfolioId, onClose, onSuccess }: BulkInstructModalProps) {
  const [selectedMeasures, setSelectedMeasures] = useState<Set<string>>(new Set());
  const [confirmText, setConfirmText] = useState("");
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const selectedDeals = useMemo(
    () => deals.filter((d) => selectedDealIds.includes(d.dealId)),
    [deals, selectedDealIds],
  );

  function toggleMeasure(name: string) {
    setSelectedMeasures((prev) => {
      const next = new Set(prev);
      if (next.has(name)) next.delete(name);
      else next.add(name);
      return next;
    });
  }

  const canSubmit = selectedMeasures.size > 0 && confirmText.trim() === "confirm" && !submitting;

  async function handleSubmit() {
    if (!canSubmit) return;
    setSubmitting(true);
    setError(null);
    try {
      const res = await fetch(`/api/portfolio/${portfolioId}/bulk-instructed-measures`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          deals: selectedDealIds.map((dealId) => ({
            dealId,
            measureNames: [...selectedMeasures],
          })),
        }),
      });
      const data = await res.json();
      if (!res.ok || !data.ok) {
        setError(data.error ?? "Failed to instruct measures");
        return;
      }
      onSuccess();
    } catch {
      setError("Network error — please try again");
    } finally {
      setSubmitting(false);
    }
  }

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-sm">
      <div className="bg-white rounded-2xl shadow-2xl w-full max-w-lg mx-4 p-6 space-y-4">
        <div className="flex items-center justify-between">
          <h2 className="text-base font-semibold text-gray-800">Bulk instruct measures</h2>
          <button onClick={onClose} className="text-gray-400 hover:text-gray-600">
            <X className="h-4 w-4" />
          </button>
        </div>

        <p className="text-sm text-gray-500">
          Instructing on <span className="font-medium text-gray-800">{selectedDeals.length} propert{selectedDeals.length !== 1 ? "ies" : "y"}</span>.
          Select measures to add to all selected deals.
        </p>

        <div className="max-h-48 overflow-y-auto">
          <div className="grid grid-cols-2 gap-1.5">
            {MEASURE_NAMES.map((name) => (
              <label
                key={name}
                className={`flex items-center gap-2 px-3 py-2 rounded-lg border cursor-pointer text-xs transition-colors ${
                  selectedMeasures.has(name)
                    ? "bg-indigo-50 border-indigo-300 text-indigo-700"
                    : "border-gray-200 text-gray-600 hover:bg-gray-50"
                }`}
              >
                <Checkbox
                  checked={selectedMeasures.has(name)}
                  onCheckedChange={() => toggleMeasure(name)}
                  className="h-3.5 w-3.5"
                />
                {name}
              </label>
            ))}
          </div>
        </div>

        {selectedMeasures.size > 0 && (
          <div className="space-y-1">
            <p className="text-xs text-gray-500">
              Type <span className="font-mono font-semibold">confirm</span> to proceed
            </p>
            <Input
              value={confirmText}
              onChange={(e) => setConfirmText(e.target.value)}
              placeholder="confirm"
              className="h-8 text-sm"
            />
          </div>
        )}

        {error && <p className="text-xs text-red-600">{error}</p>}

        <div className="flex justify-end gap-2 pt-2">
          <Button variant="outline" size="sm" onClick={onClose} disabled={submitting}>
            Cancel
          </Button>
          <Button
            size="sm"
            onClick={handleSubmit}
            disabled={!canSubmit}
            className="bg-indigo-600 hover:bg-indigo-700 text-white"
          >
            {submitting ? <Loader2 className="h-4 w-4 animate-spin mr-1.5" /> : null}
            Instruct {selectedMeasures.size > 0 ? selectedMeasures.size : ""} measure{selectedMeasures.size !== 1 ? "s" : ""}
          </Button>
        </div>
      </div>
    </div>
  );
}

// ── Main component ───────────────────────────────────────────────────────────

export default function MeasuresTable({
  data,
  approvalsByDeal,
  instructedMeasuresByDeal,
  portfolioId,
  isApprover,
}: Props) {
  const router = useRouter();
  const [isPending, startTransition] = useTransition();

  const [search, setSearch] = useState("");
  const [mode, setMode] = useState<Mode>("chip-click");

  // Chip-click mode: Set<"dealId::measureName">
  const [selectedChips, setSelectedChips] = useState<Set<string>>(new Set());

  // Instruct mode: Set<dealId>
  const [selectedRows, setSelectedRows] = useState<Set<string>>(new Set());

  const [showApproveModal, setShowApproveModal] = useState(false);
  const [showInstructModal, setShowInstructModal] = useState(false);
  const [showBatchColumns, setShowBatchColumns] = useState(false);

  const dealsWithMeasures = useMemo(
    () => data.filter((d) => d.proposedMeasures || (instructedMeasuresByDeal[d.dealId]?.length ?? 0) > 0),
    [data, instructedMeasuresByDeal],
  );

  const filtered = useMemo(
    () => filterMeasureRows(dealsWithMeasures, instructedMeasuresByDeal, search),
    [dealsWithMeasures, instructedMeasuresByDeal, search],
  );

  function switchMode(next: Mode) {
    setMode(next);
    setSelectedChips(new Set());
    setSelectedRows(new Set());
  }

  function toggleChip(dealId: string, measureName: string) {
    const key = `${dealId}::${measureName}`;
    setSelectedChips((prev) => {
      const next = new Set(prev);
      if (next.has(key)) next.delete(key);
      else next.add(key);
      return next;
    });
  }

  function toggleRow(dealId: string) {
    setSelectedRows((prev) => {
      const next = new Set(prev);
      if (next.has(dealId)) next.delete(dealId);
      else next.add(dealId);
      return next;
    });
  }

  function toggleAllFiltered() {
    const allIds = filtered.map((d) => d.dealId);
    const allSelected = allIds.every((id) => selectedRows.has(id));
    if (allSelected) {
      setSelectedRows((prev) => {
        const next = new Set(prev);
        allIds.forEach((id) => next.delete(id));
        return next;
      });
    } else {
      setSelectedRows((prev) => {
        const next = new Set(prev);
        allIds.forEach((id) => next.add(id));
        return next;
      });
    }
  }

  const selectedChipItems = useMemo(
    () =>
      [...selectedChips].map((key) => {
        const [dealId, measureName] = key.split("::");
        const deal = data.find((d) => d.dealId === dealId);
        return { dealId, dealname: deal?.dealname ?? null, measureName };
      }),
    [selectedChips, data],
  );

  const allFilteredSelected =
    filtered.length > 0 && filtered.every((d) => selectedRows.has(d.dealId));

  function handleActionSuccess() {
    setShowApproveModal(false);
    setShowInstructModal(false);
    setSelectedChips(new Set());
    setSelectedRows(new Set());
    startTransition(() => router.refresh());
  }

  if (dealsWithMeasures.length === 0) {
    return (
      <div className="rounded-xl border border-gray-100 bg-white p-12 text-center">
        <p className="text-sm text-gray-400">
          No properties with proposed measures found in this project.
        </p>
      </div>
    );
  }

  const colSpan = (mode === "instruct" ? 7 : 6) + (showBatchColumns ? 2 : 0);

  return (
    <div className="space-y-4">
      {/* ── Toolbar ──────────────────────────────────────────────────── */}
      <div className="flex items-center justify-between gap-3 flex-wrap">
        <div className="relative flex-1 min-w-48 max-w-sm">
          <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" />
          <Input
            placeholder="Search address or measure…"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            className="pl-9 h-9 text-sm"
          />
        </div>

        <div className="flex items-center gap-2">
          <span className="text-xs text-gray-400">
            {filtered.length} of {dealsWithMeasures.length} properties
          </span>

          <button
            onClick={() => setShowBatchColumns((v) => !v)}
            className={`inline-flex items-center gap-1.5 h-8 px-2.5 rounded-md border text-xs font-medium transition-colors ${
              showBatchColumns
                ? "border-brandblue/40 bg-brandblue/5 text-brandblue"
                : "border-gray-200 bg-white text-gray-600 hover:border-brandblue/30 hover:text-brandblue"
            }`}
            aria-pressed={showBatchColumns}
          >
            <Layers className="h-3.5 w-3.5" />
            Group
          </button>

          {isApprover && (
            <>
              <Button
                size="sm"
                variant={mode === "chip-click" ? "default" : "outline"}
                className="h-8 text-xs gap-1.5"
                onClick={() => switchMode("chip-click")}
              >
                <CheckSquare className="h-3.5 w-3.5" />
                Approve mode
              </Button>
              <Button
                size="sm"
                variant={mode === "instruct" ? "default" : "outline"}
                className="h-8 text-xs gap-1.5"
                onClick={() => switchMode("instruct")}
              >
                <ListChecks className="h-3.5 w-3.5" />
                Instruct mode
              </Button>
            </>
          )}
        </div>
      </div>

      {/* ── Action bar ───────────────────────────────────────────────── */}
      {isApprover && mode === "chip-click" && selectedChips.size > 0 && (
        <div className="flex items-center gap-3 rounded-lg border border-emerald-200 bg-emerald-50 px-4 py-2.5">
          <span className="text-sm text-emerald-800 font-medium">
            {selectedChips.size} measure{selectedChips.size !== 1 ? "s" : ""} selected
          </span>
          <Button
            size="sm"
            className="h-7 text-xs bg-emerald-600 hover:bg-emerald-700 text-white"
            onClick={() => setShowApproveModal(true)}
          >
            Approve selected
          </Button>
          <button
            onClick={() => setSelectedChips(new Set())}
            className="ml-auto text-emerald-600 hover:text-emerald-800 text-xs"
          >
            Clear
          </button>
        </div>
      )}

      {isApprover && mode === "instruct" && selectedRows.size > 0 && (
        <div className="flex items-center gap-3 rounded-lg border border-indigo-200 bg-indigo-50 px-4 py-2.5">
          <span className="text-sm text-indigo-800 font-medium">
            {selectedRows.size} propert{selectedRows.size !== 1 ? "ies" : "y"} selected
          </span>
          <Button
            size="sm"
            className="h-7 text-xs bg-indigo-600 hover:bg-indigo-700 text-white"
            onClick={() => setShowInstructModal(true)}
          >
            Instruct measures
          </Button>
          <button
            onClick={() => setSelectedRows(new Set())}
            className="ml-auto text-indigo-600 hover:text-indigo-800 text-xs"
          >
            Clear
          </button>
        </div>
      )}

      {/* ── Table ────────────────────────────────────────────────────── */}
      <div className="relative rounded-xl border border-gray-100 overflow-hidden bg-white">
        {isPending && (
          <div className="absolute inset-0 z-10 flex items-center justify-center bg-white/60 backdrop-blur-sm">
            <Loader2 className="h-6 w-6 animate-spin text-brandblue" />
          </div>
        )}
        <Table>
          <TableHeader>
            <TableRow className="bg-gray-50 border-b border-gray-100">
              {mode === "instruct" && (
                <TableHead className="w-10 pl-3">
                  <Checkbox
                    checked={allFilteredSelected}
                    onCheckedChange={toggleAllFiltered}
                    aria-label="Select all filtered"
                    className="h-4 w-4"
                  />
                </TableHead>
              )}
              <TableHead className="text-xs font-semibold text-gray-500 uppercase tracking-wide">
                Address
              </TableHead>
              <TableHead className="text-xs font-semibold text-gray-500 uppercase tracking-wide">
                Stage
              </TableHead>
              <TableHead className="text-xs font-semibold text-gray-500 uppercase tracking-wide">
                Proposed
              </TableHead>
              <TableHead className="text-xs font-semibold text-gray-500 uppercase tracking-wide">
                Instructed
              </TableHead>
              <TableHead className="text-xs font-semibold text-gray-500 uppercase tracking-wide">
                Tech Approved
              </TableHead>
              <TableHead className="text-xs font-semibold text-gray-500 uppercase tracking-wide">
                Status
              </TableHead>
              {showBatchColumns && (
                <>
                  <TableHead className="text-xs font-semibold text-gray-500 uppercase tracking-wide">
                    Group
                  </TableHead>
                  <TableHead className="text-xs font-semibold text-gray-500 uppercase tracking-wide">
                    Group Description
                  </TableHead>
                </>
              )}
            </TableRow>
          </TableHeader>
          <TableBody>
            {filtered.map((deal) => {
              const proposed = parseMeasures(deal.proposedMeasures);
              const instructed = instructedMeasuresByDeal[deal.dealId] ?? [];
              const techApproved = parseMeasures(deal.technicalApprovedMeasuresForInstall);
              const approvedForDeal = approvalsByDeal[deal.dealId] ?? [];
              const approvedSet = new Set(approvedForDeal);
              const stageColor = STAGE_COLORS[deal.displayStage];
              const isRowSelected = selectedRows.has(deal.dealId);

              const dealPageUrl = `/portfolio/${portfolioId}/your-projects/live/${deal.dealId}?tab=works`;

              const handleRowClick = (e: React.MouseEvent) => {
                // Don't navigate if clicking a chip or checkbox
                const target = e.target as HTMLElement;
                if (target.closest("[data-chip]") || target.closest("[data-checkbox]")) return;
                router.push(dealPageUrl);
              };

              return (
                <TableRow
                  key={deal.dealId}
                  data-testid="measures-row"
                  onClick={handleRowClick}
                  tabIndex={0}
                  role="button"
                  onKeyDown={(e) => {
                    if (e.key === "Enter" || e.key === " ") {
                      e.preventDefault();
                      router.push(dealPageUrl);
                    }
                  }}
                  className={`border-b border-gray-50 hover:bg-gray-50/50 transition-colors cursor-pointer ${
                    isRowSelected ? "bg-indigo-50/40" : ""
                  }`}
                >
                  {/* Row checkbox (instruct mode only) */}
                  {mode === "instruct" && (
                    <TableCell className="pl-3 py-3 w-10" data-checkbox>
                      <Checkbox
                        checked={isRowSelected}
                        onCheckedChange={() => toggleRow(deal.dealId)}
                        onClick={(e) => e.stopPropagation()}
                        className="h-4 w-4"
                        aria-label={`Select ${deal.dealname ?? deal.dealId}`}
                      />
                    </TableCell>
                  )}

                  {/* Address */}
                  <TableCell className="py-3">
                    <div className="font-medium text-sm text-gray-800">
                      {deal.dealname ?? "—"}
                    </div>
                    {deal.landlordPropertyId && (
                      <div className="text-xs text-gray-400 mt-0.5">
                        {deal.landlordPropertyId}
                      </div>
                    )}
                  </TableCell>

                  {/* Stage */}
                  <TableCell className="py-3">
                    <span
                      className={`inline-flex items-center gap-1.5 px-2 py-1 rounded-full text-xs font-medium border ${stageColor.bg} ${stageColor.text} ${stageColor.border}`}
                    >
                      <span className={`h-1.5 w-1.5 rounded-full ${stageColor.dot}`} />
                      {deal.displayStage}
                    </span>
                  </TableCell>

                  {/* Proposed measures */}
                  <TableCell className="py-3">
                    <div className="flex flex-wrap gap-1.5">
                      {proposed.map((measure) => {
                        const chipKey = `${deal.dealId}::${measure}`;
                        const isSelected = selectedChips.has(chipKey);
                        const isApproved = approvedSet.has(measure);
                        const clickable = isApprover && mode === "chip-click";

                        return (
                          <span
                            key={measure}
                            data-chip
                            onClick={clickable ? (e) => { e.stopPropagation(); toggleChip(deal.dealId, measure); } : undefined}
                            className={`px-2 py-1 rounded-full text-xs border transition-all ${
                              isSelected
                                ? "bg-emerald-100 border-emerald-400 text-emerald-800 ring-2 ring-emerald-300"
                                : isApproved
                                  ? "bg-emerald-50 border-emerald-200 text-emerald-700"
                                  : "bg-gray-50 border-gray-200 text-gray-600"
                            } ${clickable ? "cursor-pointer hover:border-emerald-400" : ""}`}
                          >
                            {measure}
                          </span>
                        );
                      })}
                    </div>
                  </TableCell>

                  {/* Instructed measures */}
                  <TableCell className="py-3">
                    <div className="flex flex-wrap gap-1.5">
                      {instructed.map((measure) => (
                        <span
                          key={measure}
                          className="px-2 py-1 rounded-full text-xs border bg-indigo-50 border-indigo-200 text-indigo-700"
                        >
                          {measure}
                        </span>
                      ))}
                    </div>
                  </TableCell>

                  {/* Tech approved */}
                  <TableCell className="py-3">
                    <div className="flex flex-wrap gap-1.5">
                      {techApproved.map((measure) => (
                        <span
                          key={measure}
                          className="px-2 py-1 rounded-full text-xs border bg-violet-50 border-violet-200 text-violet-700"
                        >
                          {measure}
                        </span>
                      ))}
                    </div>
                  </TableCell>

                  {/* Approval status */}
                  <TableCell className="py-3">
                    <ApprovalStatus proposed={proposed} approved={approvedForDeal} />
                  </TableCell>

                  {showBatchColumns && (
                    <>
                      <TableCell className="py-3">
                        <span className="text-xs font-mono text-gray-600">
                          {deal.batch ?? <span className="text-gray-300">—</span>}
                        </span>
                      </TableCell>
                      <TableCell className="py-3">
                        <span className="text-xs text-gray-600 max-w-[220px] line-clamp-2 leading-snug">
                          {deal.batchDescription ?? <span className="text-gray-300">—</span>}
                        </span>
                      </TableCell>
                    </>
                  )}
                </TableRow>
              );
            })}
          </TableBody>
        </Table>
      </div>

      {/* ── Modals ───────────────────────────────────────────────────── */}
      {showApproveModal && (
        <BulkApproveModal
          selected={selectedChipItems}
          portfolioId={portfolioId}
          onClose={() => setShowApproveModal(false)}
          onSuccess={handleActionSuccess}
        />
      )}

      {showInstructModal && (
        <BulkInstructModal
          selectedDealIds={[...selectedRows]}
          deals={data}
          portfolioId={portfolioId}
          onClose={() => setShowInstructModal(false)}
          onSuccess={handleActionSuccess}
        />
      )}
    </div>
  );
}
