import { useEffect, useState } from "react";
import { Download, FolderDown } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Checkbox } from "@/components/ui/checkbox";
import { supabase } from "@/integrations/supabase/client";
import { useToast } from "@/hooks/use-toast";
import jsPDF from "jspdf";
import autoTable from "jspdf-autotable";
import { format } from "date-fns";
import { embedValidationProof } from "@/lib/embedValidationProof";
import { storeValidatedPdf } from "@/lib/storeValidatedPdf";
import { SaveToDocumentsDialog } from "@/components/SaveToDocumentsDialog";
import { buildSecureStorageKey } from "@/lib/secureStorageNaming";
import { toast as sonnerToast } from "sonner";

const MEETING_TYPES = [
  "Annual Membership Meeting",
  "Special Membership Meeting",
  "Board of Directors Meeting",
  "Special Board Meeting",
  "Budget Meeting",
  "Turnover Meeting",
  "Election Meeting",
];

const MAILING_DAYS = [
  { value: "60", label: "Sixty (60) Days" },
  { value: "30", label: "Thirty (30) Days" },
  { value: "14", label: "Fourteen (14) Days" },
];

const STATUTES = [
  { value: "720", label: "§720.306(1)(d)(5) — HOA" },
  { value: "718", label: "§718.112(2)(d)3 — Condo" },
];

const STATUTE_TEXT = {
  "720": "§720.306(1)(d)(5)",
  "718": "§718.112(2)(d)3",
};

