'use client';

import { useState } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { Loader2, Plus, Save, Trash2 } from 'lucide-react';
import { toast } from 'sonner';

import { Button } from '@/components/ui/button';
import { DatePicker } from '@/components/ui/date-picker';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { apiFetch } from '@/lib/api/client';
import { toastError } from '@/lib/api/toast-error';

type SignatoryRole = 'client' | 'developer' | 'rep' | 'witness' | 'cc';

const ROLE_LABELS: Record<SignatoryRole, string> = {
  client: 'Client',
  developer: 'Developer',
  rep: 'Rep',
  witness: 'Witness',
  cc: 'CC (no signing)',
};

interface SignatoryRow {
  /** Existing rows carry the document_signers.id; new rows are added without
   *  one and the service treats them as inserts. */
  id?: string;
  name: string;
  email: string;
  role: SignatoryRole;
}

interface InitialState {
  title: string;
  /** YYYY-MM-DD slice - the DatePicker treats it as ISO date. */
  signedAt: string;
  notes: string;
  signatories: SignatoryRow[];
}

interface Props {
  open: boolean;
  onOpenChange: (next: boolean) => void;
  documentId: string;
  initial: InitialState;
}

/**
 * Edits an existing external-EOI document's metadata (title, signed
 * date, notes, signatories). Backed by `PATCH /api/v1/documents/[id]/metadata`,
 * which refuses on Documenso-managed docs - so the caller (detail page)
 * already gates rendering on `isManualUpload`.
 *
 * Mirrors the upload-side dialog's signatory shape so the on-screen
 * affordances feel identical to the rep.
 */
export function ExternalEoiEditDialog({ open, onOpenChange, documentId, initial }: Props) {
  // State is initialised once per mount; the parent guarantees a fresh
  // mount on every open by only rendering this component when the
  // dialog is open. That avoids a setState-in-effect re-hydration
  // pattern (banned by lint) - the dialog's open lifecycle IS the
  // initialisation trigger.
  const qc = useQueryClient();
  const [title, setTitle] = useState(initial.title);
  const [signedAt, setSignedAt] = useState(initial.signedAt);
  const [notes, setNotes] = useState(initial.notes);
  const [signatories, setSignatories] = useState<SignatoryRow[]>(initial.signatories);

  const mutation = useMutation({
    mutationFn: async () => {
      const trimmed = signatories.map((s) => ({
        ...(s.id ? { id: s.id } : {}),
        name: s.name.trim(),
        email: s.email.trim(),
        role: s.role,
      }));
      // Block invalid rows client-side so the rep doesn't get a generic
      // 400 they have to map back to a row.
      const invalid = trimmed.find((s) => !s.name || !s.email);
      if (invalid) {
        throw new Error('Every signatory needs a name + email.');
      }
      await apiFetch(`/api/v1/documents/${documentId}/metadata`, {
        method: 'PATCH',
        body: {
          title: title.trim(),
          signedAt,
          notes,
          signatories: trimmed,
        },
      });
    },
    onSuccess: () => {
      toast.success('Metadata updated');
      void qc.invalidateQueries({ queryKey: ['document-detail', documentId] });
      onOpenChange(false);
    },
    onError: (err) => {
      toastError(err);
    },
  });

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-3xl lg:max-w-5xl">
        <DialogHeader>
          <DialogTitle>Edit document metadata</DialogTitle>
          <DialogDescription>
            Adjust the title, signing date, notes, and signatories on this externally-signed EOI.
            The PDF itself stays put. This only edits the recorded metadata.
          </DialogDescription>
        </DialogHeader>

        <div className="space-y-4 py-2">
          <div>
            <Label htmlFor="edit-eoi-title">Title</Label>
            <Input
              id="edit-eoi-title"
              value={title}
              onChange={(e) => setTitle(e.target.value)}
              className="mt-1"
            />
          </div>

          <div>
            <Label>Date signed</Label>
            <div className="mt-1">
              <DatePicker value={signedAt} onChange={setSignedAt} toDate={new Date()} />
            </div>
          </div>

          <div className="space-y-2">
            <Label>Signatories</Label>
            <div className="space-y-2">
              {signatories.map((s, i) => (
                <div key={s.id ?? `new-${i}`} className="flex gap-2 items-center">
                  <Input
                    placeholder="Name"
                    value={s.name}
                    onChange={(e) =>
                      setSignatories((rows) =>
                        rows.map((r, idx) => (idx === i ? { ...r, name: e.target.value } : r)),
                      )
                    }
                    className="flex-1 min-w-0"
                  />
                  <Input
                    type="email"
                    placeholder="email@example.com"
                    value={s.email}
                    onChange={(e) =>
                      setSignatories((rows) =>
                        rows.map((r, idx) => (idx === i ? { ...r, email: e.target.value } : r)),
                      )
                    }
                    className="flex-[2] min-w-0"
                  />
                  <Select
                    value={s.role}
                    onValueChange={(v) =>
                      setSignatories((rows) =>
                        rows.map((r, idx) => (idx === i ? { ...r, role: v as SignatoryRole } : r)),
                      )
                    }
                  >
                    <SelectTrigger className="w-36 shrink-0">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      {(Object.keys(ROLE_LABELS) as SignatoryRole[]).map((r) => (
                        <SelectItem key={r} value={r}>
                          {ROLE_LABELS[r]}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                  <Button
                    type="button"
                    variant="ghost"
                    size="icon"
                    onClick={() => setSignatories((rows) => rows.filter((_, idx) => idx !== i))}
                    aria-label="Remove signatory"
                    className="shrink-0"
                  >
                    <Trash2 className="size-4" aria-hidden />
                  </Button>
                </div>
              ))}
            </div>
            <Button
              type="button"
              variant="outline"
              size="sm"
              onClick={() =>
                setSignatories((rows) => [...rows, { name: '', email: '', role: 'client' }])
              }
            >
              <Plus className="size-4 mr-1.5" aria-hidden />
              Add signatory
            </Button>
            <p className="text-xs text-muted-foreground">
              CC entries are recorded but excluded from the X / Y signed badge.
            </p>
          </div>

          <div>
            <Label htmlFor="edit-eoi-notes">Notes</Label>
            <Textarea
              id="edit-eoi-notes"
              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={mutation.isPending || !title.trim()}>
            {mutation.isPending ? (
              <Loader2 className="h-3.5 w-3.5 animate-spin mr-1.5" aria-hidden />
            ) : (
              <Save className="h-3.5 w-3.5 mr-1.5" aria-hidden />
            )}
            Save changes
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
