import React, { useState, useEffect, useRef } from 'react';
import { getAddressFormLines } from '@/lib/formatMailingAddress';
import { combineOwnerNames } from '@/lib/ownerAddressUtils';
import { useSearchParams } from 'react-router-dom';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button';
import { Separator } from '@/components/ui/separator';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { useToast } from '@/hooks/use-toast';
import { FileDown, Loader2, Calculator, Plus, Trash2, Settings, EyeOff, FolderDown } from 'lucide-react';
import { jsPDF } from 'jspdf';
import 'jspdf-autotable';
import { supabase } from '@/integrations/supabase/client';
import { Combobox } from '@/components/Combobox';
import { drawBlock, loadImage } from '@/lib/pdfGenerationUtils';
import { buildLedgerAccountBreakdown } from '@/lib/unitLedgerAccountBreakdown';
import { SaveToDocumentsDialog } from '@/components/SaveToDocumentsDialog';
import { buildSecureStorageKey } from '@/lib/secureStorageNaming';
import PdfStylingControls from '@/components/forms/PdfStylingControls';

const DEFAULT_NOTICE_ITEMS = [
  { description: 'Assessments', amount: '0.00' },
  { description: 'Late Fees', amount: '0.00' },
  { description: 'Interest', amount: '0.00' },
];

const TYPE_TO_LABEL = {
  assessment: 'Assessments',
  special_assessment: 'Special Assessments',
  late_fee: 'Late Fees',
  interest: 'Interest',
  admin_fee: 'Admin Fees',
  legal_fee: 'Legal Fees',
  violation: 'Violations',
  bank_fee: 'Bank Fees',
};

const cloneItems = (items) => items.map((item) => ({ ...item }));

const getDefaultNoticeItems = () => cloneItems(DEFAULT_NOTICE_ITEMS);

const isNonArchivedOwner = (owner) => owner?.status !== 'archived';

const buildNoticeItemsFromQueryParams = ({
  assessments = '0.00',
  lateFees = '0.00',
  interest = '0.00',
  adminFees = '0.00',
  legalFees = '0.00',
  violations = '0.00',
  bankFees = '0.00',
}) => {
  const items = [
    { description: 'Assessments', amount: assessments },
    { description: 'Late Fees', amount: lateFees },
    { description: 'Interest', amount: interest },
  ];

  if (parseFloat(adminFees) > 0) items.push({ description: 'Admin Fees', amount: adminFees });
  if (parseFloat(legalFees) > 0) items.push({ description: 'Legal Fees', amount: legalFees });
  if (parseFloat(violations) > 0) items.push({ description: 'Violations', amount: violations });
  if (parseFloat(bankFees) > 0) items.push({ description: 'Bank Fees', amount: bankFees });

  return items;
};

const buildNoticeItemsFromLedgerRows = (rows = []) =>
  rows
    .filter((row) => Math.max(0, Number(row.openBalance || 0)) > 0.004)
    .map((row) => ({
      description: TYPE_TO_LABEL[row.type] || row.label,
      amount: Math.max(0, Number(row.openBalance || 0)).toFixed(2),
    }));

async function buildOwnerNoticePrefill(owner, ownerPool, fallbackItems = getDefaultNoticeItems()) {
  const eligibleOwners = owner.unit_id
    ? ownerPool.filter((record) => record.unit_id === owner.unit_id && isNonArchivedOwner(record))
    : (isNonArchivedOwner(owner) ? [owner] : []);
  const coOwners = eligibleOwners.length > 0 ? eligibleOwners : [owner];

  const ownerName = combineOwnerNames(coOwners);
  const addrLines = getAddressFormLines(owner, ownerName);
  const ownerIds = coOwners.map((record) => record.id);

  let items = [];

  const { data: ledgerEntries, error } = await supabase
    .from('owner_ledger_entries')
    .select('id, transaction_type, debit, credit, date, created_at')
    .in('owner_id', ownerIds);

  if (error) {
    console.error('Error fetching ledger entries for late notice:', error);
  } else if (ledgerEntries?.length) {
    const { rows } = buildLedgerAccountBreakdown(ledgerEntries);
    items = buildNoticeItemsFromLedgerRows(rows);
  }

  return {
    ownerName,
    ownerAddressLine1: addrLines.line1,
    ownerAddressLine2: addrLines.line2,
    ownerAddressLine3: addrLines.line3,
    ownerAddressLine4: addrLines.line4,
    propertyAddress: owner.property_address || '',
    accountNo: owner.units?.account_number || owner.account_number || '',
    items: items.length > 0 ? items : cloneItems(fallbackItems),
    hiddenItems: [],
  };
}