export default function AffidavitOfMailingForm() {
  const { toast } = useToast();
  const [associations, setAssociations] = useState([]);
  const [selectedAssociation, setSelectedAssociation] = useState("");
  const [association, setAssociation] = useState(null);
  const [mailingDate, setMailingDate] = useState(format(new Date(), "yyyy-MM-dd"));
  const [meetingType, setMeetingType] = useState("Annual Membership Meeting");
  const [mailingDays, setMailingDays] = useState("14");
  const [statute, setStatute] = useState("720");
  const [signerName, setSignerName] = useState("Thomas R. Barnhart");
  const [signerTitle, setSignerTitle] = useState("Manager");
  const [signerCredentials, setSignerCredentials] = useState("Thomas R. Barnhart, LCAM");
  const [county, setCounty] = useState("Brevard");
  const [attachOwnerRoster, setAttachOwnerRoster] = useState(true);
  const [embedValidation, setEmbedValidation] = useState(true);
  const [showSaveDocsDialog, setShowSaveDocsDialog] = useState(false);
  const [owners, setOwners] = useState([]);
  const [logoUrl, setLogoUrl] = useState("");

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

  useEffect(() => {
    if (!selectedAssociation) {
      setAssociation(null);
      setLogoUrl("");
      setOwners([]);
      return;
    }
    supabase
      .from("associations")
      .select("*")
      .eq("id", selectedAssociation)
      .single()
      .then(({ data }) => {
        if (data) {
          setAssociation(data);
          setLogoUrl(data.logo_url || "");
        }
      });
    supabase
      .from("owners")
      .select("first_name, last_name, email, mailing_address, property_address, electronic_consent")
      .eq("association_id", selectedAssociation)
      .eq("status", "active")
      .order("property_address")
      .then(({ data }) => { if (data) setOwners(data); });
  }, [selectedAssociation]);

  const formatDateWordy = (dateStr) => {
    const d = new Date(dateStr + "T12:00:00");
    return format(d, "MMMM d, yyyy");
  };

  const getOrdinalDay = (dateStr) => {
    const d = new Date(dateStr + "T12:00:00");
    const day = d.getDate();
    const s = ["th", "st", "nd", "rd"];
    const v = day % 100;
    return `${day}${s[(v - 20) % 10] || s[v] || s[0]}`;
  };

  const getMonthName = (dateStr) => {
    const d = new Date(dateStr + "T12:00:00");
    return format(d, "MMMM");
  };

  const getYear = (dateStr) => {
    const d = new Date(dateStr + "T12:00:00");
    return format(d, "yyyy");
  };

  const getDaysWord = () => {
    const map = { "60": "sixty (60)", "30": "thirty (30)", "14": "fourteen (14)" };
    return map[mailingDays] || mailingDays;
  };

  const generatePdf = async () => {
    if (!association) {
      toast({ title: "Select an association", variant: "destructive" });
      return null;
    }

    const doc = new jsPDF({ orientation: "portrait", unit: "pt", format: "letter" });
    const pageW = doc.internal.pageSize.getWidth();
    const margin = 60;
    const contentW = pageW - margin * 2;
    const bodySize = 10.5;
    const bodyLeading = 15;
    const sectionGap = 22;
    let y = 60;

    // Logo
    if (logoUrl) {
      try {
        const img = new Image();
        img.crossOrigin = "anonymous";
        await new Promise((resolve, reject) => {
          img.onload = resolve;
          img.onerror = reject;
          img.src = logoUrl;
        });
        const ratio = img.width / img.height;
        const logoH = 50;
        const logoW = logoH * ratio;
        doc.addImage(img, "PNG", pageW - margin - logoW, y, logoW, logoH);
      } catch (e) {
        console.warn("Logo load failed:", e);
      }
    }

    // Title
    doc.setFont("helvetica", "bold");
    doc.setFontSize(18);
    doc.setTextColor(0, 0, 0);
    doc.text("AFFIDAVIT OF MAILING", margin, y + 18);

    y += 34;
    doc.setFontSize(11);
    doc.setFont("helvetica", "bolditalic");
    doc.text(`${getYear(mailingDate)} ${meetingType}`, margin, y);

    // State / County
    y += sectionGap;
    doc.setFont("helvetica", "bold");
    doc.setFontSize(bodySize);
    doc.text("STATE OF FLORIDA", margin, y);
    y += bodyLeading;
    doc.text(`COUNTY OF ${county.toUpperCase()}`, margin, y);

    // Body paragraph
    y += sectionGap;
    doc.setFont("helvetica", "normal");
    doc.setFontSize(bodySize);

    const meetingTypeUpper = meetingType.toUpperCase();
    const bodyText = `I, ${signerName.toUpperCase()}, on behalf of Secretary of the ${association.name}, being first duly sworn, deposes and says that the notice of the ${meetingTypeUpper} was mailed, hand delivered, or electronically sent to each unit owner at the address last furnished to the Association in accordance with the requirements of Section ${STATUTE_TEXT[statute]} Florida Statutes, at least ${getDaysWord()} days prior to the noticed meeting, or other matter of non-specified date, on ${formatDateWordy(mailingDate)}.`;

    const lines = doc.splitTextToSize(bodyText, contentW);
    for (let i = 0; i < lines.length; i++) {
      doc.text(lines[i], margin, y + i * bodyLeading);
    }
    y += lines.length * bodyLeading + 6;

    // Dated line
    doc.text(`Dated this ${getOrdinalDay(mailingDate)} day of ${getMonthName(mailingDate)}, ${getYear(mailingDate)}.`, margin, y);
    y += sectionGap;

    // BY line
    doc.setFont("helvetica", "bold");
    doc.text(`BY: ${signerName}, ${signerTitle}`, margin, y);

    // Signature line
    y += 44;
    doc.setDrawColor(0, 0, 0);
    doc.setLineWidth(0.6);
    doc.line(margin, y, margin + 250, y);
    y += 13;
    doc.setFont("helvetica", "italic");
    doc.setFontSize(9);
    doc.text(signerCredentials, margin, y);

    // Notary section
    y += 40;
    doc.setFont("helvetica", "bold");
    doc.setFontSize(bodySize);
    doc.text("STATE OF FLORIDA", margin, y);
    y += bodyLeading;
    doc.text(`COUNTY OF ${county.toUpperCase()}`, margin, y);

    y += sectionGap;
    doc.setFont("helvetica", "normal");
    doc.setFontSize(bodySize);

    const notaryText = `The foregoing Affidavit was acknowledged before me this ${getOrdinalDay(mailingDate)} day of ${getMonthName(mailingDate)}, ${getYear(mailingDate)} by ${signerName}, the Community Association Manager for ${association.name}, who is personally known to me or, produced Florida Driver's License No.: N/A.`;
    const notaryLines = doc.splitTextToSize(notaryText, contentW);
    for (let i = 0; i < notaryLines.length; i++) {
      doc.text(notaryLines[i], margin, y + i * bodyLeading);
    }
    y += notaryLines.length * bodyLeading + sectionGap;

    // Notary signature line
    doc.setLineWidth(0.6);
    doc.line(margin, y, margin + 270, y);
    y += 13;
    doc.setFont("helvetica", "normal");
    doc.setFontSize(10);
    doc.text("NOTARY PUBLIC", margin, y);

    y += 34;
    doc.setFont("helvetica", "bold");
    doc.text("(SEAL)", margin, y);

    // Owner roster pages — split by delivery method
    if (attachOwnerRoster && owners.length > 0) {
      const mailedOwners = owners.filter((o) => !o.electronic_consent);
      const electronicOwners = owners.filter((o) => o.electronic_consent);

      // --- U.S. Mail Recipients ---
      if (mailedOwners.length > 0) {
        doc.addPage();
        doc.setFont("helvetica", "bold");
        doc.setFontSize(13);
        doc.setTextColor(0, 0, 0);
        doc.text("Owner Roster — U.S. Mail Recipients", margin, 50);

        doc.setFont("helvetica", "normal");
        doc.setFontSize(8.5);
        doc.setTextColor(80, 80, 80);
        doc.text(`${association.name}  •  ${formatDateWordy(mailingDate)}  •  ${mailedOwners.length} owner(s) via U.S. Mail`, margin, 64);

        const groupedMail = {};
        for (const o of mailedOwners) {
          const addr = o.property_address || "—";
          if (!groupedMail[addr]) groupedMail[addr] = [];
          groupedMail[addr].push(o);
        }
        const sortedMailAddrs = Object.keys(groupedMail).sort((a, b) => a.localeCompare(b));
        const mailTableBody = sortedMailAddrs.map((addr, i) => {
          const names = groupedMail[addr].map((o) => `${o.first_name || ""} ${o.last_name || ""}`.trim()).join(", ");
          const mailing = groupedMail[addr][0].mailing_address || "—";
          return [i + 1, names, addr, mailing];
        });

        autoTable(doc, {
          startY: 76,
          head: [["#", "Owner Name", "Property Address", "Mailing Address"]],
          body: mailTableBody,
          margin: { left: margin, right: margin },
          styles: { fontSize: 7.5, cellPadding: 3.5, font: "helvetica" },
          headStyles: { fillColor: [26, 26, 46], textColor: 255, fontSize: 7.5, fontStyle: "bold" },
          alternateRowStyles: { fillColor: [245, 247, 250] },
          columnStyles: { 0: { cellWidth: 24 }, 1: { cellWidth: 120 }, 2: { cellWidth: 'auto' }, 3: { cellWidth: 'auto' } },
        });
      }

      // --- Electronic Consent Recipients ---
      if (electronicOwners.length > 0) {
        doc.addPage();
        doc.setFont("helvetica", "bold");
        doc.setFontSize(13);
        doc.setTextColor(0, 0, 0);
        doc.text("Owner Roster — Electronic Consent Recipients", margin, 50);

        doc.setFont("helvetica", "normal");
        doc.setFontSize(8.5);
        doc.setTextColor(80, 80, 80);
        doc.text(`${association.name}  •  ${formatDateWordy(mailingDate)}  •  ${electronicOwners.length} owner(s) via electronic delivery`, margin, 64);

        const groupedElec = {};
        for (const o of electronicOwners) {
          const addr = o.property_address || "—";
          if (!groupedElec[addr]) groupedElec[addr] = [];
          groupedElec[addr].push(o);
        }
        const sortedElecAddrs = Object.keys(groupedElec).sort((a, b) => a.localeCompare(b));
        const elecTableBody = sortedElecAddrs.map((addr, i) => {
          const group = groupedElec[addr];
          const names = group.map((o) => `${o.first_name || ""} ${o.last_name || ""}`.trim()).join(", ");
          const emails = [...new Set(group.map((o) => o.email || "—"))].join(", ");
          return [i + 1, names, addr, emails];
        });

        autoTable(doc, {
          startY: 76,
          head: [["#", "Owner Name", "Property Address", "Email Address"]],
          body: elecTableBody,
          margin: { left: margin, right: margin },
          styles: { fontSize: 7.5, cellPadding: 3.5, font: "helvetica" },
          headStyles: { fillColor: [10, 80, 60], textColor: 255, fontSize: 7.5, fontStyle: "bold" },
          alternateRowStyles: { fillColor: [240, 250, 245] },
          columnStyles: { 0: { cellWidth: 24 }, 1: { cellWidth: 120 }, 2: { cellWidth: 'auto' }, 3: { cellWidth: 'auto' } },
        });
      }
    }

    // Validation proof
    let proof = null;
    if (embedValidation) {
      try {
        proof = await embedValidationProof(doc, {
          documentTitle: `Affidavit of Mailing — ${association.name}`,
          documentType: "affidavit_of_mailing",
          documentDate: formatDateWordy(mailingDate),
          associationId: selectedAssociation,
          metadata: { meetingType, mailingDays, statute: STATUTE_TEXT[statute] },
        });
      } catch (e) {
        console.error("Validation embed error:", e);
      }
    }

    return { doc, proof };
  };

  const handleDownload = async () => {
    const result = await generatePdf();
    if (!result) return;
    const { doc, proof } = result;

    if (proof) {
      const fileName = `affidavit_of_mailing-${format(new Date(), "yyyy-MM-dd")}.pdf`;
      await storeValidatedPdf(doc, proof.id, fileName);
    }

    doc.save(`affidavit_of_mailing-${format(new Date(), "yyyy-MM-dd")}.pdf`);
    sonnerToast.success("PDF downloaded");
  };

  const handleSaveToDocs = async (metadata) => {
    const result = await generatePdf();
    if (!result) return;
    const { doc, proof } = result;

    if (proof) {
      const fileName = `affidavit_of_mailing-${format(new Date(), "yyyy-MM-dd")}.pdf`;
      await storeValidatedPdf(doc, proof.id, fileName);
    }

    const blob = doc.output("blob");
    // Display name kept human-readable; storage key is randomized.
    const displayFileName = `${(metadata.name || `affidavit_of_mailing-${format(new Date(), "yyyy-MM-dd")}`).replace(/[^a-zA-Z0-9._ -]+/g, "_").trim()}.pdf`;
    const filePath = buildSecureStorageKey("doc.pdf", `documents/${metadata.clientId}`);

    const { error: uploadErr } = await supabase.storage
      .from("files")
      .upload(filePath, blob, { contentType: "application/pdf", upsert: true });

    if (uploadErr) {
      sonnerToast.error("Upload failed: " + uploadErr.message);
      return;
    }

    const { data: { publicUrl } } = supabase.storage.from("files").getPublicUrl(filePath);
    const { data: { user: userData } } = await supabase.auth.getUser();

    const { error: docError } = await supabase.from("documents").insert({
      title: metadata.name,
      file_url: publicUrl,
      file_name: displayFileName,
      file_size: blob.size,
      association_id: metadata.clientId,
      category: metadata.category || "general",
      uploaded_by: userData?.id,
    });

    if (docError) {
      sonnerToast.error("Save error: " + docError.message);
    } else {
      sonnerToast.success("Saved to Documents");
    }
    return { blob };
  };

  return (
    <div className="space-y-4">
      <Card>
        <CardHeader className="pb-3">
          <CardTitle className="text-lg">Affidavit of Mailing</CardTitle>
        </CardHeader>
        <CardContent className="space-y-4">
          {/* Association */}
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div>
              <Label>Association</Label>
              <Select value={selectedAssociation} onValueChange={setSelectedAssociation}>
                <SelectTrigger><SelectValue placeholder="Select association" /></SelectTrigger>
                <SelectContent>
                  {associations.map((a) => (
                    <SelectItem key={a.id} value={a.id}>{a.name}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>

            <div>
              <Label>Meeting Type</Label>
              <Select value={meetingType} onValueChange={setMeetingType}>
                <SelectTrigger><SelectValue /></SelectTrigger>
                <SelectContent>
                  {MEETING_TYPES.map((t) => (
                    <SelectItem key={t} value={t}>{t}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          </div>

          <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
            <div>
              <Label>Mailing Date</Label>
              <Input type="date" value={mailingDate} onChange={(e) => setMailingDate(e.target.value)} />
            </div>

            <div>
              <Label>Required Notice Period</Label>
              <Select value={mailingDays} onValueChange={setMailingDays}>
                <SelectTrigger><SelectValue /></SelectTrigger>
                <SelectContent>
                  {MAILING_DAYS.map((d) => (
                    <SelectItem key={d.value} value={d.value}>{d.label}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>

            <div>
              <Label>Applicable Statute</Label>
              <Select value={statute} onValueChange={setStatute}>
                <SelectTrigger><SelectValue /></SelectTrigger>
                <SelectContent>
                  {STATUTES.map((s) => (
                    <SelectItem key={s.value} value={s.value}>{s.label}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          </div>

          <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
            <div>
              <Label>Signer Name</Label>
              <Input value={signerName} onChange={(e) => setSignerName(e.target.value)} />
            </div>
            <div>
              <Label>Signer Title</Label>
              <Input value={signerTitle} onChange={(e) => setSignerTitle(e.target.value)} />
            </div>
            <div>
              <Label>Credentials Line</Label>
              <Input value={signerCredentials} onChange={(e) => setSignerCredentials(e.target.value)} />
            </div>
          </div>

          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div>
              <Label>County</Label>
              <Input value={county} onChange={(e) => setCounty(e.target.value)} />
            </div>
          </div>

          {/* Options */}
          <div className="flex flex-wrap gap-6 pt-2">
            <label className="flex items-center gap-2 text-sm">
              <Checkbox checked={attachOwnerRoster} onCheckedChange={setAttachOwnerRoster} />
              Attach Owner Roster ({owners.length} owners)
            </label>
            <label className="flex items-center gap-2 text-sm">
              <Checkbox checked={embedValidation} onCheckedChange={setEmbedValidation} />
              Embed Validation Proof QR
            </label>
          </div>

          {/* Actions */}
          <div className="flex gap-3 pt-2">
            <Button onClick={handleDownload} className="gap-2">
              <Download className="w-4 h-4" /> Download PDF
            </Button>
            <Button variant="outline" onClick={() => setShowSaveDocsDialog(true)} className="gap-2">
              <FolderDown className="w-4 h-4" /> Save to Docs
            </Button>
          </div>
        </CardContent>
      </Card>

      <SaveToDocumentsDialog
        open={showSaveDocsDialog}
        onOpenChange={setShowSaveDocsDialog}
        onSave={handleSaveToDocs}
        defaultName={`Affidavit of Mailing — ${association?.name || ""}`}
        associationId={selectedAssociation}
      />
    </div>
  );
}
