import { useState, useEffect, useMemo, memo, useCallback } from "react";
import { FileText, Plus, Trash2, Download, Bold, Italic, Save, FolderOpen, FolderDown, IndentIncrease, IndentDecrease, AlignLeft, AlignCenter, AlignRight } from "lucide-react";
import ReactQuill from "react-quill-new";
import "react-quill-new/dist/quill.snow.css";
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 { Separator } from "@/components/ui/separator";
import { Textarea } from "@/components/ui/textarea";
import { Badge } from "@/components/ui/badge";
import { supabase } from "@/integrations/supabase/client";
import { useToast } from "@/hooks/use-toast";
import { useSavedFormTemplates } from "@/hooks/useSavedFormTemplates";
import LoadTemplateDialog from "@/components/LoadTemplateDialog";
import { DndContext, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors } from "@dnd-kit/core";
import { arrayMove, SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
import SortableFormBlock from "./SortableFormBlock";
import jsPDF from "jspdf";
import { format } from "date-fns";
import { Checkbox } from "@/components/ui/checkbox";
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 DEFAULT_BLOCKS = [
  { id: "1", type: "numbered", content: "Call to Order & Establishment of Quorum", indent: 0, isBold: true },
  { id: "2", type: "text", content: "", indent: 1, isBold: false },
  { id: "3", type: "numbered", content: "Proof of Notice", indent: 0, isBold: true },
  { id: "4", type: "text", content: "", indent: 1, isBold: false },
  { id: "5", type: "numbered", content: "Reading/Waiver of Previous Minutes", indent: 0, isBold: true },
  { id: "6", type: "text", content: "", indent: 1, isBold: false },
  { id: "7", type: "numbered", content: "Officers' and Management Reports", indent: 0, isBold: true },
  { id: "8", type: "text", content: "", indent: 1, isBold: false },
  { id: "9", type: "numbered", content: "Financial Report", indent: 0, isBold: true },
  { id: "10", type: "text", content: "", indent: 1, isBold: false },
  { id: "11", type: "numbered", content: "ARC Report", indent: 0, isBold: true },
  { id: "12", type: "text", content: "", indent: 1, isBold: false },
  { id: "13", type: "numbered", content: "Old Business", indent: 0, isBold: true },
  { id: "14", type: "text", content: "", indent: 1, isBold: false },
  { id: "15", type: "numbered", content: "New Business", indent: 0, isBold: true },
  { id: "16", type: "text", content: "", indent: 1, isBold: false },
  { id: "17", type: "numbered", content: "Owner Forum", indent: 0, isBold: true },
  { id: "18", type: "text", content: "", indent: 1, isBold: false },
  { id: "19", type: "numbered", content: "Adjournment", indent: 0, isBold: true },
  { id: "20", type: "motion", content: "Motion to adjourn at __:__ PM.", indent: 1, isBold: false },
];

import gavelIconSrc from "@/assets/icons8-gavel-20.png";

async function fetchLogoDataUrl(url) {
  if (!url) return null;
  try {
    // Try fetching with no-cors fallback via an Image element to bypass CORS issues
    return new Promise((resolve) => {
      const img = new Image();
      img.crossOrigin = "anonymous";
      img.onload = () => {
        try {
          const canvas = document.createElement("canvas");
          canvas.width = img.naturalWidth;
          canvas.height = img.naturalHeight;
          const ctx = canvas.getContext("2d");
          ctx.drawImage(img, 0, 0);
          resolve(canvas.toDataURL("image/png"));
        } catch {
          resolve(null);
        }
      };
      img.onerror = () => resolve(null);
      img.src = url;
    });
  } catch {
    return null;
  }
}

const TYPE_COLORS = { numbered: "default", text: "secondary", motion: "outline", spacer: "secondary", line: "secondary" };
const MINUTES_QUILL_MODULES = { toolbar: [["bold", "italic"]] };
const QUILL_FORMATS = ["bold", "italic"];

// Strip HTML for static preview rendering when block is not focused
function stripHtmlPreserveBreaks(html) {
  if (!html) return "";
  // Convert closing block tags + <br> to newlines, then strip remaining tags
  return html
    .replace(/<\s*br\s*\/?>/gi, "\n")
    .replace(/<\/(p|div|li|h[1-6])>/gi, "\n")
    .replace(/<[^>]+>/g, "")
    .replace(/&nbsp;/g, " ")
    .replace(/&amp;/g, "&")
    .replace(/&lt;/g, "<")
    .replace(/&gt;/g, ">")
    .replace(/\n{3,}/g, "\n\n")
    .trim();
}

const MinutesBlockRow = memo(function MinutesBlockRow({
  block,
  isFocused,
  onFocus,
  onBlur,
  onUpdate,
  onRemove,
}) {
  const handleContentChange = useCallback((val) => onUpdate(block.id, "content", val), [block.id, onUpdate]);
  const handleNumberChange = useCallback((e) => onUpdate(block.id, "customNumber", e.target.value), [block.id, onUpdate]);
  const handleOutdent = useCallback(
    () => onUpdate(block.id, "indent", Math.max(0, (block.indent || 0) - 1)),
    [block.id, block.indent, onUpdate]
  );
  const handleIndent = useCallback(
    () => onUpdate(block.id, "indent", Math.min(4, (block.indent || 0) + 1)),
    [block.id, block.indent, onUpdate]
  );
  const handleAlign = useCallback(() => {
    const aligns = ["left", "center", "right"];
    const cur = aligns.indexOf(block.align || "left");
    onUpdate(block.id, "align", aligns[(cur + 1) % 3]);
  }, [block.id, block.align, onUpdate]);
  const handleRemove = useCallback(() => onRemove(block.id), [block.id, onRemove]);
  const handleFocus = useCallback(() => onFocus(block.id), [block.id, onFocus]);

  const isStructural = block.type === "spacer" || block.type === "line";
  const previewText = !isFocused && !isStructural ? stripHtmlPreserveBreaks(block.content) : "";

  return (
    <div className="flex items-start gap-1.5 flex-1" style={{ paddingLeft: `${block.indent * 24}px` }}>
      <Badge
        variant={TYPE_COLORS[block.type] || "secondary"}
        className={`text-[10px] mt-1.5 shrink-0 w-16 justify-center ${block.type === "motion" ? "bg-primary/10 text-primary border-primary/30" : ""}`}
      >
        {block.type}
      </Badge>
      {block.type === "numbered" && (
        <Input
          value={block.customNumber ?? ""}
          onChange={handleNumberChange}
          placeholder="#"
          className="w-10 h-9 text-xs text-center p-0 shrink-0"
          title="Custom number (leave blank for auto)"
        />
      )}
      {isStructural ? (
        <div className="text-xs text-muted-foreground italic flex-1 py-2">
          {block.type === "spacer" ? "— Spacer —" : "— Horizontal Line —"}
        </div>
      ) : isFocused ? (
        <div className={`flex-1 minutes-quill-block ${block.type === "motion" ? "motion-block" : ""}`}>
          <ReactQuill
            theme="snow"
            value={block.content}
            onChange={handleContentChange}
            onBlur={onBlur}
            modules={MINUTES_QUILL_MODULES}
            formats={QUILL_FORMATS}
            className="text-sm"
          />
        </div>
      ) : (
        <button
          type="button"
          onClick={handleFocus}
          className={`flex-1 text-left text-sm py-2 px-3 rounded border border-transparent hover:border-border hover:bg-muted/40 transition-colors min-h-[36px] whitespace-pre-wrap ${
            block.type === "motion" ? "italic" : ""
          } ${!previewText ? "text-muted-foreground/60" : ""}`}
        >
          {previewText || "Click to edit…"}
        </button>
      )}
      <button onClick={handleOutdent} className="p-1 mt-1.5 text-muted-foreground hover:text-foreground opacity-0 group-hover:opacity-100" title="Outdent">
        <IndentDecrease className="h-3.5 w-3.5" />
      </button>
      <button onClick={handleIndent} className="p-1 mt-1.5 text-muted-foreground hover:text-foreground opacity-0 group-hover:opacity-100" title="Indent">
        <IndentIncrease className="h-3.5 w-3.5" />
      </button>
      <button
        onClick={handleAlign}
        className={`p-1 mt-1.5 rounded ${block.align && block.align !== "left" ? "text-primary" : "text-muted-foreground"} hover:text-foreground opacity-0 group-hover:opacity-100`}
        title={`Align: ${block.align || "left"}`}
      >
        {block.align === "center" ? <AlignCenter className="h-3.5 w-3.5" /> : block.align === "right" ? <AlignRight className="h-3.5 w-3.5" /> : <AlignLeft className="h-3.5 w-3.5" />}
      </button>
      <button onClick={handleRemove} className="p-1 mt-1.5 text-destructive/70 hover:text-destructive opacity-0 group-hover:opacity-100">
        <Trash2 className="h-3.5 w-3.5" />
      </button>
    </div>
  );
});

export default function MeetingMinutesForm() {
  const { toast } = useToast();
  const [associations, setAssociations] = useState([]);
  const [selectedAssociation, setSelectedAssociation] = useState("");
  const [association, setAssociation] = useState(null);
  const [meetingDate, setMeetingDate] = useState(format(new Date(), "yyyy-MM-dd"));
  const [meetingTime, setMeetingTime] = useState("7:00 PM");
  const [meetingLocation, setMeetingLocation] = useState("");
  const [meetingType, setMeetingType] = useState("Board of Directors");
  const [font, setFont] = useState("Helvetica");
  const [fontSize, setFontSize] = useState(10);
  const [closingNotes, setClosingNotes] = useState("");
  const [blocks, setBlocks] = useState(DEFAULT_BLOCKS);
  const [attendees, setAttendees] = useState("");
  const [absent, setAbsent] = useState("");
  const [managementRep, setManagementRep] = useState("Avria Community Management, represented by Tom Barnhart");
  const [embedValidation, setEmbedValidation] = useState(false);
  const [showSaveDocsDialog, setShowSaveDocsDialog] = useState(false);

  const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 5 } }), useSensor(KeyboardSensor));
  const handleDragEnd = (event) => {
    const { active, over } = event;
    if (active.id !== over?.id) {
      setBlocks((prev) => {
        const oldIndex = prev.findIndex((b) => b.id === active.id);
        const newIndex = prev.findIndex((b) => b.id === over.id);
        return arrayMove(prev, oldIndex, newIndex);
      });
    }
  };

  const templates = useSavedFormTemplates("minutes");

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

  useEffect(() => {
    if (!selectedAssociation) { setAssociation(null); return; }
    supabase.from("associations").select("*").eq("id", selectedAssociation).single().then(({ data }) => {
      if (data) setAssociation(data);
    });
  }, [selectedAssociation]);

  const getFormData = () => ({
    selectedAssociation, meetingDate, meetingTime, meetingLocation, meetingType, font, fontSize, closingNotes, blocks,
    attendees, absent, managementRep,
  });

  const applyFormData = (data) => {
    if (data.selectedAssociation) setSelectedAssociation(data.selectedAssociation);
    if (data.meetingDate) setMeetingDate(data.meetingDate);
    if (data.meetingTime) setMeetingTime(data.meetingTime);
    if (data.meetingLocation !== undefined) setMeetingLocation(data.meetingLocation);
    if (data.meetingType) setMeetingType(data.meetingType);
    if (data.font) setFont(data.font);
    if (data.fontSize) setFontSize(data.fontSize);
    if (data.closingNotes !== undefined) setClosingNotes(data.closingNotes);
    if (data.blocks) setBlocks(data.blocks);
    if (data.attendees !== undefined) setAttendees(data.attendees);
    if (data.absent !== undefined) setAbsent(data.absent);
    if (data.managementRep !== undefined) setManagementRep(data.managementRep);
  };

  const handleSave = async () => {
    const name = `${meetingType} Minutes - ${meetingDate}`;
    await templates.saveTemplate(name, getFormData(), selectedAssociation || null);
  };

  const handleLoad = async (templateId) => {
    const result = await templates.loadTemplate(templateId);
    if (result?.form_data) applyFormData(result.form_data);
  };

  const handleNew = () => {
    templates.newTemplate();
    setSelectedAssociation("");
    setMeetingDate(format(new Date(), "yyyy-MM-dd"));
    setMeetingTime("7:00 PM");
    setMeetingLocation("");
    setMeetingType("Board of Directors");
    setClosingNotes("");
    setBlocks(DEFAULT_BLOCKS);
    setAttendees("");
    setAbsent("");
    setManagementRep("Avria Community Management, represented by Tom Barnhart");
  };

  const [focusedBlockId, setFocusedBlockId] = useState(null);

  const addBlock = useCallback((type = "text") => {
    const newId = Date.now().toString();
    setBlocks((prev) => [...prev, { id: newId, type, content: "", indent: 0, isBold: false }]);
    setFocusedBlockId(newId);
  }, []);
  const updateBlock = useCallback((id, field, value) => {
    setBlocks((prev) => prev.map((b) => (b.id === id ? { ...b, [field]: value } : b)));
  }, []);
  const removeBlock = useCallback((id) => {
    setBlocks((prev) => prev.filter((b) => b.id !== id));
    setFocusedBlockId((cur) => (cur === id ? null : cur));
  }, []);
  const handleBlockBlur = useCallback(() => setFocusedBlockId(null), []);

  const buildPdf = async () => {
    const doc = new jsPDF({ unit: "pt", format: "letter" });
    doc.setCharSpace(0);
    const margin = 60;
    const pageW = doc.internal.pageSize.getWidth();
    const pageH = doc.internal.pageSize.getHeight();
    const contentW = pageW - margin * 2;
    const fontName = font.toLowerCase() === "times" ? "times" : font.toLowerCase() === "courier" ? "courier" : "helvetica";
    let y = 50;

    // --- Logo ---
    const logoUrl = association?.logo_url;
    if (logoUrl) {
      const logoData = await fetchLogoDataUrl(logoUrl);
      if (logoData) {
        try {
          const logoW = 125;
          // Wait for image to load to get natural dimensions
          const logoH = await new Promise((resolve) => {
            const tmpImg = new Image();
            tmpImg.onload = () => {
              const ratio = tmpImg.naturalHeight / tmpImg.naturalWidth;
              resolve(logoW * (ratio || 0.4));
            };
            tmpImg.onerror = () => resolve(logoW * 0.4);
            tmpImg.src = logoData;
          });
          doc.addImage(logoData, "PNG", (pageW - logoW) / 2, y, logoW, logoH);
          y += logoH + 14;
        } catch { /* skip logo on error */ }
      }
    }

    // --- MEETING MINUTES ---
    doc.setFontSize(16);
    doc.setFont(fontName, "bold");
    doc.setTextColor(0, 0, 0);
    doc.text("MEETING MINUTES", pageW / 2, y, { align: "center" });
    y += 22;

    // --- Association Name ---
    doc.setFontSize(12);
    doc.setFont(fontName, "bold");
    const assocName = (association?.name || "").toUpperCase();
    if (assocName) {
      doc.text(assocName, pageW / 2, y, { align: "center" });
      y += 18;
    }

    // --- Meeting Type (e.g. BOARD OF DIRECTORS) ---
    doc.setFontSize(11);
    doc.setFont(fontName, "bold");
    doc.text(meetingType.toUpperCase(), pageW / 2, y, { align: "center" });
    y += 28;

    // --- Metadata fields ---
    const labelX = margin;
    const valueX = margin + 90;
    doc.setFontSize(fontSize);

    const metaFields = [
      { label: "Date:", value: meetingDate ? format(new Date(meetingDate + "T12:00:00"), "MMMM d, yyyy") : "" },
      { label: "Time:", value: meetingTime },
      { label: "Location:", value: meetingLocation },
    ];

    metaFields.forEach(({ label, value }) => {
      if (!value) return;
      doc.setFont(fontName, "bold");
      doc.text(label, labelX, y);
      doc.setFont(fontName, "normal");
      doc.text(value, valueX, y);
      y += 16;
    });

    // Attendees
    if (attendees) {
      doc.setFont(fontName, "bold");
      doc.text("Attendees:", labelX, y);
      doc.setFont(fontName, "normal");
      const attendeeLines = doc.splitTextToSize(attendees, contentW - 90);
      doc.text(attendeeLines, valueX, y);
      y += attendeeLines.length * 14 + 2;
    } else {
      doc.setFont(fontName, "bold");
      doc.text("Attendees:", labelX, y);
      y += 16;
    }

    // Absent
    doc.setFont(fontName, "bold");
    doc.text("Absent:", labelX, y);
    if (absent) {
      doc.setFont(fontName, "normal");
      doc.text(absent, valueX, y);
    }
    y += 16;

    // Management
    doc.setFont(fontName, "bold");
    doc.text("Management:", labelX, y);
    if (managementRep) {
      doc.setFont(fontName, "normal");
      const mgmtLines = doc.splitTextToSize(managementRep, contentW - 90);
      doc.text(mgmtLines, valueX, y);
      y += mgmtLines.length * 14 + 2;
    } else {
      y += 16;
    }

    y += 10;

    // --- Horizontal divider ---
    doc.setDrawColor(180, 180, 180);
    doc.setLineWidth(0.5);
    doc.line(margin, y, pageW - margin, y);
    y += 25;

    // --- Helper: parse HTML content into styled segments ---
    const stripHtml = (html) => {
      if (!html) return "";
      return html.replace(/<[^>]*>/g, "").replace(/&nbsp;/g, " ").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'").trim();
    };

    const parseHtmlSegments = (html) => {
      if (!html) return [];
      // Replace <br> and </p><p> with newlines
      let text = html.replace(/<br\s*\/?>/gi, "\n").replace(/<\/p>\s*<p[^>]*>/gi, "\n");
      const segments = [];
      // Simple regex parser for <strong>, <em>, <b>, <i> tags
      const tagRegex = /(<\/?(?:strong|em|b|i)>)/gi;
      const parts = text.split(tagRegex);
      let bold = false, italic = false;
      parts.forEach((part) => {
        const lower = part.toLowerCase();
        if (lower === "<strong>" || lower === "<b>") { bold = true; return; }
        if (lower === "</strong>" || lower === "</b>") { bold = false; return; }
        if (lower === "<em>" || lower === "<i>") { italic = true; return; }
        if (lower === "</em>" || lower === "</i>") { italic = false; return; }
        // Strip any remaining tags
        const cleaned = part.replace(/<[^>]*>/g, "").replace(/&nbsp;/g, " ").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'");
        if (cleaned) {
          segments.push({ text: cleaned, bold, italic });
        }
      });
      return segments;
    };

    const getSegmentFontStyle = (seg) => {
      if (seg.bold && seg.italic) return "bolditalic";
      if (seg.bold) return "bold";
      if (seg.italic) return "italic";
      return "normal";
    };

    // Render rich text segments on a single logical line, handling wrapping
    const renderRichLine = (segments, startX, maxW, lineHeight = 14) => {
      if (!segments.length) return;
      // Flatten segments into one plain string to compute word-wrap lines
      const plainText = segments.map(s => s.text).join("");
      // For simple cases (short text), render inline segments directly
      // For wrapping, we need to break by words and track which segment each word belongs to

      // Build word list with formatting
      const words = [];
      segments.forEach((seg) => {
        const segWords = seg.text.split(/(\s+)/);
        segWords.forEach((w) => {
          if (w) words.push({ text: w, bold: seg.bold, italic: seg.italic });
        });
      });

      let currentX = startX;
      let lineStarted = false;

      words.forEach((word) => {
        if (word.text === "\n" || word.text.includes("\n")) {
          y += lineHeight;
          checkPageBreak(lineHeight);
          currentX = startX;
          lineStarted = false;
          return;
        }
        doc.setFont(fontName, getSegmentFontStyle(word));
        const wordW = doc.getTextWidth(word.text);
        
        // Check if word would overflow (skip check for whitespace-only)
        if (lineStarted && word.text.trim() && currentX + wordW > startX + maxW) {
          y += lineHeight;
          checkPageBreak(lineHeight);
          currentX = startX;
          lineStarted = false;
          // Skip leading whitespace on new line
          if (!word.text.trim()) return;
        }

        doc.text(word.text, currentX, y);
        currentX += wordW;
        if (word.text.trim()) lineStarted = true;
      });
      y += lineHeight;
    };

    // --- Blocks ---
    let counter = 0;
    const bodyIndent = 30;
    const subCounters = {};

    const checkPageBreak = (needed = 30) => {
      if (y + needed > pageH - 60) {
        doc.addPage();
        y = 50;
      }
    };

    const getFontStyle = (block) => {
      if (block.isBold && block.isItalic) return "bolditalic";
      if (block.isBold) return "bold";
      if (block.isItalic) return "italic";
      return "normal";
    };

    const getSubLabel = (level, count) => {
      if (level === 1) return String.fromCharCode(96 + Math.min(count, 26)) + ".";
      if (level === 2) {
        const romans = ["i","ii","iii","iv","v","vi","vii","viii","ix","x"];
        return (romans[count - 1] || count) + ".";
      }
      if (level === 3) return String.fromCharCode(64 + Math.min(count, 26)) + ".";
      return count + ".";
    };

    // Helper to get content - supports both HTML (new) and plain text (legacy)
    const getBlockContent = (block) => {
      const content = block.content || "";
      // Check if content contains HTML tags
      if (/<[^>]+>/.test(content)) return content;
      return content;
    };

    const isHtml = (text) => /<[^>]+>/.test(text);

    blocks.forEach((block) => {
      checkPageBreak();
      const indent = block.indent * 24;
      const content = getBlockContent(block);

      if (block.type === "motion") {
        const cellX = margin + indent + bodyIndent;
        const cellW = contentW - indent - bodyIndent;
        const cellPadding = 10;
        const textW = cellW - cellPadding * 2 - 14;
        const plainContent = isHtml(content) ? stripHtml(content) : content;
        doc.setFont(fontName, "bolditalic");
        doc.setFontSize(fontSize);
        const lines = doc.splitTextToSize(plainContent, textW);
        const textH = lines.length * 14;
        const cellH = textH + cellPadding * 2;
        checkPageBreak(cellH + 4);
        doc.setDrawColor(100, 100, 100);
        doc.setLineWidth(1.2);
        doc.rect(cellX, y, cellW, cellH);
        doc.setLineWidth(0.4);
        doc.rect(cellX + 2, y + 2, cellW - 4, cellH - 4);
        try {
          doc.addImage(gavelIconSrc, "PNG", cellX + cellPadding, y + cellPadding + 1, 10, 10);
        } catch { /* skip icon on error */ }
        doc.setFont(fontName, "bolditalic");
        doc.setFontSize(fontSize);
        let textY = y + cellPadding + 10;
        lines.forEach((line) => {
          doc.text(line, cellX + cellPadding + 14, textY);
          textY += 14;
        });
        y += cellH + 6;
        doc.setFont(fontName, "normal");
      } else if (block.type === "numbered" && block.indent === 0) {
        counter++;
        for (const key in subCounters) delete subCounters[key];
        const displayNum = block.customNumber ? block.customNumber : `${counter}`;
        y += 6;
        checkPageBreak(20);
        doc.setFontSize(fontSize);
        // Render number label
        doc.setFont(fontName, "bold");
        doc.text(`${displayNum}.`, margin, y);
        // Render content with wrapping and inline formatting
        const textX = margin + 20;
        const maxW = contentW - 20;
        if (isHtml(content)) {
          const segments = parseHtmlSegments(content);
          // Apply block-level bold/italic as base
          const baseSegments = segments.map(s => ({
            ...s,
            bold: s.bold || block.isBold,
            italic: s.italic || block.isItalic,
          }));
          renderRichLine(baseSegments, textX, maxW);
        } else {
          doc.setFont(fontName, getFontStyle(block));
          const lines = doc.splitTextToSize(content, maxW);
          lines.forEach((line, li) => {
            if (li > 0) checkPageBreak(14);
            doc.text(line, textX, y);
            if (li < lines.length - 1) y += 14;
          });
          y += 14;
        }
        doc.setFont(fontName, "normal");
        y += 4;
      } else if (block.type === "numbered" && block.indent > 0) {
        const level = block.indent;
        subCounters[level] = (subCounters[level] || 0) + 1;
        for (let l = level + 1; l <= 5; l++) subCounters[l] = 0;
        const label = block.customNumber ? block.customNumber : getSubLabel(level, subCounters[level]);
        y += 4;
        checkPageBreak(18);
        doc.setFontSize(fontSize);
        doc.setFont(fontName, getFontStyle(block));
        const labelX = margin + indent;
        doc.text(label, labelX, y);
        // Render content with wrapping
        const textX = labelX + 20;
        const maxW = contentW - indent - 20;
        if (isHtml(content)) {
          const segments = parseHtmlSegments(content);
          const baseSegments = segments.map(s => ({
            ...s,
            bold: s.bold || block.isBold,
            italic: s.italic || block.isItalic,
          }));
          renderRichLine(baseSegments, textX, maxW);
        } else {
          const lines = doc.splitTextToSize(content, maxW);
          lines.forEach((line, li) => {
            if (li > 0) checkPageBreak(14);
            doc.text(line, textX, y);
            if (li < lines.length - 1) y += 14;
          });
          y += 14;
        }
        doc.setFont(fontName, "normal");
        y += 2;
      } else if (block.type === "line") {
        doc.setDrawColor(200, 200, 200);
        doc.line(margin, y, pageW - margin, y);
        y += 10;
      } else if (block.type === "spacer") {
        y += 14;
      } else {
        if (content) {
          doc.setFontSize(fontSize);
          const blockAlign = block.align || "left";
          const textX = blockAlign === "center" ? pageW / 2 : blockAlign === "right" ? pageW - margin : margin + indent + bodyIndent;
          const maxW = blockAlign === "left" ? contentW - indent - bodyIndent : contentW;
          if (isHtml(content) && blockAlign === "left") {
            const segments = parseHtmlSegments(content);
            const baseSegments = segments.map(s => ({
              ...s,
              bold: s.bold || block.isBold,
              italic: s.italic || block.isItalic,
            }));
            renderRichLine(baseSegments, textX, maxW);
          } else {
            const plainContent = isHtml(content) ? stripHtml(content) : content;
            doc.setFont(fontName, getFontStyle(block));
            const lines = doc.splitTextToSize(plainContent, maxW);
            lines.forEach((line) => {
              checkPageBreak(14);
              doc.text(line, textX, y, { align: blockAlign });
              y += 14;
            });
          }
          doc.setFont(fontName, "normal");
        }
      }
      // Add line break between entries
      if (block.type !== "spacer" && block.type !== "line") {
        y += 8;
      }
    });

    // --- Closing notes ---
    if (closingNotes) {
      y += 15;
      doc.setFont(fontName, "normal");
      doc.setFontSize(fontSize);
      const lines = doc.splitTextToSize(closingNotes, contentW);
      lines.forEach((line) => {
        checkPageBreak(14);
        doc.text(line, margin, y);
        y += 14;
      });
    }

    // --- Footer on every page ---
    const totalPages = doc.internal.getNumberOfPages();
    for (let i = 1; i <= totalPages; i++) {
      doc.setPage(i);
      doc.setFontSize(8);
      doc.setTextColor(150, 150, 150);
      doc.text(`Page ${i} of ${totalPages}`, pageW - margin, pageH - 30, { align: "right" });
      doc.setTextColor(0, 0, 0);
    }

    let validationProof = null;
    if (embedValidation) {
      try {
        const docDate = meetingDate ? format(new Date(`${meetingDate}T12:00:00`), "MMMM d, yyyy") : "";
        validationProof = await embedValidationProof(doc, {
          documentTitle: `${meetingType} Meeting Minutes${association ? ` – ${association.name}` : ""}`,
          documentType: "Meeting Minutes",
          documentDate: docDate,
          associationId: selectedAssociation || undefined,
        });
      } catch (err) {
        console.error("Failed to embed validation proof:", err);
      }
    }

    return { doc, validationProof };
  };

  const exportPDF = async () => {
    const { doc, validationProof } = await buildPdf();
    const pdfFileName = `Minutes_${format(new Date(meetingDate + "T12:00:00"), "yyyy-MM-dd")}.pdf`;

    let validatedPdfStored = false;
    if (validationProof) {
      try {
        const url = await storeValidatedPdf(doc, validationProof.id, pdfFileName);
        if (url) validatedPdfStored = true;
      } catch (err) {
        console.error("Failed to store validated PDF:", err);
      }
    }

    doc.save(pdfFileName);

    if (validatedPdfStored) {
      sonnerToast.success("Minutes PDF exported", { description: "Validation certificate embedded and saved." });
    } else if (embedValidation) {
      sonnerToast.warning("Minutes PDF exported, but validation storage failed");
    } else {
      sonnerToast.success("Minutes PDF exported");
    }
  };

  const handleSaveToDocuments = async (metadata) => {
    const { doc, validationProof } = await buildPdf();
    const blob = doc.output("blob");
    const pdfFileName = `Minutes_${format(new Date(meetingDate + "T12:00:00"), "yyyy-MM-dd")}.pdf`;

    const { data: userData } = await supabase.auth.getUser();
    if (!userData?.user) throw new Error("Not authenticated");

    if (validationProof) {
      try {
        await storeValidatedPdf(doc, validationProof.id, pdfFileName);
      } catch (err) {
        console.error("Failed to store validated PDF:", err);
      }
    }

    // Display name kept human-readable; storage key is randomized.
    const displayFileName = `${metadata.name.replace(/[^a-zA-Z0-9._ -]+/g, "_").trim()}.pdf`;
    const filePath = buildSecureStorageKey("doc.pdf", userData.user.id);

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

    const { data: { publicUrl } } = supabase.storage.from("files").getPublicUrl(filePath);

    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.user.id,
    });
    if (docError) throw docError;

    sonnerToast.success("Minutes saved to Documents", {
      description: validationProof ? "Validation certificate embedded." : undefined,
    });
    return { blob };
  };

  return (
    <div className="flex flex-col gap-4 p-6 h-full min-h-0 overflow-auto">
      {/* Top Bar: Title + Actions */}
      <div className="flex items-center gap-3">
        <div className="h-9 w-9 rounded-lg bg-primary/10 flex items-center justify-center">
          <FileText className="h-4 w-4 text-primary" />
        </div>
        <div>
          <h2 className="text-base font-semibold text-foreground">Minutes Editor</h2>
          <p className="text-xs text-muted-foreground">
            {templates.currentTemplateId ? `Editing: ${templates.currentTemplateName}` : "New Draft"}
          </p>
        </div>
        <div className="ml-auto flex gap-1.5">
          <Button variant="outline" size="sm" className="gap-1 text-xs h-8" onClick={handleNew}><Plus className="h-3 w-3" /> New</Button>
          <LoadTemplateDialog
            templates={templates.savedTemplates}
            onLoad={handleLoad}
            onDelete={templates.deleteTemplate}
          />
          <Button variant="outline" size="sm" className="gap-1 text-xs h-8" onClick={handleSave}><Save className="h-3 w-3" /> Save</Button>
          <Button variant="outline" size="sm" className="gap-1.5 text-xs h-8" onClick={() => setShowSaveDocsDialog(true)}>
            <FolderDown className="h-3.5 w-3.5" /> Save to Docs
          </Button>
          <Button size="sm" className="gap-1.5 text-xs h-8" onClick={exportPDF}>
            <Download className="h-3.5 w-3.5" /> Export PDF
          </Button>
        </div>
      </div>

      {/* Meeting Details + Attendance Row */}
      <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
        <Card>
          <CardHeader className="pb-2">
            <CardTitle className="text-sm flex items-center gap-2">📅 Meeting Details</CardTitle>
          </CardHeader>
          <CardContent className="space-y-3">
            <div className="grid grid-cols-3 gap-3">
              <div className="space-y-1">
                <Label className="text-xs">Association</Label>
                <Select value={selectedAssociation} onValueChange={setSelectedAssociation}>
                  <SelectTrigger className="text-xs h-8"><SelectValue placeholder="Select Association" /></SelectTrigger>
                  <SelectContent>
                    {associations.map((a) => <SelectItem key={a.id} value={a.id}>{a.name}</SelectItem>)}
                  </SelectContent>
                </Select>
              </div>
              <div className="space-y-1">
                <Label className="text-xs">Meeting Type</Label>
                <Input value={meetingType} onChange={(e) => setMeetingType(e.target.value)} className="h-8 text-xs" />
              </div>
              <div className="space-y-1">
                <Label className="text-xs">Location</Label>
                <Input value={meetingLocation} onChange={(e) => setMeetingLocation(e.target.value)} className="h-8 text-xs" />
              </div>
            </div>
            <div className="grid grid-cols-4 gap-3">
              <div className="space-y-1">
                <Label className="text-xs">Date</Label>
                <Input type="date" value={meetingDate} onChange={(e) => setMeetingDate(e.target.value)} className="h-8 text-xs" />
              </div>
              <div className="space-y-1">
                <Label className="text-xs">Time</Label>
                <Input value={meetingTime} onChange={(e) => setMeetingTime(e.target.value)} className="h-8 text-xs" />
              </div>
              <div className="space-y-1">
                <Label className="text-xs">Font</Label>
                <Select value={font} onValueChange={setFont}>
                  <SelectTrigger className="h-8 text-xs"><SelectValue /></SelectTrigger>
                  <SelectContent>
                    <SelectItem value="Helvetica">Helvetica</SelectItem>
                    <SelectItem value="Times">Times</SelectItem>
                    <SelectItem value="Courier">Courier</SelectItem>
                  </SelectContent>
                </Select>
              </div>
              <div className="space-y-1">
                <Label className="text-xs">Size (pt)</Label>
                <Input type="number" value={fontSize} onChange={(e) => setFontSize(Number(e.target.value))} className="h-8 text-xs" />
              </div>
            </div>
            <div className="flex items-center gap-2 pt-1">
              <Checkbox id="embedValidationMinutes" checked={embedValidation} onCheckedChange={(checked) => setEmbedValidation(Boolean(checked))} />
              <Label htmlFor="embedValidationMinutes" className="text-xs cursor-pointer">Embed validation certificate</Label>
            </div>
          </CardContent>
        </Card>

        <Card>
          <CardHeader className="pb-2">
            <CardTitle className="text-sm flex items-center gap-2">👥 Attendance</CardTitle>
          </CardHeader>
          <CardContent className="space-y-3">
            <div className="space-y-1">
              <Label className="text-xs">Attendees</Label>
              <Textarea
                value={attendees}
                onChange={(e) => setAttendees(e.target.value)}
                placeholder="Names of attendees..."
                rows={2}
                className="text-xs"
              />
            </div>
            <div className="space-y-1">
              <Label className="text-xs">Absent</Label>
              <Input value={absent} onChange={(e) => setAbsent(e.target.value)} className="h-8 text-xs" placeholder="Names of absent members" />
            </div>
            <div className="space-y-1">
              <Label className="text-xs">Management Representative</Label>
              <Input value={managementRep} onChange={(e) => setManagementRep(e.target.value)} className="h-8 text-xs" />
            </div>
          </CardContent>
        </Card>
      </div>

      <Separator />

      {/* Minutes Content */}
      <div className="flex-1 flex flex-col min-h-0">
        <div className="flex items-center justify-between mb-3">
          <h3 className="text-sm font-semibold flex items-center gap-2">≡ Minutes Content</h3>
          <div className="flex gap-1.5">
            <Button variant="outline" size="sm" className="gap-1 text-xs h-8" onClick={() => addBlock("spacer")}>↕ Spacer</Button>
            <Button variant="outline" size="sm" className="gap-1 text-xs h-8" onClick={() => addBlock("line")}>— Line</Button>
            <Button variant="outline" size="sm" className="gap-1 text-xs h-8" onClick={() => addBlock("motion")}>🏷 Motion</Button>
            <Button variant="outline" size="sm" className="gap-1 text-xs h-8" onClick={() => addBlock("text")}>≡ Text</Button>
            <Button size="sm" className="gap-1 text-xs h-8" onClick={() => addBlock("numbered")}>☰ Numbered</Button>
          </div>
        </div>

        <DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
          <SortableContext items={blocks.map((b) => b.id)} strategy={verticalListSortingStrategy}>
            <div className="flex-1 overflow-auto border rounded-lg bg-card p-4 space-y-1.5">
              {blocks.map((block) => (
                <SortableFormBlock key={block.id} id={block.id}>
                  <MinutesBlockRow
                    block={block}
                    isFocused={focusedBlockId === block.id}
                    onFocus={setFocusedBlockId}
                    onBlur={handleBlockBlur}
                    onUpdate={updateBlock}
                    onRemove={removeBlock}
                  />
                </SortableFormBlock>
              ))}
            </div>
          </SortableContext>
        </DndContext>

        {/* Closing Notes */}
        <div className="mt-4">
          <Label className="text-xs font-semibold flex items-center gap-1.5 mb-1.5">📋 Additional Notes / Closing Remarks</Label>
          <Textarea
            value={closingNotes}
            onChange={(e) => setClosingNotes(e.target.value)}
            placeholder="Enter any closing remarks, adjournment notes, or unformatted text here that will appear at the end of the PDF..."
            rows={3}
            className="text-sm"
          />
        </div>
      </div>

      <SaveToDocumentsDialog
        open={showSaveDocsDialog}
        onOpenChange={setShowSaveDocsDialog}
        onSave={handleSaveToDocuments}
        defaultName={`${meetingType} Meeting Minutes${association ? ` – ${association.name}` : ""}`}
        defaultClientId={selectedAssociation}
      />
    </div>
  );
}
