'use client';

import { useEffect, useMemo, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { AlertTriangle, Anchor, FileText, Loader2, Receipt, Ship, Users } from 'lucide-react';
import { toast } from 'sonner';

import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Textarea } from '@/components/ui/textarea';
import { apiFetch } from '@/lib/api/client';

interface DossierBerth {
  berthId: string;
  mooringNumber: string;
  status: string;
  otherInterests: Array<{
    interestId: string;
    clientId: string | null;
    clientName: string | null;
    pipelineStage: string;
    daysSinceUpdate: number;
  }>;
}
interface DossierDocument {
  documentId: string;
  templateName: string | null;
  status: string;
  documensoEnvelopeId: string | null;
  isInFlight: boolean;
}
interface DossierYacht {
  yachtId: string;
  name: string;
  hullNumber: string | null;
  status: string;
}
interface DossierReservation {
  reservationId: string;
  berthId: string;
  mooringNumber: string;
  status: string;
  startDate: string;
}
interface DossierInvoice {
  invoiceId: string;
  invoiceNumber: string;
  status: string;
  total: string;
  currency: string;
}
interface DossierInterest {
  interestId: string;
  pipelineStage: string;
  primaryBerthMooring: string | null;
  hasSignedEoi: boolean;
}
interface ArchiveDossier {
  client: { id: string; fullName: string; portId: string; archivedAt: string | null };
  stakeLevel: 'low' | 'high';
  highStakesStage: string | null;
  interests: DossierInterest[];
  berths: DossierBerth[];
  yachts: DossierYacht[];
  companies: Array<{ companyId: string; name: string; membershipRole: string | null }>;
  reservations: DossierReservation[];
  invoices: DossierInvoice[];
  documents: DossierDocument[];
  hasPortalUser: boolean;
  blockers: string[];
}

type BerthAction = 'release' | 'retain';
type YachtAction = 'transfer' | 'mark_sold_away' | 'retain';
type ReservationAction = 'cancel' | 'transfer';
type InvoiceAction = 'void' | 'write_off' | 'leave';
type DocumentAction = 'void_documenso' | 'leave';

interface Props {
  open: boolean;
  onOpenChange: (next: boolean) => void;
  clientId: string;
  clientName: string;
  /** Called after successful archive. */
  onSuccess?: () => void;
}