export default function LateAssessmentForm() {
  const { toast } = useToast();
  const [searchParams] = useSearchParams();
  const prefillApplied = useRef(false);
  const [associations, setAssociations] = useState([]);
  const [owners, setOwners] = useState([]);
  const [loading, setLoading] = useState(false);
  const [selectedAssociationId, setSelectedAssociationId] = useState('');
  const [selectedOwnerId, setSelectedOwnerId] = useState('');
  const [showSaveDocsDialog, setShowSaveDocsDialog] = useState(false);
  const [showSaveResidentDialog, setShowSaveResidentDialog] = useState(false);

  // Queue for Batch Generation
  const [batchQueue, setBatchQueue] = useState([]);

  // PDF Settings
  const [pdfConfig, setPdfConfig] = useState({
    font: 'helvetica',
    fontSize: '10',
    textAlign: 'left'
  });

  // Calculate default due date (30 days from now)
  const getDefaultDueDate = () => {
    const d = new Date();
    d.setDate(d.getDate() + 30);
    return d.toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' });
  };

  // Form State
  const [formData, setFormData] = useState({
    date: new Date().toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' }),
    dueDate: getDefaultDueDate(),
    certifiedMailNumber: '',
    
    // Owner Info
    ownerName: '',
    ownerAddressLine1: '',
    ownerAddressLine2: '',
    ownerAddressLine3: '', 
    ownerAddressLine4: '', 
    
    // Property Info
    propertyAddress: '',
    accountNo: '',
    
    // Financials
    items: getDefaultNoticeItems(),
    hiddenItems: [], 
    
    interestRate: '12.00',
    
    // Association Info
    associationName: '',
    paymentAddressLine1: 'P.O. Box 560060',
    paymentAddressLine2: 'Rockledge, Florida 32956',
    noticeLogo: '',
    footerLogo: '',
    
    // Management Info
    managementCompany: 'Avria Community Management, LLC',
    managementEmail: '',
    managementPhone: '(321) 405-2449',
    managementWebsite: ''
  });

  useEffect(() => {
    fetchAssociations();
  }, []);

  // Auto-fill from Outstanding Balances URL params
  useEffect(() => {
    if (prefillApplied.current || associations.length === 0) return;
    const associationId = searchParams.get('associationId');
    const ownerId = searchParams.get('ownerId');
    if (!associationId) return;

    prefillApplied.current = true;

    // Select association
    const assoc = associations.find(c => c.id === associationId);
    if (assoc) {
      setSelectedAssociationId(associationId);
      setFormData(prev => ({
        ...prev,
        associationName: assoc.name,
        managementEmail: assoc.email || prev.managementEmail,
        managementWebsite: assoc.website || prev.managementWebsite,
        managementPhone: assoc.phone || prev.managementPhone,
        noticeLogo: assoc.logo_url || ''
      }));
    }

    // Fetch owners then auto-select + fill financials
    const doOwnerPrefill = async () => {
      const { data: ownerData } = await supabase
        .from('owners')
        .select('*, units(unit_number, account_number)')
        .eq('association_id', associationId)
        .neq('status', 'archived')
        .order('last_name');
      
      if (ownerData) setOwners(ownerData);

      const owner = ownerId && ownerData ? ownerData.find(o => o.id === ownerId) : null;

      const ownerName = searchParams.get('ownerName') || '';
      const address = searchParams.get('address') || '';
      const assessments = searchParams.get('assessments') || '0.00';
      const lateFees = searchParams.get('lateFees') || '0.00';
      const interest = searchParams.get('interest') || '0.00';
      const adminFees = searchParams.get('adminFees') || '0.00';
      const legalFees = searchParams.get('legalFees') || '0.00';
      const violations = searchParams.get('violations') || '0.00';
      const bankFees = searchParams.get('bankFees') || '0.00';
      const queryParamItems = buildNoticeItemsFromQueryParams({
        assessments,
        lateFees,
        interest,
        adminFees,
        legalFees,
        violations,
        bankFees,
      });

      if (owner) {
        setSelectedOwnerId(owner.id);
        const ownerNoticeData = await buildOwnerNoticePrefill(owner, ownerData || [], queryParamItems);

        setFormData(prev => ({
          ...prev,
          ...ownerNoticeData,
          propertyAddress: ownerNoticeData.propertyAddress || address,
        }));
      } else if (ownerName) {
        setFormData(prev => ({
          ...prev,
          ownerName,
          ownerAddressLine1: ownerName,
          propertyAddress: address,
          items: queryParamItems,
          hiddenItems: [],
        }));
      }
    };

    doOwnerPrefill();
  }, [associations, searchParams]);

  const fetchAssociations = async () => {
    const { data, error } = await supabase.from('associations').select('id, name, address, email, website, phone, logo_url').neq('status', 'archived');
    if (!error) setAssociations(data || []);
  };

  const fetchOwners = async (associationId) => {
    const { data, error } = await supabase
      .from('owners')
      .select('*, units(unit_number, account_number)')
      .eq('association_id', associationId)
      .neq('status', 'archived')
      .order('last_name');
    
    if (!error) setOwners(data || []);
    else setOwners([]);
  };

  const handleAssociationChange = (associationId) => {
    setSelectedAssociationId(associationId);
    fetchOwners(associationId);
    setBatchQueue([]);
    
    const assoc = associations.find(c => c.id === associationId);
    if (assoc) {
      setFormData(prev => ({
        ...prev,
        associationName: assoc.name,
        managementEmail: assoc.email || prev.managementEmail,
        managementWebsite: assoc.website || prev.managementWebsite,
        managementPhone: assoc.phone || prev.managementPhone,
        noticeLogo: assoc.logo_url || ''
      }));
    }
  };

  const handleOwnerChange = async (ownerId) => {
    setSelectedOwnerId(ownerId);
    const owner = owners.find(o => o.id === ownerId);
    
    if (owner) {
      const ownerNoticeData = await buildOwnerNoticePrefill(owner, owners);

      setFormData(prev => ({
        ...prev,
        ...ownerNoticeData,
      }));
    }
  };

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData(prev => ({ ...prev, [name]: value }));
  };

  const handleItemChange = (index, field, value) => {
    const newItems = [...formData.items];
    newItems[index][field] = value;
    setFormData(prev => ({ ...prev, items: newItems }));
  };

  const addItem = () => {
    setFormData(prev => ({
      ...prev,
      items: [...prev.items, { description: '', amount: '0.00' }]
    }));
  };

  const removeItem = (index) => {
    const newItems = formData.items.filter((_, i) => i !== index);
    setFormData(prev => ({ ...prev, items: newItems }));
  };

  const handleHiddenItemChange = (index, field, value) => {
    const newItems = [...formData.hiddenItems];
    newItems[index][field] = value;
    setFormData(prev => ({ ...prev, hiddenItems: newItems }));
  };

  const addHiddenItem = () => {
    setFormData(prev => ({
      ...prev,
      hiddenItems: [...prev.hiddenItems, { description: 'Admin Fee', amount: '0.00' }]
    }));
  };

  const removeHiddenItem = (index) => {
    const newItems = formData.hiddenItems.filter((_, i) => i !== index);
    setFormData(prev => ({ ...prev, hiddenItems: newItems }));
  };

  const getTotal = (visibleItems = formData.items, hiddenItems = formData.hiddenItems) => {
    const visibleTotal = visibleItems.reduce((acc, item) => {
      const val = parseFloat(item.amount.replace(/,/g, '')) || 0;
      return acc + val;
    }, 0);
    const hiddenTotal = hiddenItems.reduce((acc, item) => {
      const val = parseFloat(item.amount.replace(/,/g, '')) || 0;
      return acc + val;
    }, 0);
    return (visibleTotal + hiddenTotal).toFixed(2);
  };

  const addToQueue = () => {
    if (!formData.ownerName) {
        toast({ variant: "destructive", title: "Error", description: "Owner name is required." });
        return;
    }
    const newItem = {
        ...formData,
        id: Date.now(),
        items: JSON.parse(JSON.stringify(formData.items)),
        hiddenItems: JSON.parse(JSON.stringify(formData.hiddenItems))
    };
    setBatchQueue(prev => [...prev, newItem]);
    toast({ title: "Added to Queue", description: `${formData.ownerName} added to batch.` });
  };

  const removeFromQueue = (id) => {
    setBatchQueue(prev => prev.filter(i => i.id !== id));
  };
  
  const generatePDF = async (action = 'download') => {
    setLoading(true);
    
    let itemsToPrint = [];
    if (batchQueue.length > 0) {
        itemsToPrint = batchQueue;
    } else {
        itemsToPrint = [formData];
    }
    
    try {
      const doc = new jsPDF({
        orientation: 'portrait',
        unit: 'pt',
        format: 'letter'
      });
      
      const pageWidth = doc.internal.pageSize.getWidth();
      const pageHeight = doc.internal.pageSize.getHeight();
      const margin = 54; 
      
      const returnAddressX = 38; 
      const returnAddressY = 60;
      
      const baseFontSize = parseInt(pdfConfig.fontSize) || 10;
      const baseFont = pdfConfig.font;

      let headerLogoData = null;
      if (itemsToPrint[0].noticeLogo) headerLogoData = await loadImage(itemsToPrint[0].noticeLogo);
      
      let footerLogoData = null;
      if (itemsToPrint[0].footerLogo) footerLogoData = await loadImage(itemsToPrint[0].footerLogo);

      for (let i = 0; i < itemsToPrint.length; i++) {
        if (i > 0) doc.addPage();
        const startPage = doc.internal.getNumberOfPages();
        const data = itemsToPrint[i];
        
        const alignRight = (text, y, fontSize = baseFontSize, font = baseFont, style = "normal") => {
            doc.setFont(font, style);
            doc.setFontSize(fontSize);
            const w = doc.getTextWidth(text);
            doc.text(text, pageWidth - margin - w, y);
        };

        doc.setFont(baseFont, "normal");
        doc.setFontSize(baseFontSize);
        doc.setTextColor(0);

        // --- 1. HEADER (Return Address) ---
        let currentY = returnAddressY;
        doc.setFontSize(baseFontSize); 
        doc.setFont(baseFont, "normal");

        doc.text(data.associationName, returnAddressX, currentY);
        currentY += 12;
        doc.text("c/o " + data.managementCompany, returnAddressX, currentY);
        currentY += 12;
        doc.text(data.paymentAddressLine1, returnAddressX, currentY);
        currentY += 12;
        doc.text(data.paymentAddressLine2, returnAddressX, currentY);
        currentY += 12;

        let logoY = margin - 15; 
        if (headerLogoData) {
            const { dataURL, width, height } = headerLogoData;
            const maxLogoW = 180; 
            const maxLogoH = 50;
            let logoW = maxLogoW;
            let logoH = logoW * (width / height);
            if (logoH > maxLogoH) {
                logoH = maxLogoH;
                logoW = logoH * (width / height);
            }
            doc.addImage(dataURL, 'PNG', pageWidth - margin - logoW, logoY, logoW, logoH);
        }

        // --- 2. RECIPIENT BLOCK ---
        const addressBlockX = margin; 
        let addressBlockY = 175; 
        
        if (currentY > addressBlockY) addressBlockY = currentY + 20;

        alignRight(data.date, addressBlockY, baseFontSize, baseFont, "bold");
        
        let addrY = addressBlockY;
        doc.setFont(baseFont, "normal");
        doc.setFontSize(baseFontSize);
        
        const mailLines = [
            data.ownerAddressLine1,
            data.ownerAddressLine2,
            data.ownerAddressLine3,
            data.ownerAddressLine4
        ].filter(l => l && l.trim().length > 0);

        if (mailLines.length > 0) {
            mailLines.forEach(line => {
                doc.text(String(line), addressBlockX, addrY);
                addrY += 12;
            });
        } else {
             doc.text(data.ownerName, addressBlockX, addrY); addrY += 12;
        }

        currentY = Math.max(addrY + 30, 240); 

        // Certified Mail
        if (data.certifiedMailNumber) {
            let certY = addressBlockY + 40; 
            alignRight("Sent via U.S. Mail and U.S. Certified Mail No.:", certY, 9, baseFont, "bold"); 
            certY += 11;
            alignRight(data.certifiedMailNumber, certY, 9, baseFont, "normal");
        }
        
        // --- 3. TITLE ---
        doc.setFontSize(baseFontSize + 2); 
        doc.setFont(baseFont, "bold");
        const titleText = "NOTICE OF LATE ASSESSMENT";
        const titleWidth = doc.getTextWidth(titleText);
        const titleX = (pageWidth - titleWidth) / 2;
        
        doc.text(titleText, titleX, currentY);
        doc.line(titleX, currentY + 2, titleX + titleWidth, currentY + 2); 
        currentY += 30;

        // --- 4. RE: BLOCK ---
        const reX = margin + 20;
        doc.setFont(baseFont, "normal");
        doc.setFontSize(baseFontSize);
        
        doc.text("Re: Property Address:", reX, currentY);
        doc.text("Account No.:", reX, currentY + 14);
        doc.setFont(baseFont, "bold");
        doc.text("Amount Due:", reX, currentY + 28);
        
        const valX = reX + 110;
        const totalDue = getTotal(data.items, data.hiddenItems);

        doc.setFont(baseFont, "normal");
        doc.text(data.propertyAddress, valX, currentY);
        doc.text(data.accountNo, valX, currentY + 14);
        doc.setFont(baseFont, "bold");
        doc.text(`$${totalDue}`, valX, currentY + 28);
        
        currentY += 50;

        const textAlign = pdfConfig.textAlign || 'left';
        const paragraphGap = baseFontSize * 0.8;

        const writeTextBlock = async (text, startY, isBold = false) => {
            const block = {
                type: 'paragraph',
                content: text,
                styles: {
                    fontSize: baseFontSize,
                    fontFamily: baseFont,
                    textAlign: textAlign,
                    fontWeight: isBold ? 'bold' : 'normal'
                }
            };
            const endY = await drawBlock(doc, block, startY, pageWidth, { left: margin, right: margin, top: margin, bottom: 50 });
            return endY + paragraphGap;
        };

        // --- 5. BODY ---
        doc.setFont(baseFont, "normal");
        doc.text(`Dear ${data.ownerName}:`, margin, currentY);
        currentY += 20;
        
        const p1 = `The following amounts are currently due on your account to ${data.associationName}, and must be paid within thirty (30) days of the date of this letter. This letter shall serve as the association's notice of its intent to proceed with further collection against your property no sooner than thirty (30) days of the date of this letter, unless you pay in full the amounts set forth below, plus any additional assessments that may become due prior to the thirty (30) day time period. The amount currently due are as followed:`;
        currentY = await writeTextBlock(p1, currentY);

        // --- 6. BREAKDOWN TABLE ---
        const tableIndent = margin + 40;
        const dollarSignX = pageWidth - margin - 120;
        const amountRightEdge = pageWidth - margin - 60;
        
        if (currentY + (data.items.length * 15) + 40 > pageHeight - 120) {
            doc.addPage();
            currentY = margin + 30;
        }

        data.items.forEach(item => {
            doc.setFont(baseFont, "normal");
            doc.setFontSize(baseFontSize);
            doc.text(`${item.description}:`, tableIndent, currentY);
            doc.text("$", dollarSignX, currentY);
            const fmtAmt = parseFloat(item.amount.replace(/,/g, '') || '0').toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
            doc.text(fmtAmt, amountRightEdge, currentY, { align: 'right' });
            currentY += 15;
        });
        
        currentY += 5;
        doc.setLineWidth(0.5);
        doc.line(tableIndent, currentY, amountRightEdge + 10, currentY);
        currentY += 15;
        
        doc.setFont(baseFont, "bold");
        doc.setFontSize(baseFontSize);
        doc.text("TOTAL AMOUNT DUE:", tableIndent, currentY);
        doc.text("$", dollarSignX, currentY);
        const fmtTotal = parseFloat(totalDue.replace(/,/g, '') || '0').toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
        doc.text(fmtTotal, amountRightEdge, currentY, { align: 'right' });
        
        currentY += 30;

        const p2Content = `This amount must be paid by cashier's check or money order no later than thirty (30) days from the date of this letter, which is on or before <b><u>${data.dueDate}</u></b>. Interest accrues at a rate of ${data.interestRate}% per annum. The above charges do not necessarily reflect all outstanding charges. Please review the enclosed ledger for full accuracy of the amounts due and owing.`;
        currentY = await writeTextBlock(p2Content, currentY);

        const p3 = `All payments for any monetary obligation due to the Association on this property must be made payable to: ${data.associationName}, and sent to ${data.managementCompany} at the following address:`;
        currentY = await writeTextBlock(p3, currentY);

        if (currentY + 60 > pageHeight - 120) {
            doc.addPage();
            currentY = margin + 30;
        }
        
        doc.setFont(baseFont, "normal");
        const payIndent = margin + 20;
        doc.text(data.associationName, payIndent, currentY);
        currentY += 11;
        doc.text(`c/o ${data.managementCompany}`, payIndent, currentY);
        currentY += 11;
        doc.text(data.paymentAddressLine1, payIndent, currentY);
        currentY += 11;
        doc.text(data.paymentAddressLine2, payIndent, currentY);
        
        currentY += 25;

        const closing = "Please be sure to indicate the association name and property address with your payment. Please govern yourself accordingly.";
        currentY = await writeTextBlock(closing, currentY);

        if (currentY + 60 > pageHeight - 120) {
            doc.addPage();
            currentY = margin + 30;
        }

        doc.text("Sincerely,", margin, currentY);
        currentY += 25; 
        doc.text(data.managementCompany, margin, currentY);
        currentY += 11;
        doc.text(`Managing Agent for ${data.associationName}`, margin, currentY);
        
        currentY += 30;

        const legalText = `NOTICE: Pursuant to 15 U.S.C.S. § 1 692(g)(a) ${data.managementCompany} is attempting to collect a debt and any information obtained will be used for that purpose. The above-referenced Association is the creditor to whom the debt is owed. Unless you, the debtor, within thirty (30) days after receipt of this notice dispute the validity of the debt or any portion thereof, ${data.managementCompany}, will assume the debt is valid. If you notify ${data.managementCompany} in writing within a thirty (30) day period that the debt, or any portion thereof, is disputed, ${data.managementCompany} shall obtain written verification of the debt and mail the same to you.`;
        currentY = await writeTextBlock(legalText, currentY, true); 

        // --- 10. FOOTER ---
        const endPage = doc.internal.getNumberOfPages();
        for (let j = startPage; j <= endPage; j++) {
            doc.setPage(j);
            const footerLineY = pageHeight - 50;
            
            if (footerLogoData) {
                const { dataURL, width, height } = footerLogoData;
                const fLogoH = 25; 
                const fLogoW = fLogoH * (width / height);
                doc.addImage(dataURL, 'PNG', (pageWidth - fLogoW) / 2, footerLineY - fLogoH - 5, fLogoW, fLogoH);
            } else {
                doc.setFont("helvetica", "bold");
                doc.setFontSize(10);
                const txt = "ACM";
                const w = doc.getTextWidth(txt);
                doc.text(txt, (pageWidth - w)/2, footerLineY - 15);
            }

            doc.setDrawColor(0);
            doc.setLineWidth(0.5);
            doc.line(margin, footerLineY, pageWidth - margin, footerLineY);
            
            const infoY = footerLineY + 15;
            doc.setFont("helvetica", "normal");
            doc.setFontSize(8); 
            
            doc.text(`Phone: ${data.managementPhone}`, margin, infoY);
            const emailW = doc.getTextWidth(data.managementEmail);
            doc.text(data.managementEmail, (pageWidth - emailW) / 2, infoY);
            const webW = doc.getTextWidth(data.managementWebsite);
            doc.text(data.managementWebsite, pageWidth - margin - webW, infoY);

            const pageNumText = `${j - startPage + 1}`;
            const pW = doc.getTextWidth(pageNumText);
            doc.text(pageNumText, (pageWidth - pW) / 2, pageHeight - 20); 
        }
      }

      if (action === 'blob') {
          return doc.output('blob');
      } else {
          const fileName = itemsToPrint.length > 1 ? `Batch_Late_Notices_${new Date().toISOString().split('T')[0]}.pdf` : `Late_Notice_${formData.ownerName.replace(/\s+/g, '_')}.pdf`;
          doc.save(fileName);
          toast({ title: "Success", description: "PDF Generated successfully." });
      }

    } catch (err) {
      console.error(err);
      toast({ variant: "destructive", title: "Error", description: "Failed to generate PDF" });
      return null;
    } finally {
      setLoading(false);
    }
  };

  const handleSaveToDocuments = async (metadata) => {
    try {
        const blob = await generatePDF('blob');
        if (!blob) throw new Error("Failed to generate PDF blob.");

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

        // Display name kept human-readable for the documents row.
        const displayFileName = `${metadata.name.replace(/[^a-zA-Z0-9._ -]+/g, '_').trim()}.pdf`;
        // Storage key is randomized so the public URL doesn't expose the real name.
        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);

        // Insert document record into documents table
        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;

        toast({ title: 'Success', description: 'Document saved successfully.' });
        return { blob };
    } catch (err) {
        console.error(err);
        toast({ variant: 'destructive', title: 'Error saving document', description: err.message });
        throw err;
    }
  };

  return (
    <div className="max-w-5xl mx-auto">
      <Card>
        <CardHeader className="bg-muted/50 border-b">
          <div className="flex justify-between items-start">
              <div>
                <CardTitle className="text-xl flex items-center gap-2">
                    <Calculator className="w-5 h-5 text-primary" />
                    Notice of Late Assessment Generator
                </CardTitle>
              </div>
          </div>
        </CardHeader>
        <CardContent className="p-6 space-y-8">
          
          {/* Section 1: Association & Basic Info */}
          <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
            <div>
              <Label>Select Association</Label>
              <Select onValueChange={handleAssociationChange} value={selectedAssociationId}>
                <SelectTrigger>
                  <SelectValue placeholder="Select Association" />
                </SelectTrigger>
                <SelectContent>
                  {associations.map((assoc) => (
                    <SelectItem key={assoc.id} value={assoc.id}>
                      {assoc.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div className="grid grid-cols-3 gap-4">
                <div>
                    <Label>Letter Date</Label>
                    <Input name="date" value={formData.date} onChange={handleChange} />
                </div>
                <div>
                    <Label>Due Date</Label>
                    <Input name="dueDate" value={formData.dueDate} onChange={handleChange} placeholder="e.g. Jan 16, 2026" />
                </div>
                <div>
                    <Label>Interest Rate (%)</Label>
                    <Input name="interestRate" value={formData.interestRate} onChange={handleChange} />
                </div>
            </div>
          </div>
          
          <div>
              <Label>Certified Mail No.</Label>
              <Input 
                name="certifiedMailNumber" 
                value={formData.certifiedMailNumber} 
                onChange={handleChange} 
                placeholder="Optional"
              />
          </div>
          
          {/* PDF Styling */}
          <PdfStylingControls pdfConfig={pdfConfig} onChange={setPdfConfig} />

          {/* Branding Configuration */}
          <Accordion type="single" collapsible className="w-full bg-muted/50 rounded-lg border">
            <AccordionItem value="branding" className="border-none">
              <AccordionTrigger className="px-4 py-3 text-muted-foreground font-medium hover:no-underline">
                <div className="flex items-center gap-2">
                  <Settings className="w-4 h-4" />
                  Logos & Branding Configuration
                </div>
              </AccordionTrigger>
              <AccordionContent className="px-4 pb-4 pt-2 bg-background rounded-b-lg border-t">
                 <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
                    <div className="space-y-2">
                      <Label>Header Logo URL (Top Right)</Label>
                      <Input name="noticeLogo" value={formData.noticeLogo} onChange={handleChange} />
                    </div>
                    <div className="space-y-2">
                      <Label>Footer Logo URL (Centered)</Label>
                      <Input name="footerLogo" value={formData.footerLogo} onChange={handleChange} />
                    </div>
                    <div className="space-y-2">
                       <Label>Mgmt Phone</Label>
                       <Input name="managementPhone" value={formData.managementPhone} onChange={handleChange} />
                    </div>
                    <div className="space-y-2">
                       <Label>Mgmt Email</Label>
                       <Input name="managementEmail" value={formData.managementEmail} onChange={handleChange} />
                    </div>
                    <div className="space-y-2">
                       <Label>Mgmt Website</Label>
                       <Input name="managementWebsite" value={formData.managementWebsite} onChange={handleChange} />
                    </div>
                 </div>
              </AccordionContent>
            </AccordionItem>
          </Accordion>

          <Separator />

          {/* Section 2: Recipient Info */}
          <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
            <div className="space-y-4">
              <div className="flex justify-between items-center">
                  <h3 className="font-semibold text-foreground">Owner Information</h3>
                  <Button size="sm" variant="ghost" className="text-primary" onClick={addToQueue}>
                      <Plus className="w-4 h-4 mr-1" /> Add to Queue
                  </Button>
              </div>
              <div className="space-y-2">
                 <Label>Select Owner (Autofill)</Label>
                 <Combobox
                   options={owners.map(o => ({
                     value: o.id,
                     label: `${o.first_name} ${o.last_name} - ${o.property_address || ''}`
                   }))}
                   value={selectedOwnerId}
                   onChange={handleOwnerChange}
                   placeholder="Select Owner from List"
                   disabled={!selectedAssociationId}
                   emptyText="No owner found."
                   className="w-full"
                 />
              </div>

              <div className="space-y-2">
                <Label>Owner Name</Label>
                <Input name="ownerName" placeholder="e.g. John Doe" value={formData.ownerName} onChange={handleChange} />
              </div>
              
               <div className="bg-muted/50 p-3 rounded border">
                     <p className="text-xs font-semibold text-muted-foreground mb-2 uppercase">Mailing Address</p>
                     <div className="space-y-2">
                        <Input name="ownerAddressLine1" value={formData.ownerAddressLine1} onChange={handleChange} placeholder="Line 1" className="h-8 text-sm"/>
                        <Input name="ownerAddressLine2" value={formData.ownerAddressLine2} onChange={handleChange} placeholder="Line 2" className="h-8 text-sm"/>
                        <Input name="ownerAddressLine3" value={formData.ownerAddressLine3} onChange={handleChange} placeholder="Line 3" className="h-8 text-sm"/>
                        <Input name="ownerAddressLine4" value={formData.ownerAddressLine4} onChange={handleChange} placeholder="Line 4" className="h-8 text-sm"/>
                     </div>
                 </div>
            </div>

            <div className="space-y-4">
              <h3 className="font-semibold text-foreground">Financial Breakdown</h3>
              <div className="bg-muted/50 p-4 rounded-lg border space-y-3">
                  {formData.items.map((item, idx) => (
                      <div key={idx} className="flex gap-2 items-end">
                          <div className="flex-grow">
                              <Label className="text-xs">Description</Label>
                              <Input 
                                value={item.description} 
                                onChange={(e) => handleItemChange(idx, 'description', e.target.value)} 
                                className="h-8 text-sm"
                              />
                          </div>
                          <div className="w-24">
                              <Label className="text-xs">Amount ($)</Label>
                              <Input 
                                value={item.amount} onChange={(e) => handleItemChange(idx, 'amount', e.target.value)} 
                                className="h-8 text-sm text-right"
                              />
                          </div>
                          <Button 
                            variant="ghost" size="icon" className="h-8 w-8 text-destructive"
                            onClick={() => removeItem(idx)}
                          >
                              <Trash2 className="w-4 h-4" />
                          </Button>
                      </div>
                  ))}
                  <Button variant="outline" size="sm" onClick={addItem} className="w-full mt-2">
                      <Plus className="w-3 h-3 mr-2" /> Add Item
                  </Button>
              </div>

              {/* Hidden Items Section */}
              <div className="bg-orange-50 dark:bg-orange-950/20 p-4 rounded-lg border border-orange-200 dark:border-orange-800 space-y-3">
                  <div className="flex justify-between items-center mb-1">
                      <h4 className="text-sm font-semibold text-orange-800 dark:text-orange-300 flex items-center gap-1">
                          <EyeOff className="w-4 h-4" /> 
                          Hidden Fees
                      </h4>
                      <span className="text-[10px] text-orange-600 dark:text-orange-400 uppercase font-medium">Included in Total, Hidden from Ledger</span>
                  </div>
                  
                  {formData.hiddenItems.map((item, idx) => (
                      <div key={idx} className="flex gap-2 items-end">
                          <div className="flex-grow">
                              <Label className="text-xs text-orange-700 dark:text-orange-400">Description (Hidden)</Label>
                              <Input 
                                value={item.description} 
                                onChange={(e) => handleHiddenItemChange(idx, 'description', e.target.value)} 
                                className="h-8 text-sm bg-background"
                              />
                          </div>
                          <div className="w-24">
                              <Label className="text-xs text-orange-700 dark:text-orange-400">Amount ($)</Label>
                              <Input 
                                value={item.amount} 
                                onChange={(e) => handleHiddenItemChange(idx, 'amount', e.target.value)} 
                                className="h-8 text-sm text-right bg-background"
                              />
                          </div>
                          <Button 
                            variant="ghost" size="icon" className="h-8 w-8 text-orange-400 hover:text-orange-600"
                            onClick={() => removeHiddenItem(idx)}
                          >
                              <Trash2 className="w-4 h-4" />
                          </Button>
                      </div>
                  ))}
                  <Button variant="outline" size="sm" onClick={addHiddenItem} className="w-full mt-2 border-orange-300 text-orange-700 hover:bg-orange-100">
                      <Plus className="w-3 h-3 mr-2" /> Add Hidden Fee
                  </Button>
              </div>

              <div className="flex justify-between items-center pt-2 border-t mt-2">
                  <span className="font-bold text-foreground">Total Amount Due:</span>
                  <span className="font-bold text-lg">${getTotal()}</span>
              </div>

              <div className="space-y-2 mt-4">
                <Label>Property Address (Reference)</Label>
                <Input name="propertyAddress" value={formData.propertyAddress} onChange={handleChange} />
              </div>
              <div className="space-y-2">
                <Label>Account Number</Label>
                <Input name="accountNo" value={formData.accountNo} onChange={handleChange} />
              </div>
            </div>
          </div>

          {/* Queue Section */}
          {batchQueue.length > 0 && (
              <div className="space-y-4 pt-4 border-t">
                  <h3 className="font-semibold text-foreground">Batch Generation Queue ({batchQueue.length})</h3>
                  <div className="border rounded-md max-h-60 overflow-y-auto">
                    <Table>
                        <TableHeader>
                            <TableRow>
                                <TableHead>Owner</TableHead>
                                <TableHead>Property</TableHead>
                                <TableHead>Total Due</TableHead>
                                <TableHead></TableHead>
                            </TableRow>
                        </TableHeader>
                        <TableBody>
                            {batchQueue.map(item => (
                                <TableRow key={item.id}>
                                    <TableCell>{item.ownerName}</TableCell>
                                    <TableCell>{item.propertyAddress}</TableCell>
                                    <TableCell>${getTotal(item.items, item.hiddenItems)}</TableCell>
                                    <TableCell>
                                        <Button variant="ghost" size="sm" onClick={() => removeFromQueue(item.id)}>
                                            <Trash2 className="w-4 h-4 text-destructive" />
                                        </Button>
                                    </TableCell>
                                </TableRow>
                            ))}
                        </TableBody>
                    </Table>
                  </div>
              </div>
          )}

          <div className="flex justify-end gap-2 pt-6">
            <Button
              variant="outline"
              onClick={() => setShowSaveDocsDialog(true)}
              disabled={loading}
              title="Save PDF directly to Documents"
            >
              <FolderDown className="w-4 h-4 mr-2" /> Save to Docs
            </Button>
            {(() => {
              const sel = owners.find(o => o.id === selectedOwnerId);
              const unitNum = sel?.units?.unit_number;
              if (!unitNum || batchQueue.length > 0) return null;
              return (
                <Button
                  variant="outline"
                  onClick={() => setShowSaveResidentDialog(true)}
                  disabled={loading}
                  title={`Save to Resident Files / ${unitNum}`}
                >
                  <FolderDown className="w-4 h-4 mr-2" /> Save to Resident File
                </Button>
              );
            })()}
            <Button 
              onClick={() => generatePDF('download')} 
              disabled={loading}
              className="min-w-[200px]"
            >
              {loading ? <Loader2 className="w-4 h-4 animate-spin mr-2" /> : <FileDown className="w-4 h-4 mr-2" />}
              {batchQueue.length > 0 ? `Generate Batch PDF (${batchQueue.length})` : "Generate Late Notice"}
            </Button>
          </div>

        </CardContent>
      </Card>

      <SaveToDocumentsDialog
        open={showSaveDocsDialog}
        onOpenChange={setShowSaveDocsDialog}
        onSave={handleSaveToDocuments}
        defaultName={batchQueue.length > 0 ? `Batch Late Notices` : `Late Notice - ${formData.ownerName}`}
        defaultClientId={selectedAssociationId}
      />

      <SaveToDocumentsDialog
        open={showSaveResidentDialog}
        onOpenChange={setShowSaveResidentDialog}
        onSave={handleSaveToDocuments}
        defaultName={`Late Notice - ${formData.ownerName}`}
        defaultClientId={selectedAssociationId}
        residentFileMode
        unitId={(owners.find(o => o.id === selectedOwnerId)?.unit_id) || ""}
        unitNumber={(owners.find(o => o.id === selectedOwnerId)?.units?.unit_number) || ""}
      />
    </div>
  );
}
