'use client';

import { useMemo, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import {
  AlertTriangle,
  Anchor,
  CheckCircle2,
  FileText,
  Loader2,
  Lock,
  Ship,
  Wrench,
} 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 { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Checkbox } from '@/components/ui/checkbox';
import { apiFetch } from '@/lib/api/client';
import { toastError } from '@/lib/api/toast-error';

interface RestoreReversal {
  id: string;
  kind: string;
  refId: string;
  label: string;
  reason: string;
}
interface LockedReversal extends RestoreReversal {
  lockReason: string;
}
interface RestoreDossier {
  client: { id: string; fullName: string; portId: string };
  autoReversible: RestoreReversal[];
  reversibleWithPrompt: RestoreReversal[];
  locked: LockedReversal[];
}

interface Props {
  open: boolean;
  onOpenChange: (next: boolean) => void;
  clientId: string;
  clientName: string;
  onSuccess?: () => void;
}

function iconFor(kind: string) {
  if (kind.startsWith('berth_')) return <Anchor className="h-3 w-3" aria-hidden />;
  if (kind.startsWith('yacht_')) return <Ship className="h-3 w-3" aria-hidden />;
  if (kind.startsWith('documenso_')) return <FileText className="h-3 w-3" aria-hidden />;
  return <Wrench className="h-3 w-3" aria-hidden />;
}

export function SmartRestoreDialog(props: Props) {
  // Key-based remount: the body is keyed on open + clientId so its
  // useState({}) initializer runs fresh each open. Replaces the prior
  // useEffect(setSelected, [open, dossier]) reset.
  return (
    <SmartRestoreDialogBody key={props.open ? `open:${props.clientId}` : 'closed'} {...props} />
  );
}

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

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

  const dossier = dossierQuery.data?.data;

  const [selected, setSelected] = useState<Record<string, boolean>>({});

  const restoreMutation = useMutation({
    mutationFn: () => {
      const applyReversals = Object.entries(selected)
        .filter(([, v]) => v)
        .map(([k]) => k);
      return apiFetch<{
        data: { autoReversed: number; promptedReversed: number; lockedSkipped: number };
      }>(`/api/v1/clients/${clientId}/restore`, {
        method: 'POST',
        body: { applyReversals },
      });
    },
    onSuccess: (res) => {
      const d = res.data;
      const parts: string[] = [];
      if (d.autoReversed > 0) parts.push(`${d.autoReversed} auto-reversed`);
      if (d.promptedReversed > 0) parts.push(`${d.promptedReversed} re-applied`);
      if (d.lockedSkipped > 0) parts.push(`${d.lockedSkipped} locked`);
      toast.success(`${clientName} restored${parts.length > 0 ? ` (${parts.join(', ')})` : ''}.`);
      qc.invalidateQueries({ queryKey: ['clients'] });
      qc.invalidateQueries({ queryKey: ['clients', clientId] });
      qc.invalidateQueries({ queryKey: ['berths'] });
      qc.invalidateQueries({ queryKey: ['interests'] });
      onOpenChange(false);
      onSuccess?.();
    },
    onError: (err: unknown) => {
      toastError(err, 'Restore failed');
    },
  });

  const nothingToShow = useMemo(
    () =>
      !!dossier &&
      dossier.autoReversible.length === 0 &&
      dossier.reversibleWithPrompt.length === 0 &&
      dossier.locked.length === 0,
    [dossier],
  );

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-2xl">
        <DialogHeader>
          <DialogTitle>Restore {clientName}</DialogTitle>
          <DialogDescription>
            Review what was changed at archive time and decide which changes to undo. The client
            record itself will always be un-archived.
          </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" aria-hidden />
            Loading restore 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>
        ) : nothingToShow ? (
          <div className="py-6 text-center text-sm text-muted-foreground">
            No tracked archive changes to review. The client will simply be un-archived.
          </div>
        ) : (
          <div className="space-y-3 max-h-[60vh] overflow-y-auto pr-1">
            {dossier.autoReversible.length > 0 && (
              <Card className="border-emerald-300 bg-emerald-50">
                <CardHeader className="pb-2">
                  <CardTitle className="text-sm font-medium text-emerald-900 flex items-center gap-2">
                    <CheckCircle2 className="h-4 w-4" aria-hidden /> Auto-reversed (
                    {dossier.autoReversible.length})
                  </CardTitle>
                </CardHeader>
                <CardContent className="text-xs space-y-1.5 text-emerald-900">
                  {dossier.autoReversible.map((r) => (
                    <div key={r.id} className="flex items-start gap-2">
                      <span className="mt-0.5">{iconFor(r.kind)}</span>
                      <span>
                        <span className="font-medium">{r.label}</span> - {r.reason}
                      </span>
                    </div>
                  ))}
                </CardContent>
              </Card>
            )}

            {dossier.reversibleWithPrompt.length > 0 && (
              <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" aria-hidden /> Opt-in to undo (
                    {dossier.reversibleWithPrompt.length})
                  </CardTitle>
                </CardHeader>
                <CardContent className="text-xs space-y-2 text-amber-900">
                  {dossier.reversibleWithPrompt.map((r) => (
                    <label
                      key={r.id}
                      className="flex items-start gap-2 cursor-pointer rounded p-1 -mx-1 hover:bg-amber-100"
                    >
                      <Checkbox
                        checked={!!selected[r.id]}
                        onCheckedChange={(v) =>
                          setSelected((prev) => ({ ...prev, [r.id]: v === true }))
                        }
                        className="mt-0.5"
                      />
                      <span className="flex-1">
                        <span className="flex items-center gap-1.5 font-medium">
                          {iconFor(r.kind)} {r.label}
                        </span>
                        <span className="text-xs">{r.reason}</span>
                      </span>
                    </label>
                  ))}
                </CardContent>
              </Card>
            )}

            {dossier.locked.length > 0 && (
              <Card className="border-slate-300 bg-slate-50">
                <CardHeader className="pb-2">
                  <CardTitle className="text-sm font-medium text-slate-900 flex items-center gap-2">
                    <Lock className="h-4 w-4" aria-hidden /> Cannot be undone (
                    {dossier.locked.length})
                  </CardTitle>
                </CardHeader>
                <CardContent className="text-xs space-y-1.5 text-slate-700">
                  {dossier.locked.map((r) => (
                    <div key={r.id} className="flex items-start gap-2">
                      <span className="mt-0.5">{iconFor(r.kind)}</span>
                      <span>
                        <span className="font-medium">{r.label}</span> - {r.reason}.{' '}
                        <span className="italic">{r.lockReason}</span>
                      </span>
                    </div>
                  ))}
                </CardContent>
              </Card>
            )}
          </div>
        )}

        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button
            onClick={() => restoreMutation.mutate()}
            disabled={!dossier || restoreMutation.isPending}
          >
            {restoreMutation.isPending ? (
              <>
                <Loader2 className="h-4 w-4 animate-spin mr-1.5" aria-hidden /> Restoring…
              </>
            ) : (
              'Restore client'
            )}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
