'use client';

import { useState } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { AlertTriangle, Loader2, Mail } 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 { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { apiFetch } from '@/lib/api/client';
import { toastError } from '@/lib/api/toast-error';

interface Props {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  clientIds: string[];
  onDeleted?: (deletedCount: number) => void;
}

type Stage = 'intent' | 'confirm' | 'partial';

interface SkippedRow {
  clientId: string;
  reason: string;
}

/**
 * Key-based remount of the body when the dialog opens - fresh state per
 * open without an open→reset useEffect (React Compiler-safe).
 */
export function BulkHardDeleteDialog(props: Props) {
  return (
    <Dialog open={props.open} onOpenChange={props.onOpenChange}>
      <DialogContent className="sm:max-w-md">
        {props.open && <BulkHardDeleteDialogBody key={props.clientIds.join(',')} {...props} />}
      </DialogContent>
    </Dialog>
  );
}

function BulkHardDeleteDialogBody({ onOpenChange, clientIds, onDeleted }: Props) {
  const qc = useQueryClient();
  const [stage, setStage] = useState<Stage>('intent');
  const [code, setCode] = useState('');
  const [typedPhrase, setTypedPhrase] = useState('');
  const [maskedEmail, setMaskedEmail] = useState<string | null>(null);
  const [skipped, setSkipped] = useState<SkippedRow[]>([]);
  const [partialDeleted, setPartialDeleted] = useState(0);

  const expectedPhrase = `DELETE ${clientIds.length} CLIENT${clientIds.length === 1 ? '' : 'S'}`;

  const requestCode = useMutation({
    mutationFn: () =>
      apiFetch<{ data: { count: number; sentToMaskedEmail: string } }>(
        '/api/v1/clients/bulk-hard-delete-request',
        { method: 'POST', body: { ids: clientIds } },
      ),
    onSuccess: (res) => {
      setMaskedEmail(res.data.sentToMaskedEmail);
      setStage('confirm');
      toast.success(`Code sent to ${res.data.sentToMaskedEmail}`);
    },
    onError: (err: unknown) => {
      toastError(err, 'Failed to send code');
    },
  });

  const bulkDelete = useMutation({
    mutationFn: () =>
      apiFetch<{
        data: { deletedCount: number; skipped: SkippedRow[] };
      }>('/api/v1/clients/bulk-hard-delete', {
        method: 'POST',
        body: { ids: clientIds, code, typedPhrase },
      }),
    onSuccess: (res) => {
      const n = res.data.deletedCount;
      const skippedRows = res.data.skipped ?? [];
      qc.invalidateQueries({ queryKey: ['clients'] });
      if (skippedRows.length === 0) {
        toast.success(`${n} client${n === 1 ? '' : 's'} permanently deleted.`);
        onOpenChange(false);
        onDeleted?.(n);
      } else {
        // Stay open so the operator can see exactly which IDs were
        // skipped and why (e.g. unarchived between preflight + execute,
        // already deleted by another operator).
        setSkipped(skippedRows);
        setPartialDeleted(n);
        setStage('partial');
        toast.warning(`${n} of ${clientIds.length} deleted. ${skippedRows.length} skipped.`);
      }
    },
    onError: (err: unknown) => {
      toastError(err, 'Bulk delete failed');
    },
  });

  const phraseMatches = typedPhrase.trim().toUpperCase() === expectedPhrase;
  const codeValid = /^\d{4}$/.test(code.trim());

  return (
    <>
      <DialogHeader>
        <DialogTitle className="flex items-center gap-2 text-destructive">
          <AlertTriangle className="h-5 w-5" aria-hidden />
          Permanently delete {clientIds.length} client{clientIds.length === 1 ? '' : 's'}
        </DialogTitle>
        <DialogDescription>
          All selected clients must already be archived. This cannot be undone.
        </DialogDescription>
      </DialogHeader>

      {stage === 'intent' && (
        <div className="space-y-3 text-sm text-muted-foreground">
          <p>
            We&rsquo;ll email a 4-digit confirmation code to your account address. The code is tied
            to this exact set of clients and expires in 10 minutes.
          </p>
          <div className="rounded-md border border-amber-300 bg-amber-50 p-3 text-amber-900 text-xs">
            For each client we delete: client record + addresses, contacts, notes, tags, portal
            user, GDPR records, all interests, all tenancies. Signed documents, email threads, files
            and reminders are detached but kept.
          </div>
        </div>
      )}

      {stage === 'confirm' && (
        <div className="space-y-3">
          <div className="flex items-start gap-2 rounded-md border border-blue-300 bg-blue-50 p-3 text-xs text-blue-900">
            <Mail className="h-4 w-4 shrink-0 mt-0.5" aria-hidden />
            <div>
              Code sent to <span className="font-mono">{maskedEmail}</span>. Enter both fields
              below.
            </div>
          </div>
          <div className="space-y-1.5">
            <Label htmlFor="bhd-code">4-digit code from email</Label>
            <Input
              id="bhd-code"
              inputMode="numeric"
              maxLength={4}
              value={code}
              onChange={(e) => setCode(e.target.value.replace(/\D/g, ''))}
              placeholder="0000"
              className="font-mono tracking-[0.4em] text-center text-lg"
              autoComplete="off"
            />
          </div>
          <div className="space-y-1.5">
            <Label htmlFor="bhd-phrase">
              Type <span className="font-mono font-semibold">{expectedPhrase}</span> to confirm
            </Label>
            <Input
              id="bhd-phrase"
              value={typedPhrase}
              onChange={(e) => setTypedPhrase(e.target.value)}
              placeholder={expectedPhrase}
              autoComplete="off"
              className="font-mono"
            />
          </div>
        </div>
      )}

      {stage === 'partial' && (
        <div className="space-y-3 text-sm">
          <div className="rounded-md border border-amber-300 bg-amber-50 p-3 text-amber-900">
            {partialDeleted} of {clientIds.length} permanently deleted. {skipped.length} skipped -
            see below.
          </div>
          <div className="rounded-md border max-h-60 overflow-y-auto">
            <table className="w-full text-xs">
              <thead className="bg-muted/50 sticky top-0">
                <tr>
                  <th scope="col" className="text-left px-2 py-1.5 font-medium">
                    Client ID
                  </th>
                  <th scope="col" className="text-left px-2 py-1.5 font-medium">
                    Reason
                  </th>
                </tr>
              </thead>
              <tbody>
                {skipped.map((row) => (
                  <tr key={row.clientId} className="border-t">
                    <td className="px-2 py-1.5 font-mono text-xs">{row.clientId.slice(0, 8)}…</td>
                    <td className="px-2 py-1.5">{row.reason}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}

      <DialogFooter>
        {stage !== 'partial' && (
          <Button variant="outline" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
        )}
        {stage === 'intent' && (
          <Button
            variant="destructive"
            onClick={() => requestCode.mutate()}
            disabled={requestCode.isPending}
          >
            {requestCode.isPending ? (
              <>
                <Loader2 className="h-4 w-4 animate-spin mr-1.5" aria-hidden /> Sending…
              </>
            ) : (
              'Send confirmation code'
            )}
          </Button>
        )}
        {stage === 'confirm' && (
          <Button
            variant="destructive"
            onClick={() => bulkDelete.mutate()}
            disabled={!codeValid || !phraseMatches || bulkDelete.isPending}
          >
            {bulkDelete.isPending ? (
              <>
                <Loader2 className="h-4 w-4 animate-spin mr-1.5" aria-hidden /> Deleting…
              </>
            ) : (
              `Permanently delete ${clientIds.length}`
            )}
          </Button>
        )}
        {stage === 'partial' && (
          <Button
            onClick={() => {
              onOpenChange(false);
              onDeleted?.(partialDeleted);
            }}
          >
            Done
          </Button>
        )}
      </DialogFooter>
    </>
  );
}
