import { useState, useEffect } from "react";
import { supabase } from "@/integrations/supabase/client";
import { useToast } from "@/hooks/use-toast";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from "@/components/ui/dialog";
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 { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Badge } from "@/components/ui/badge";
import { Loader2, Send, Plus, X, FileSignature, UserPlus } from "lucide-react";
import { extractDocuSignFunctionError } from "@/lib/docusign";

interface Recipient {
  name: string;
  email: string;
}

function arrayBufferToBase64(buffer: ArrayBuffer) {
  const bytes = new Uint8Array(buffer);
  const chunkSize = 0x8000;
  let binary = "";

  for (let index = 0; index < bytes.length; index += chunkSize) {
    const chunk = bytes.subarray(index, index + chunkSize);
    binary += String.fromCharCode(...chunk);
  }

  return btoa(binary);
}

interface DocuSignSendDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  /** Pre-fill with a document URL from storage */
  documentUrl?: string;
  documentName?: string;
  associationId?: string;
  onSuccess?: () => void;
}

export default function DocuSignSendDialog({
  open,
  onOpenChange,
  documentUrl,
  documentName: initialDocName,
  associationId: initialAssocId,
  onSuccess,
}: DocuSignSendDialogProps) {
  const { toast } = useToast();
  const [sending, setSending] = useState(false);
  const [associations, setAssociations] = useState<any[]>([]);
  const [associationId, setAssociationId] = useState(initialAssocId || "");
  const [documentName, setDocumentName] = useState(initialDocName || "");
  const [emailSubject, setEmailSubject] = useState("");
  const [emailBody, setEmailBody] = useState("");
  const [recipients, setRecipients] = useState<Recipient[]>([{ name: "", email: "" }]);
  const [file, setFile] = useState<File | null>(null);
  const [consentUrl, setConsentUrl] = useState<string | null>(null);

  useEffect(() => {
    if (open) {
      setConsentUrl(null);
      supabase
        .from("associations")
        .select("id, name")
        .eq("status", "active")
        .order("name")
        .then(({ data }) => setAssociations(data || []));

      if (initialAssocId) setAssociationId(initialAssocId);
      if (initialDocName) setDocumentName(initialDocName);
    }
  }, [open, initialAssocId, initialDocName]);

  const addRecipient = () => setRecipients([...recipients, { name: "", email: "" }]);

  const removeRecipient = (idx: number) => {
    if (recipients.length <= 1) return;
    setRecipients(recipients.filter((_, i) => i !== idx));
  };

  const updateRecipient = (idx: number, field: keyof Recipient, value: string) => {
    const updated = [...recipients];
    updated[idx] = { ...updated[idx], [field]: value };
    setRecipients(updated);
  };

  const handleSend = async () => {
    // Validate
    if (!associationId) {
      toast({ variant: "destructive", title: "Select an association" });
      return;
    }
    const validRecipients = recipients.filter((r) => r.name.trim() && r.email.trim());
    if (validRecipients.length === 0) {
      toast({ variant: "destructive", title: "Add at least one recipient with name and email" });
      return;
    }
    if (!file && !documentUrl) {
      toast({ variant: "destructive", title: "Upload a document or provide a document URL" });
      return;
    }

    setSending(true);
    try {
      let base64Doc: string;
      let ext = "pdf";

      if (file) {
        // Read file as base64
        const buffer = await file.arrayBuffer();
        base64Doc = arrayBufferToBase64(buffer);
        ext = file.name.split(".").pop() || "pdf";
        if (!documentName) setDocumentName(file.name);
      } else if (documentUrl) {
        // Fetch from storage URL
        const res = await fetch(documentUrl);
        const blob = await res.blob();
        const buffer = await blob.arrayBuffer();
        base64Doc = arrayBufferToBase64(buffer);
        ext = documentUrl.split(".").pop()?.split("?")[0] || "pdf";
      } else {
        throw new Error("No document provided");
      }

      const { data, error } = await supabase.functions.invoke("docusign-send", {
        body: {
          action: "send",
          association_id: associationId,
          document_name: documentName || file?.name || "Document",
          document_base64: base64Doc,
          file_extension: ext,
          recipients: validRecipients,
          email_subject: emailSubject || `Please sign: ${documentName || "Document"}`,
          email_body: emailBody || undefined,
        },
      });

      if (error) throw error;
      if (data?.error) throw new Error(data.error);

      setConsentUrl(null);

      toast({
        title: "Document Sent for Signing",
        description: `Envelope ${data.envelope_id} sent to ${validRecipients.length} recipient(s).`,
      });

      onSuccess?.();
      onOpenChange(false);

      // Reset form
      setRecipients([{ name: "", email: "" }]);
      setFile(null);
      setDocumentName("");
      setEmailSubject("");
      setEmailBody("");
    } catch (err: any) {
      console.error("DocuSign send error:", err);
      const parsedError = await extractDocuSignFunctionError(err);

      if (parsedError.code === "consent_required") {
        setConsentUrl(parsedError.consentUrl ?? null);
        toast({
          variant: "destructive",
          title: "DocuSign consent required",
          description: "Open the consent link, approve access, then try sending again.",
        });
        return;
      }

      toast({
        variant: "destructive",
        title: "Failed to Send",
        description: parsedError.message || "An error occurred while sending the document.",
      });
    } finally {
      setSending(false);
    }
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-lg max-h-[85vh] overflow-y-auto">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            <FileSignature className="h-5 w-5 text-primary" />
            Send for Signature
          </DialogTitle>
          <DialogDescription>
            Send a document via DocuSign for electronic signature.
          </DialogDescription>
        </DialogHeader>

        <div className="space-y-4 py-2">
          {/* Association */}
          <div className="space-y-1.5">
            <Label>Association</Label>
            <Select value={associationId} onValueChange={setAssociationId}>
              <SelectTrigger>
                <SelectValue placeholder="Select association" />
              </SelectTrigger>
              <SelectContent>
                {associations.map((a) => (
                  <SelectItem key={a.id} value={a.id}>{a.name}</SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          {/* Document Upload */}
          <div className="space-y-1.5">
            <Label>Document</Label>
            {documentUrl ? (
              <div className="flex items-center gap-2 p-2 bg-muted rounded-md text-sm">
                <FileSignature className="h-4 w-4 text-muted-foreground" />
                <span className="truncate flex-1">{documentName || "Linked document"}</span>
                <Badge variant="secondary" className="text-xs">From storage</Badge>
              </div>
            ) : (
              <Input
                type="file"
                accept=".pdf,.doc,.docx"
                onChange={(e) => {
                  const f = e.target.files?.[0] || null;
                  setFile(f);
                  if (f && !documentName) setDocumentName(f.name);
                }}
              />
            )}
          </div>

          {/* Document Name */}
          <div className="space-y-1.5">
            <Label>Document Name</Label>
            <Input
              placeholder="e.g., Estoppel Certificate"
              value={documentName}
              onChange={(e) => setDocumentName(e.target.value)}
            />
          </div>

          {/* Email Subject */}
          <div className="space-y-1.5">
            <Label>Email Subject (optional)</Label>
            <Input
              placeholder={`Please sign: ${documentName || "Document"}`}
              value={emailSubject}
              onChange={(e) => setEmailSubject(e.target.value)}
            />
          </div>

          {/* Email Body */}
          <div className="space-y-1.5">
            <Label>Message (optional)</Label>
            <Textarea
              placeholder="Please review and sign the attached document."
              value={emailBody}
              onChange={(e) => setEmailBody(e.target.value)}
              rows={2}
            />
          </div>

          {/* Recipients */}
          <div className="space-y-2">
            <div className="flex items-center justify-between">
              <Label>Recipients</Label>
              <Button type="button" variant="ghost" size="sm" onClick={addRecipient} className="gap-1 h-7 text-xs">
                <UserPlus className="h-3 w-3" /> Add Signer
              </Button>
            </div>
            {recipients.map((r, idx) => (
              <div key={idx} className="flex items-center gap-2">
                <Input
                  placeholder="Full name"
                  value={r.name}
                  onChange={(e) => updateRecipient(idx, "name", e.target.value)}
                  className="flex-1"
                />
                <Input
                  placeholder="Email"
                  type="email"
                  value={r.email}
                  onChange={(e) => updateRecipient(idx, "email", e.target.value)}
                  className="flex-1"
                />
                {recipients.length > 1 && (
                  <Button type="button" variant="ghost" size="icon" className="h-8 w-8 shrink-0" onClick={() => removeRecipient(idx)}>
                    <X className="h-3.5 w-3.5" />
                  </Button>
                )}
              </div>
            ))}
          </div>

          <div className="bg-muted/50 rounded-md p-3 text-xs text-muted-foreground space-y-1">
            <p className="font-medium text-foreground">Signature placement tips:</p>
            <p>• Add <code className="bg-muted px-1 rounded">/sig/</code> in your document where signatures should appear</p>
            <p>• Add <code className="bg-muted px-1 rounded">/date/</code> where the signed date should appear</p>
            <p>• DocuSign will automatically detect these anchors</p>
          </div>

          {consentUrl && (
            <div className="rounded-md border border-border bg-muted/50 p-3 space-y-2">
              <p className="text-sm font-medium text-foreground">DocuSign access needs one-time consent</p>
              <p className="text-xs text-muted-foreground">Open the consent page, approve access, then come back and resend the document.</p>
              <Button
                type="button"
                variant="outline"
                size="sm"
                onClick={() => window.open(consentUrl, "_blank", "noopener,noreferrer")}
              >
                Grant DocuSign Consent
              </Button>
            </div>
          )}
        </div>

        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)} disabled={sending}>
            Cancel
          </Button>
          <Button onClick={handleSend} disabled={sending} className="gap-2">
            {sending ? <Loader2 className="h-4 w-4 animate-spin" /> : <Send className="h-4 w-4" />}
            {sending ? "Sending..." : "Send for Signature"}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
