import { jsPDF } from "jspdf";
import autoTable from "jspdf-autotable";
import { format } from "date-fns";
import { supabase } from "@/integrations/supabase/client";

/**
 * Generates and downloads a comprehensive single-ARC record PDF including:
 *  - Application details (project, owner, address, association, dates, status)
 *  - Vote tally + individual votes (committee/admin recorded)
 *  - Comment thread
 *  - Decision notes
 *  - Attachments list
 */
export async function generateArcApplicationRecord(application: any) {
  if (!application?.id) throw new Error("Missing application");

  // Fetch votes + comments + attachments + voter profile names + committee names
  const [votesRes, commentsRes, filesRes] = await Promise.all([
    supabase
      .from("entity_votes")
      .select("vote, voter_name, user_id, recorded_by, created_at")
      .eq("entity_type", "arc_application")
      .eq("entity_id", application.id)
      .order("created_at", { ascending: true }),
    supabase
      .from("entity_comments")
      .select("comment, user_id, created_at")
      .eq("entity_type", "arc_application")
      .eq("entity_id", application.id)
      .order("created_at", { ascending: true }),
    supabase
      .from("arc_files" as any)
      .select("file_name, file_url, created_at")
      .eq("application_id", application.id)
      .order("created_at", { ascending: true }),
  ]);

  const votes = votesRes.data || [];
  const comments = commentsRes.data || [];
  const files = (filesRes.data as any[]) || [];

  // Resolve user names
  const userIds = Array.from(
    new Set(
      [...votes, ...comments]
        .flatMap((r: any) => [r.user_id, r.recorded_by])
        .filter(Boolean) as string[],
    ),
  );
  let profilesById: Record<string, string> = {};
  if (userIds.length) {
    const { data: profs } = await supabase
      .from("profiles")
      .select("id, full_name, email")
      .in("id", userIds);
    profilesById = Object.fromEntries(
      (profs || []).map((p: any) => [p.id, p.full_name || p.email || "User"]),
    );
  }
  const nameFor = (v: any) =>
    v.voter_name ||
    (v.user_id && profilesById[v.user_id]) ||
    "Unknown";

  // Doc setup
  const doc = new jsPDF({ orientation: "portrait", unit: "pt", format: "letter" });
  const pageWidth = doc.internal.pageSize.getWidth();
  const pageHeight = doc.internal.pageSize.getHeight();
  const margin = 40;
  let y = 40;

  // Header
  doc.setFont("helvetica", "bold");
  doc.setFontSize(18);
  doc.setTextColor(30, 41, 59);
  doc.text("ARC Application Record", margin, y);
  y += 18;
  doc.setFont("helvetica", "normal");
  doc.setFontSize(9);
  doc.setTextColor(100, 116, 139);
  doc.text(`Generated: ${format(new Date(), "MMM d, yyyy h:mm a")}`, margin, y);
  doc.text(`ID: ${application.id}`, pageWidth - margin, y, { align: "right" });
  y += 18;

  // Status banner
  const status = (application.status || "submitted").toString();
  const color =
    status === "approved" ? [34, 197, 94] :
    status === "denied" || status === "rejected" ? [239, 68, 68] :
    status === "withdrawn" ? [148, 163, 184] :
    [234, 179, 8];
  doc.setFillColor(color[0], color[1], color[2]);
  doc.roundedRect(margin, y, pageWidth - margin * 2, 22, 3, 3, "F");
  doc.setTextColor(255, 255, 255);
  doc.setFont("helvetica", "bold");
  doc.setFontSize(10);
  doc.text(`STATUS: ${status.replace(/_/g, " ").toUpperCase()}`, margin + 10, y + 15);
  y += 35;

  // Owner / address helpers
  const ownerName = application.owners
    ? `${application.owners.first_name || ""} ${application.owners.last_name || ""}`.trim()
    : "—";
  const address =
    application.units?.address ||
    application.owners?.property_address ||
    "—";
  const unitNum = application.units?.unit_number || "—";
  const submitted = application.submitted_date
    ? format(new Date(application.submitted_date), "MMM d, yyyy")
    : application.created_at
      ? format(new Date(application.created_at), "MMM d, yyyy")
      : "—";
  const reviewed = application.review_date
    ? format(new Date(application.review_date), "MMM d, yyyy")
    : "—";

  // Application details
  autoTable(doc, {
    startY: y,
    head: [["Application Details", ""]],
    body: [
      ["Title", application.title || "—"],
      ["Project Type", application.project_type || "—"],
      ["Owner", ownerName || "—"],
      ["Property Address", address],
      ["Unit #", unitNum],
      ["Association", application.associations?.name || "—"],
      ["Submitted", submitted],
      ["Reviewed", reviewed],
    ],
    theme: "grid",
    styles: { fontSize: 9, cellPadding: 6, lineColor: [226, 232, 240], lineWidth: 0.5 },
    headStyles: { fillColor: [51, 65, 85], textColor: [255, 255, 255], fontStyle: "bold" },
    columnStyles: {
      0: { fontStyle: "bold", cellWidth: 130, textColor: [71, 85, 105] },
      1: { textColor: [15, 23, 42] },
    },
    margin: { left: margin, right: margin },
  });
  y = (doc as any).lastAutoTable.finalY + 18;

  // Description
  if (application.description) {
    doc.setFont("helvetica", "bold");
    doc.setFontSize(11);
    doc.setTextColor(15, 23, 42);
    doc.text("Description of Work", margin, y);
    y += 12;
    doc.setFont("helvetica", "normal");
    doc.setFontSize(9);
    doc.setTextColor(51, 65, 85);
    const lines = doc.splitTextToSize(application.description, pageWidth - margin * 2);
    doc.text(lines, margin, y);
    y += lines.length * 11 + 12;
  }

  // Vote tally
  const tally = votes.reduce<Record<string, number>>((acc, v: any) => {
    const k = (v.vote || "").toLowerCase();
    acc[k] = (acc[k] || 0) + 1;
    return acc;
  }, {});
  const tallyText = Object.keys(tally).length
    ? Object.entries(tally).map(([k, n]) => `${k}: ${n}`).join("   •   ")
    : "No votes recorded";

  if (y > pageHeight - 150) { doc.addPage(); y = 40; }
  doc.setFont("helvetica", "bold");
  doc.setFontSize(11);
  doc.setTextColor(15, 23, 42);
  doc.text("Voting Record", margin, y);
  y += 12;
  doc.setFont("helvetica", "normal");
  doc.setFontSize(9);
  doc.setTextColor(71, 85, 105);
  doc.text(`Tally: ${tallyText}`, margin, y);
  y += 10;

  if (votes.length) {
    autoTable(doc, {
      startY: y,
      head: [["Date", "Voter", "Vote", "Recorded By"]],
      body: votes.map((v: any) => [
        format(new Date(v.created_at), "MMM d, yyyy h:mm a"),
        nameFor(v),
        (v.vote || "").toUpperCase(),
        v.recorded_by ? profilesById[v.recorded_by] || "Admin" : v.user_id ? "Self" : "—",
      ]),
      styles: { fontSize: 8.5, cellPadding: 5 },
      headStyles: { fillColor: [59, 130, 246], textColor: [255, 255, 255] },
      margin: { left: margin, right: margin },
    });
    y = (doc as any).lastAutoTable.finalY + 18;
  } else {
    y += 14;
  }

  // Comments thread
  if (y > pageHeight - 150) { doc.addPage(); y = 40; }
  doc.setFont("helvetica", "bold");
  doc.setFontSize(11);
  doc.setTextColor(15, 23, 42);
  doc.text(`Comments (${comments.length})`, margin, y);
  y += 12;

  if (comments.length === 0) {
    doc.setFont("helvetica", "italic");
    doc.setFontSize(9);
    doc.setTextColor(148, 163, 184);
    doc.text("No comments recorded.", margin, y);
    y += 14;
  } else {
    doc.setFont("helvetica", "normal");
    doc.setFontSize(9);
    for (const c of comments as any[]) {
      const author = (c.user_id && profilesById[c.user_id]) || "User";
      const when = format(new Date(c.created_at), "MMM d, yyyy h:mm a");
      const headLine = `${author} — ${when}`;
      const bodyLines = doc.splitTextToSize(c.comment || "", pageWidth - margin * 2);
      const blockHeight = 12 + bodyLines.length * 11 + 8;
      if (y + blockHeight > pageHeight - 40) { doc.addPage(); y = 40; }
      doc.setTextColor(71, 85, 105);
      doc.setFont("helvetica", "bold");
      doc.text(headLine, margin, y);
      y += 12;
      doc.setFont("helvetica", "normal");
      doc.setTextColor(15, 23, 42);
      doc.text(bodyLines, margin, y);
      y += bodyLines.length * 11 + 8;
    }
  }

  // Decision notes
  if (application.decision_notes) {
    if (y > pageHeight - 100) { doc.addPage(); y = 40; }
    doc.setFont("helvetica", "bold");
    doc.setFontSize(11);
    doc.setTextColor(15, 23, 42);
    doc.text("Decision Notes", margin, y);
    y += 12;
    doc.setFont("helvetica", "normal");
    doc.setFontSize(9);
    doc.setTextColor(51, 65, 85);
    const lines = doc.splitTextToSize(application.decision_notes, pageWidth - margin * 2);
    doc.text(lines, margin, y);
    y += lines.length * 11 + 12;
  }

  // Attachments
  if (files.length) {
    if (y > pageHeight - 100) { doc.addPage(); y = 40; }
    doc.setFont("helvetica", "bold");
    doc.setFontSize(11);
    doc.setTextColor(15, 23, 42);
    doc.text(`Attachments (${files.length})`, margin, y);
    y += 6;
    autoTable(doc, {
      startY: y + 6,
      head: [["File", "Uploaded"]],
      body: files.map((f: any) => [
        f.file_name || "—",
        f.created_at ? format(new Date(f.created_at), "MMM d, yyyy") : "—",
      ]),
      styles: { fontSize: 8.5, cellPadding: 5 },
      headStyles: { fillColor: [100, 116, 139], textColor: [255, 255, 255] },
      margin: { left: margin, right: margin },
    });
  }

  // Footer
  const pageCount = (doc as any).internal.getNumberOfPages();
  for (let i = 1; i <= pageCount; i++) {
    doc.setPage(i);
    doc.setFontSize(8);
    doc.setTextColor(148, 163, 184);
    doc.text(`Page ${i} of ${pageCount}`, pageWidth / 2, pageHeight - 20, { align: "center" });
  }

  const slug = (application.title || "ARC")
    .replace(/[^a-z0-9]/gi, "_")
    .substring(0, 30);
  doc.save(`ARC_Record_${slug}_${format(new Date(), "yyyy-MM-dd")}.pdf`);
}
