'use client';

import { useMemo, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { Loader2, Upload } from 'lucide-react';
import { toast } from 'sonner';

import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import { apiFetch } from '@/lib/api/client';
import { toastError } from '@/lib/api/toast-error';
import { formatBerthRange } from '@/lib/templates/berth-range';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';

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

export function ExternalEoiUploadDialog({ open, onOpenChange, interestId, onSuccess }: Props) {
  const qc = useQueryClient();
  const [file, setFile] = useState<File | null>(null);
  const [title, setTitle] = useState('');
  const [signedAt, setSignedAt] = useState(() => new Date().toISOString().slice(0, 10));
  const [signerNames, setSignerNames] = useState('');
  const [notes, setNotes] = useState('');

  // Fetched on open to power the default title:
  // "External EOI — <Client> — <berth range> — YYYY-MM-DD". Without
  // this the file lands as just "External EOI - <date>" which is
  // unscannable in any list when a port has multiple deals closing on
  // the same day.
  const { data: interestData } = useQuery<{ data: { clientName: string | null } }>({
    queryKey: ['interests', interestId],
    queryFn: () =>
      apiFetch<{ data: { clientName: string | null } }>(`/api/v1/interests/${interestId}`),
    enabled: open,
    staleTime: 60_000,
  });
  const { data: berthsData } = useQuery<{ data: Array<{ mooringNumber: string | null }> }>({
    queryKey: ['interests', interestId, 'berths'],
    queryFn: () =>
      apiFetch<{ data: Array<{ mooringNumber: string | null }> }>(
        `/api/v1/interests/${interestId}/berths`,
      ),
    enabled: open,
    staleTime: 60_000,
  });

  const defaultTitle = useMemo(() => {
    const date = signedAt || new Date().toISOString().slice(0, 10);
    const moorings = (berthsData?.data ?? [])
      .map((b) => b.mooringNumber)
      .filter((m): m is string => !!m);
    const berthLabel = moorings.length > 0 ? formatBerthRange(moorings) : null;
    const clientName = interestData?.data?.clientName ?? null;
    const parts = ['External EOI'];
    if (clientName) parts.push(clientName);
    if (berthLabel) parts.push(berthLabel);
    parts.push(date);
    return parts.join(' — ');
  }, [interestData, berthsData, signedAt]);

  const mutation = useMutation<{ data?: { stageChanged?: boolean } }, Error, void>({
    mutationFn: async () => {
      if (!file) throw new Error('No file selected');
      const form = new FormData();
      form.append('file', file);
      const effectiveTitle = title.trim() || defaultTitle;
      if (effectiveTitle) form.append('title', effectiveTitle);
      if (signedAt) form.append('signedAt', signedAt);
      if (signerNames) form.append('signerNames', signerNames);
      if (notes) form.append('notes', notes);
      const res = await fetch(`/api/v1/interests/${interestId}/external-eoi`, {
        method: 'POST',
        body: form,
        credentials: 'include',
      });
      if (!res.ok) {
        const err = (await res.json().catch(() => ({ error: 'Upload failed' }))) as {
          error?: string;
        };
        throw new Error(err.error ?? 'Upload failed');
      }
      return (await res.json()) as { data?: { stageChanged?: boolean } };
    },
    onSuccess: (response) => {
      const stageChanged = response?.data?.stageChanged === true;
      toast.success(
        stageChanged
          ? 'External EOI uploaded. Stage advanced to EOI Signed.'
          : 'External EOI uploaded. Filed against this deal (stage unchanged).',
      );
      qc.invalidateQueries({ queryKey: ['interests', interestId] });
      qc.invalidateQueries({ queryKey: ['interests'] });
      qc.invalidateQueries({ queryKey: ['documents'] });
      setFile(null);
      setTitle('');
      setSignerNames('');
      setNotes('');
      onOpenChange(false);
      onSuccess?.();
    },
    onError: (err: unknown) => {
      toastError(err, 'Upload failed');
    },
  });

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Upload externally-signed EOI</DialogTitle>
          <DialogDescription>
            For EOIs signed outside our signing service (paper, in person, alternate e-sign vendor).
            The uploaded PDF is filed against this interest and the pipeline stage is advanced to
            EOI Signed.
          </DialogDescription>
        </DialogHeader>

        <div className="space-y-3 py-2">
          <div>
            <Label>PDF file *</Label>
            <Input
              type="file"
              accept="application/pdf,.pdf"
              onChange={(e) => setFile(e.target.files?.[0] ?? null)}
              className="mt-1"
            />
          </div>
          <div>
            <Label>Title (optional)</Label>
            <Input
              value={title}
              onChange={(e) => setTitle(e.target.value)}
              placeholder={defaultTitle}
              className="mt-1"
            />
            <p className="text-xs text-muted-foreground mt-1">
              Leave blank to use the default shown above.
            </p>
          </div>
          <div>
            <Label>Date signed</Label>
            <Input
              type="date"
              value={signedAt}
              onChange={(e) => setSignedAt(e.target.value)}
              className="mt-1"
            />
          </div>
          <div>
            <Label>Signer names (comma-separated)</Label>
            <Input
              value={signerNames}
              onChange={(e) => setSignerNames(e.target.value)}
              placeholder="e.g. John Smith, Marina Director"
              className="mt-1"
            />
            <p className="text-xs text-muted-foreground mt-1">
              Recorded in the audit trail alongside the document.
            </p>
          </div>
          <div>
            <Label>Notes (optional)</Label>
            <Textarea
              value={notes}
              onChange={(e) => setNotes(e.target.value)}
              placeholder="Where / how this EOI was signed"
              rows={2}
              className="mt-1"
            />
          </div>
        </div>

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