"use client";

import { useState, useMemo, useEffect } from "react";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { ApprovalConfirmDialog } from "../ApprovalConfirmDialog";
import type { PendingDiff } from "../ApprovalConfirmDialog";

interface MeasureApprovalEditorProps {
  dealId: string;
  dealName: string | null;
  portfolioId: string;
  proposedMeasures: string[];
  isApprover: boolean;
}

export function MeasureApprovalEditor({
  dealId,
  dealName,
  portfolioId,
  proposedMeasures,
  isApprover,
}: MeasureApprovalEditorProps) {
  const queryClient = useQueryClient();

  // Reuse the pibi-measures query — it already returns approvedMeasures and
  // instructedMeasures alongside the PIBI selection.
  const { data, isLoading } = useQuery<{
    pibiMeasures: string[];
    approvedMeasures: string[];
    instructedMeasures: string[];
  }>({
    queryKey: ["pibiMeasures", portfolioId, dealId],
    queryFn: async () => {
      const res = await fetch(
        `/api/portfolio/${portfolioId}/pibi-measures?dealId=${encodeURIComponent(dealId)}`,
      );
      if (!res.ok) throw new Error("Failed to fetch measures");
      return res.json();
    },
    staleTime: 30_000,
  });

  const allMeasures = useMemo(() => {
    const instructed = data?.instructedMeasures ?? [];
    const all = [...proposedMeasures];
    for (const m of instructed) {
      if (!all.includes(m)) all.push(m);
    }
    return all;
  }, [proposedMeasures, data?.instructedMeasures]);

  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [savedSelected, setSavedSelected] = useState<Set<string>>(new Set());
  const [initialised, setInitialised] = useState(false);
  const [confirmOpen, setConfirmOpen] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (!data) return;
    const initial = new Set(data.approvedMeasures);
    setSelected(new Set(initial));
    setSavedSelected(new Set(initial));
    setInitialised(true);
    setError(null);
  }, [dealId, data]);

  function toggleMeasure(measure: string) {
    if (!isApprover) return;
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(measure)) next.delete(measure);
      else next.add(measure);
      return next;
    });
  }

  const pendingDiff: PendingDiff = useMemo(() => {
    const added = allMeasures.filter((m) => selected.has(m) && !savedSelected.has(m));
    const removed = allMeasures.filter((m) => !selected.has(m) && savedSelected.has(m));
    return { added, removed };
  }, [allMeasures, selected, savedSelected]);

  const isDirty = pendingDiff.added.length > 0 || pendingDiff.removed.length > 0;

  async function handleConfirm() {
    setSubmitting(true);
    setError(null);

    const changes = [
      ...pendingDiff.added.map((measureName) => ({
        hubspotDealId: dealId,
        measureName,
        approved: true,
      })),
      ...pendingDiff.removed.map((measureName) => ({
        hubspotDealId: dealId,
        measureName,
        approved: false,
      })),
    ];

    try {
      const res = await fetch(`/api/portfolio/${portfolioId}/approvals`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ changes }),
      });
      if (!res.ok) {
        const json = await res.json().catch(() => ({}));
        setError(
          typeof json.error === "string" ? json.error : "Failed to save approvals",
        );
        setConfirmOpen(false);
        return;
      }
      setSavedSelected(new Set(selected));
      setConfirmOpen(false);
      queryClient.invalidateQueries({
        queryKey: ["pibiMeasures", portfolioId, dealId],
      });
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to save approvals");
      setConfirmOpen(false);
    } finally {
      setSubmitting(false);
    }
  }

  if (isLoading || !initialised) {
    if (allMeasures.length === 0 && isLoading) {
      return (
        <p
          data-testid="measure-approval-loading"
          className="text-xs text-gray-400 py-2"
        >
          Loading…
        </p>
      );
    }
  }

  if (allMeasures.length === 0) {
    return (
      <p className="text-xs text-gray-400 py-2">
        No proposed measures for this property yet.
      </p>
    );
  }

  return (
    <div className="space-y-3">
      <div
        data-testid="measure-approval-chips"
        className="flex flex-wrap gap-2"
      >
        {allMeasures.map((measure) => {
          const isApproved = selected.has(measure);
          return (
            <label
              key={measure}
              data-testid={`measure-approval-chip-${measure}`}
              className={`flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs border transition-colors ${
                isApprover ? "cursor-pointer" : "cursor-default"
              } ${
                isApproved
                  ? "bg-brandblue/10 border-brandblue/40 text-brandblue font-medium"
                  : "bg-gray-50 border-gray-200 text-gray-600 hover:bg-gray-100"
              }`}
            >
              {isApprover && (
                <input
                  type="checkbox"
                  className="sr-only"
                  checked={isApproved}
                  onChange={() => toggleMeasure(measure)}
                  disabled={submitting}
                  data-testid={`measure-approval-checkbox-${measure}`}
                />
              )}
              <span
                className={`w-3 h-3 rounded-sm border flex items-center justify-center shrink-0 ${
                  isApproved
                    ? "bg-brandblue border-brandblue"
                    : "bg-white border-gray-300"
                }`}
              >
                {isApproved && (
                  <svg viewBox="0 0 10 8" className="w-2 h-2 fill-white">
                    <path
                      d="M1 4l3 3 5-6"
                      stroke="white"
                      strokeWidth="1.5"
                      fill="none"
                      strokeLinecap="round"
                      strokeLinejoin="round"
                    />
                  </svg>
                )}
              </span>
              {measure}
            </label>
          );
        })}
      </div>

      {isApprover && (
        <div className="flex items-center justify-between gap-3">
          <p className="text-[11px] text-gray-400">
            Tick measures to approve. Changes require confirmation before saving.
          </p>
          <button
            type="button"
            data-testid="measure-approval-save"
            onClick={() => setConfirmOpen(true)}
            disabled={!isDirty || submitting}
            className="text-xs font-medium px-3 py-1.5 rounded-lg bg-brandblue text-white hover:bg-brandmidblue disabled:opacity-50 transition-colors"
          >
            {submitting ? "Saving…" : "Review & Save"}
          </button>
        </div>
      )}

      {error && (
        <p
          data-testid="measure-approval-error"
          className="text-xs text-red-600 bg-red-50 px-3 py-2 rounded-lg"
        >
          {error}
        </p>
      )}

      <ApprovalConfirmDialog
        open={confirmOpen}
        pendingDiffs={{ [dealId]: pendingDiff }}
        dealNames={{ [dealId]: dealName ?? dealId }}
        onConfirm={handleConfirm}
        onCancel={() => setConfirmOpen(false)}
        isPending={submitting}
      />
    </div>
  );
}