export function SmartArchiveDialog({ open, onOpenChange, clientId, clientName, onSuccess }: Props) {
  const qc = useQueryClient();

  const dossierQuery = useQuery({
    queryKey: ['client-archive-dossier', clientId],
    queryFn: () =>
      apiFetch<{ data: ArchiveDossier }>(`/api/v1/clients/${clientId}/archive-dossier`),
    enabled: open,
  });

  const dossier = dossierQuery.data?.data;

  // ─── Local decision state ────────────────────────────────────────────────
  const [reason, setReason] = useState('');
  const [acknowledged, setAcknowledged] = useState(false);
  const [berthDecisions, setBerthDecisions] = useState<Record<string, BerthAction>>({});
  const [yachtDecisions, setYachtDecisions] = useState<Record<string, YachtAction>>({});
  const [reservationDecisions, setReservationDecisions] = useState<
    Record<string, ReservationAction>
  >({});
  const [invoiceDecisions, setInvoiceDecisions] = useState<Record<string, InvoiceAction>>({});
  const [documentDecisions, setDocumentDecisions] = useState<Record<string, DocumentAction>>({});

  // Reset state when the dialog opens / closes / dossier loads.
  useEffect(() => {
    if (!open || !dossier) return;
    setReason('');
    setAcknowledged(false);
    // Sensible defaults: release all berths, retain all yachts, cancel
    // active reservations, leave invoices, leave documents alone.
    const b: Record<string, BerthAction> = {};
    for (const berth of dossier.berths) {
      // Sold berths can't be released; default to retain.
      b[berth.berthId] = berth.status === 'sold' ? 'retain' : 'release';
    }
    setBerthDecisions(b);
    setYachtDecisions(Object.fromEntries(dossier.yachts.map((y) => [y.yachtId, 'retain'])));
    setReservationDecisions(
      Object.fromEntries(dossier.reservations.map((r) => [r.reservationId, 'cancel'])),
    );
    setInvoiceDecisions(Object.fromEntries(dossier.invoices.map((i) => [i.invoiceId, 'leave'])));
    setDocumentDecisions(Object.fromEntries(dossier.documents.map((d) => [d.documentId, 'leave'])));
  }, [open, dossier]);

  const hasSignedDocs = useMemo(
    () =>
      dossier?.documents.some((d) => d.status === 'completed' || d.status === 'signed') ?? false,
    [dossier],
  );

  const canSubmit = useMemo(() => {
    if (!dossier) return false;
    if (dossier.blockers.length > 0) return false;
    if (dossier.stakeLevel === 'high' && reason.trim().length < 5) return false;
    if (hasSignedDocs && !acknowledged) return false;
    return true;
  }, [dossier, reason, hasSignedDocs, acknowledged]);

  const archiveMutation = useMutation({
    mutationFn: () => {
      if (!dossier) throw new Error('No dossier');
      const berthDec = dossier.berths.map((b) => ({
        berthId: b.berthId,
        // The interestId for this berth — use the first interest in the
        // dossier that has this berth as its primary. Fallback to the
        // first interest at all (the API only needs the link reference).
        interestId:
          dossier.interests.find((i) => i.primaryBerthMooring === b.mooringNumber)?.interestId ??
          dossier.interests[0]?.interestId ??
          '',
        action: berthDecisions[b.berthId] ?? 'retain',
      }));
      return apiFetch<{ data: { releasedBerths: Array<{ mooringNumber: string }> } }>(
        `/api/v1/clients/${clientId}/archive`,
        {
          method: 'POST',
          body: {
            reason,
            acknowledgedSignedDocuments: acknowledged,
            berthDecisions: berthDec,
            yachtDecisions: dossier.yachts.map((y) => ({
              yachtId: y.yachtId,
              action: yachtDecisions[y.yachtId] ?? 'retain',
            })),
            reservationDecisions: dossier.reservations.map((r) => ({
              reservationId: r.reservationId,
              action: reservationDecisions[r.reservationId] ?? 'cancel',
            })),
            invoiceDecisions: dossier.invoices.map((i) => ({
              invoiceId: i.invoiceId,
              action: invoiceDecisions[i.invoiceId] ?? 'leave',
            })),
            documentDecisions: dossier.documents.map((d) => ({
              documentId: d.documentId,
              action: documentDecisions[d.documentId] ?? 'leave',
            })),
          },
        },
      );
    },
    onSuccess: (res) => {
      const released = res.data.releasedBerths;
      toast.success(
        released.length > 0
          ? `${clientName} archived. ${released.length} berth${released.length === 1 ? '' : 's'} released.`
          : `${clientName} archived.`,
      );
      qc.invalidateQueries({ queryKey: ['clients'] });
      qc.invalidateQueries({ queryKey: ['berths'] });
      qc.invalidateQueries({ queryKey: ['interests'] });
      onOpenChange(false);
      onSuccess?.();
    },
    onError: (err: unknown) => {
      toast.error(err instanceof Error ? err.message : 'Archive failed');
    },
  });

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-2xl">
        <DialogHeader>
          <DialogTitle>Archive {clientName}</DialogTitle>
          <DialogDescription>
            Archive is reversible — the client can be restored from the archived list. Decide what
            should happen to the relationships below before continuing.
          </DialogDescription>
        </DialogHeader>

        {dossierQuery.isLoading ? (
          <div className="py-8 text-center text-sm text-muted-foreground">
            <Loader2 className="h-5 w-5 animate-spin mx-auto mb-2" />
            Loading dossier…
          </div>
        ) : dossierQuery.error || !dossier ? (
          <div className="py-8 text-center text-sm text-red-600">
            Failed to load dossier:{' '}
            {dossierQuery.error instanceof Error ? dossierQuery.error.message : 'unknown error'}
          </div>
        ) : (
          <div className="space-y-3 max-h-[60vh] overflow-y-auto pr-1">
            {dossier.blockers.length > 0 && (
              <Card className="border-red-300 bg-red-50">
                <CardHeader className="pb-2">
                  <CardTitle className="text-sm font-medium text-red-800 flex items-center gap-2">
                    <AlertTriangle className="h-4 w-4" /> Cannot archive
                  </CardTitle>
                </CardHeader>
                <CardContent className="text-sm text-red-700 space-y-1">
                  {dossier.blockers.map((b, i) => (
                    <p key={i}>{b}</p>
                  ))}
                </CardContent>
              </Card>
            )}

            {dossier.stakeLevel === 'high' && (
              <Card className="border-amber-300 bg-amber-50">
                <CardHeader className="pb-2">
                  <CardTitle className="text-sm font-medium text-amber-900 flex items-center gap-2">
                    <AlertTriangle className="h-4 w-4" />
                    Late-stage deal — confirmation required
                  </CardTitle>
                </CardHeader>
                <CardContent className="text-xs text-amber-900">
                  This client is at <Badge variant="secondary">{dossier.highStakesStage}</Badge>.
                  Provide a reason explaining why you&rsquo;re archiving them at this stage. The
                  reason is recorded in the audit log.
                </CardContent>
              </Card>
            )}

            {/* Interests + signed-doc acknowledgment */}
            {dossier.interests.length > 0 && (
              <Card>
                <CardHeader className="pb-2">
                  <CardTitle className="text-sm font-medium flex items-center gap-2">
                    <FileText className="h-4 w-4" /> Pipeline interests ({dossier.interests.length})
                  </CardTitle>
                </CardHeader>
                <CardContent className="text-xs space-y-1">
                  {dossier.interests.map((i) => (
                    <div key={i.interestId} className="flex items-center justify-between">
                      <span className="font-mono">{i.interestId.slice(0, 8)}</span>
                      <span className="flex items-center gap-2">
                        <Badge variant="secondary" className="text-xs">
                          {i.pipelineStage}
                        </Badge>
                        {i.hasSignedEoi && <Badge className="text-xs">Signed EOI</Badge>}
                      </span>
                    </div>
                  ))}
                </CardContent>
              </Card>
            )}

            {hasSignedDocs && (
              <Card className="border-blue-300 bg-blue-50">
                <CardContent className="pt-4 text-xs text-blue-900">
                  <label className="flex items-start gap-2 cursor-pointer">
                    <input
                      type="checkbox"
                      checked={acknowledged}
                      onChange={(e) => setAcknowledged(e.target.checked)}
                      className="mt-0.5"
                    />
                    <span>
                      I acknowledge this client has signed legal documents. The documents will be
                      retained in the system and remain binding regardless of archive status.
                    </span>
                  </label>
                </CardContent>
              </Card>
            )}

            {/* Berths */}
            {dossier.berths.length > 0 && (
              <Card>
                <CardHeader className="pb-2">
                  <CardTitle className="text-sm font-medium flex items-center gap-2">
                    <Anchor className="h-4 w-4" /> Berths ({dossier.berths.length})
                  </CardTitle>
                </CardHeader>
                <CardContent className="space-y-3">
                  {dossier.berths.map((b) => (
                    <div key={b.berthId} className="text-xs">
                      <div className="flex items-center justify-between mb-1">
                        <div className="flex items-center gap-2">
                          <span className="font-medium">Berth {b.mooringNumber}</span>
                          <Badge variant="secondary" className="text-xs">
                            {b.status}
                          </Badge>
                        </div>
                        <select
                          className="rounded border bg-background px-2 py-1 text-xs disabled:opacity-50"
                          value={berthDecisions[b.berthId] ?? 'retain'}
                          onChange={(e) =>
                            setBerthDecisions((prev) => ({
                              ...prev,
                              [b.berthId]: e.target.value as BerthAction,
                            }))
                          }
                          disabled={b.status === 'sold'}
                        >
                          <option value="retain">Retain on archived client</option>
                          <option value="release">Release to available</option>
                        </select>
                      </div>
                      {b.status === 'sold' && (
                        <p className="text-muted-foreground italic">
                          Sold berths stay sold. Process a refund separately if needed.
                        </p>
                      )}
                      {b.otherInterests.length > 0 && berthDecisions[b.berthId] === 'release' && (
                        <p className="text-muted-foreground">
                          Releasing will notify the sales rep. Other interests on this berth:{' '}
                          {b.otherInterests
                            .slice(0, 3)
                            .map((o) => `${o.clientName ?? '?'} (${o.pipelineStage})`)
                            .join(', ')}
                          {b.otherInterests.length > 3 ? ` +${b.otherInterests.length - 3}` : ''}
                        </p>
                      )}
                    </div>
                  ))}
                </CardContent>
              </Card>
            )}

            {/* Yachts */}
            {dossier.yachts.length > 0 && (
              <Card>
                <CardHeader className="pb-2">
                  <CardTitle className="text-sm font-medium flex items-center gap-2">
                    <Ship className="h-4 w-4" /> Yachts owned ({dossier.yachts.length})
                  </CardTitle>
                </CardHeader>
                <CardContent className="space-y-2">
                  {dossier.yachts.map((y) => (
                    <div key={y.yachtId} className="flex items-center justify-between text-xs">
                      <span className="font-medium">{y.name}</span>
                      <select
                        className="rounded border bg-background px-2 py-1 text-xs"
                        value={yachtDecisions[y.yachtId] ?? 'retain'}
                        onChange={(e) =>
                          setYachtDecisions((prev) => ({
                            ...prev,
                            [y.yachtId]: e.target.value as YachtAction,
                          }))
                        }
                      >
                        <option value="retain">Leave on archived client</option>
                        <option value="mark_sold_away">Mark as sold-away</option>
                        {/* Transfer to another owner needs an owner picker; v1
                            offers retain + sold-away inline. Use the yacht
                            detail page to transfer to a specific owner. */}
                      </select>
                    </div>
                  ))}
                </CardContent>
              </Card>
            )}

            {/* Reservations */}
            {dossier.reservations.length > 0 && (
              <Card>
                <CardHeader className="pb-2">
                  <CardTitle className="text-sm font-medium flex items-center gap-2">
                    <Anchor className="h-4 w-4" /> Active reservations (
                    {dossier.reservations.length})
                  </CardTitle>
                </CardHeader>
                <CardContent className="space-y-2">
                  {dossier.reservations.map((r) => (
                    <div
                      key={r.reservationId}
                      className="flex items-center justify-between text-xs"
                    >
                      <span>Berth {r.mooringNumber}</span>
                      <select
                        className="rounded border bg-background px-2 py-1 text-xs"
                        value={reservationDecisions[r.reservationId] ?? 'cancel'}
                        onChange={(e) =>
                          setReservationDecisions((prev) => ({
                            ...prev,
                            [r.reservationId]: e.target.value as ReservationAction,
                          }))
                        }
                      >
                        <option value="cancel">Cancel reservation</option>
                      </select>
                    </div>
                  ))}
                </CardContent>
              </Card>
            )}

            {/* Invoices */}
            {dossier.invoices.length > 0 && (
              <Card>
                <CardHeader className="pb-2">
                  <CardTitle className="text-sm font-medium flex items-center gap-2">
                    <Receipt className="h-4 w-4" /> Outstanding invoices ({dossier.invoices.length})
                  </CardTitle>
                </CardHeader>
                <CardContent className="space-y-2">
                  {dossier.invoices.map((i) => (
                    <div key={i.invoiceId} className="flex items-center justify-between text-xs">
                      <span>
                        {i.invoiceNumber} · {i.total} {i.currency}
                      </span>
                      <select
                        className="rounded border bg-background px-2 py-1 text-xs"
                        value={invoiceDecisions[i.invoiceId] ?? 'leave'}
                        onChange={(e) =>
                          setInvoiceDecisions((prev) => ({
                            ...prev,
                            [i.invoiceId]: e.target.value as InvoiceAction,
                          }))
                        }
                      >
                        <option value="leave">Leave open</option>
                        <option value="void">Void</option>
                        <option value="write_off">Write off</option>
                      </select>
                    </div>
                  ))}
                </CardContent>
              </Card>
            )}

            {/* In-flight Documenso envelopes */}
            {dossier.documents.filter((d) => d.isInFlight).length > 0 && (
              <Card>
                <CardHeader className="pb-2">
                  <CardTitle className="text-sm font-medium flex items-center gap-2">
                    <FileText className="h-4 w-4" /> In-flight Documenso envelopes
                  </CardTitle>
                </CardHeader>
                <CardContent className="space-y-2">
                  {dossier.documents
                    .filter((d) => d.isInFlight)
                    .map((d) => (
                      <div key={d.documentId} className="flex items-center justify-between text-xs">
                        <span>{d.templateName ?? d.documentId.slice(0, 8)}</span>
                        <select
                          className="rounded border bg-background px-2 py-1 text-xs"
                          value={documentDecisions[d.documentId] ?? 'leave'}
                          onChange={(e) =>
                            setDocumentDecisions((prev) => ({
                              ...prev,
                              [d.documentId]: e.target.value as DocumentAction,
                            }))
                          }
                        >
                          <option value="leave">Leave envelope pending</option>
                          <option value="void_documenso">Void in Documenso</option>
                        </select>
                      </div>
                    ))}
                </CardContent>
              </Card>
            )}

            {/* Auto-handled summary */}
            <Card className="border-muted">
              <CardHeader className="pb-2">
                <CardTitle className="text-sm font-medium flex items-center gap-2">
                  <Users className="h-4 w-4" /> Automatically handled
                </CardTitle>
              </CardHeader>
              <CardContent className="text-xs text-muted-foreground space-y-1">
                <p>EOI documents — retained for audit (always)</p>
                {dossier.hasPortalUser && <p>Portal user — deactivated (login revoked)</p>}
                {dossier.companies.length > 0 && (
                  <p>Company memberships — end-dated to today (history preserved)</p>
                )}
                <p>Notes, contacts, tags, addresses — survive on the archived client</p>
              </CardContent>
            </Card>

            {/* Reason field */}
            <div>
              <label className="text-xs uppercase tracking-wide text-muted-foreground">
                Reason {dossier.stakeLevel === 'high' && <span className="text-red-600">*</span>}
              </label>
              <Textarea
                value={reason}
                onChange={(e) => setReason(e.target.value)}
                placeholder={
                  dossier.stakeLevel === 'high'
                    ? `Why are you archiving this client at ${dossier.highStakesStage}?`
                    : 'Optional: why is this client being archived?'
                }
                className="mt-1 min-h-[60px]"
              />
            </div>
          </div>
        )}

        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button
            disabled={!canSubmit || archiveMutation.isPending}
            onClick={() => archiveMutation.mutate()}
          >
            {archiveMutation.isPending ? (
              <Loader2 className="h-3.5 w-3.5 animate-spin mr-1.5" />
            ) : null}
            Archive
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
