import { useState, useEffect, useMemo, useCallback } from "react";
import { format } from "date-fns";
import { cn } from "@/lib/utils";
import { Calendar } from "@/components/ui/calendar";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { CalendarIcon } from "lucide-react";
import { supabase } from "@/integrations/supabase/client";
import { useToast } from "@/hooks/use-toast";
import { useAuth } from "@/contexts/AuthContext";
import {
  DollarSign, Search, AlertTriangle, CheckCircle2, Clock, ArrowUpDown,
  Scale, FileText, Send, Gavel, CreditCard, ChevronRight, RefreshCw,
  TrendingUp, Users, Banknote, CalendarClock, X, Plus, MoreHorizontal, Trash2, Briefcase, FileDown
} from "lucide-react";
import CollectionDialog from "@/components/CollectionDialog";
import RecordImportButton from "@/components/RecordImportButton";
import { Checkbox } from "@/components/ui/checkbox";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription } from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@/components/ui/sheet";
import { Separator } from "@/components/ui/separator";
import { Progress } from "@/components/ui/progress";

// ─── Types ───────────────────────────────────────────────────────────
interface OwnerAccount {
  id: string; // unit_id or owner_id as key
  owners: { id: string; first_name: string; last_name: string; email: string | null; phone: string | null }[];
  balance: number;
  email: string | null;
  phone: string | null;
  association_id: string;
  unit_id: string | null;
  unit?: { id: string; unit_number: string; address: string | null } | null;
  collection?: {
    id: string;
    status: string;
    amount_owed: number;
    notes: string | null;
    last_notice_date: string | null;
    created_at: string;
    updated_at: string;
  } | null;
  ledgerBreakdown?: LedgerBreakdown;
  daysDelinquent?: number;
  paymentPlan?: any;
  // Display helpers
  first_name: string;
  last_name: string;
}

interface LedgerBreakdown {
  assessments: number;
  lateFees: number;
  interest: number;
  legalFees: number;
  adminFees: number;
  violations: number;
  bankFees: number;
  payments: number;
  total: number;
}

const PAYMENT_TYPES = ["payment", "prepayment", "applied_deposit", "applied_prepayment", "refund", "reversed_payment"];
const PAYMENT_TYPE_SET = new Set(PAYMENT_TYPES);

const currentMonthRange = () => {
  const now = new Date();
  return {
    start: format(new Date(now.getFullYear(), now.getMonth(), 1), "yyyy-MM-dd"),
    end: format(new Date(now.getFullYear(), now.getMonth() + 1, 0), "yyyy-MM-dd"),
  };
};

// ─── Stage Configuration ─────────────────────────────────────────────
const COLLECTION_STAGES = [
  { value: "late_notice", label: "Late Notice", icon: FileText, color: "bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-300", dotColor: "bg-amber-500" },
  { value: "second_notice", label: "NOLA", icon: Send, color: "bg-orange-100 text-orange-800 dark:bg-orange-900/30 dark:text-orange-300", dotColor: "bg-orange-500" },
  { value: "intent_to_lien", label: "Intent to Lien", icon: Scale, color: "bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300", dotColor: "bg-red-500" },
  { value: "attorney", label: "Attorney", icon: Gavel, color: "bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-300", dotColor: "bg-purple-500" },
  { value: "payment_plan", label: "Payment Plan", icon: CreditCard, color: "bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300", dotColor: "bg-blue-500" },
  { value: "bankruptcy_hold", label: "Bankruptcy Hold", icon: Scale, color: "bg-rose-100 text-rose-800 dark:bg-rose-900/30 dark:text-rose-300", dotColor: "bg-rose-500" },
  { value: "resolved", label: "Resolved", icon: CheckCircle2, color: "bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-300", dotColor: "bg-emerald-500" },
];

// Legacy status mapping
const LEGACY_MAP: Record<string, string> = {
  open: "late_notice",
  "in-collections": "second_notice",
  lien: "intent_to_lien",
};

function normalizeStage(status: string): string {
  return LEGACY_MAP[status] || status;
}

function normalizeCollectionSaveStatus(status: string): string {
  return normalizeStage(status) === "resolved" ? "closed" : status;
}

function isArchivedCollectionStatus(status: string): boolean {
  const normalized = normalizeStage(status);
  return normalized === "resolved" || normalized === "closed" || normalized === "archived";
}

function getAccountOwnerNames(account: OwnerAccount) {
  return account.owners.map((owner) => `${owner.first_name} ${owner.last_name}`.trim()).filter(Boolean);
}

function getStageConfig(status: string) {
  const normalized = normalizeStage(status);
  return COLLECTION_STAGES.find(s => s.value === normalized) || COLLECTION_STAGES[0];
}

function preferCollection(current: any, candidate: any) {
  if (!current) return candidate;

  const currentResolved = normalizeStage(current.status) === "resolved";
  const candidateResolved = normalizeStage(candidate.status) === "resolved";
  if (currentResolved !== candidateResolved) {
    return currentResolved ? candidate : current;
  }

  const currentUpdatedAt = new Date(current.updated_at || current.created_at || 0).getTime();
  const candidateUpdatedAt = new Date(candidate.updated_at || candidate.created_at || 0).getTime();
  if (currentUpdatedAt !== candidateUpdatedAt) {
    return candidateUpdatedAt > currentUpdatedAt ? candidate : current;
  }

  const currentAmount = Number(current.amount_owed || 0);
  const candidateAmount = Number(candidate.amount_owed || 0);
  if (currentAmount !== candidateAmount) {
    return candidateAmount > currentAmount ? candidate : current;
  }

  return candidate;
}

function categorizeLedger(entries: any[]): LedgerBreakdown {
  const b: LedgerBreakdown = { assessments: 0, lateFees: 0, interest: 0, legalFees: 0, adminFees: 0, violations: 0, bankFees: 0, payments: 0, total: 0 };

  // First pass: accumulate charges by category
  const charges: Record<string, number> = { assessment: 0, special_assessment: 0, late_fee: 0, interest: 0, legal_fee: 0, admin_fee: 0, violation: 0, bank_fee: 0 };
  let totalPayments = 0;

  entries.forEach(e => {
    const t = (e.transaction_type || "").trim().toLowerCase();
    const debit = e.debit || 0;
    const credit = e.credit || 0;

    if (PAYMENT_TYPE_SET.has(t)) {
      // For payments: credit is the payment amount, debit is reversal
      totalPayments += credit - debit;
    } else {
      // For charges: debit is the charge, credit is adjustment/reversal
      const net = debit - credit;
      if (t === "assessment" || t === "special_assessment") charges.assessment += net;
      else if (t === "late_fee") charges.late_fee += net;
      else if (t === "interest") charges.interest += net;
      else if (t === "legal_fee" || t === "legal") charges.legal_fee += net;
      else if (t === "admin_fee" || t === "admin") charges.admin_fee += net;
      else if (t === "violation") charges.violation += net;
      else if (t === "bank_fee") charges.bank_fee += net;
      else charges.assessment += net; // fallback
    }
  });

  b.assessments = charges.assessment;
  b.lateFees = charges.late_fee;
  b.interest = charges.interest;
  b.legalFees = charges.legal_fee;
  b.adminFees = charges.admin_fee;
  b.violations = charges.violation;
  b.bankFees = charges.bank_fee;
  b.payments = totalPayments;
  b.total = b.assessments + b.lateFees + b.interest + b.legalFees + b.adminFees + b.violations + b.bankFees - b.payments;
  return b;
}

function calcDaysDelinquent(collection: any): number {
  if (!collection?.created_at) return 0;
  return Math.max(0, Math.floor((Date.now() - new Date(collection.created_at).getTime()) / 86400000));
}

function isPaymentPlanAccount(account: OwnerAccount | null): boolean {
  return normalizeStage(account?.collection?.status || "") === "payment_plan" || Boolean(account?.paymentPlan);
}

const fmt = (n: number) => `$${Math.abs(n).toLocaleString(undefined, { minimumFractionDigits: 2 })}`;

// ─── Main Component ──────────────────────────────────────────────────
export default function CollectionsPage() {
  const { toast } = useToast();
  const { user } = useAuth();
  const [trackingLegalId, setTrackingLegalId] = useState<string | null>(null);
  const [accounts, setAccounts] = useState<OwnerAccount[]>([]);
  const [associations, setAssociations] = useState<{ id: string; name: string }[]>([]);
  const [filterAssociation, setFilterAssociation] = useState("all");
  const [filterDateFrom, setFilterDateFrom] = useState<Date | undefined>(undefined);
  const [filterDateTo, setFilterDateTo] = useState<Date | undefined>(undefined);
  const [loading, setLoading] = useState(true);
  const [search, setSearch] = useState("");
  const [stageTab, setStageTab] = useState("all");
  const [filterBalance, setFilterBalance] = useState("all");
  const [filterDays, setFilterDays] = useState("all");
  const [sortField, setSortField] = useState<string>("balance");
  const [sortDir, setSortDir] = useState<"asc" | "desc">("desc");

  // Detail panel
  const [detailOpen, setDetailOpen] = useState(false);
  const [selectedAccount, setSelectedAccount] = useState<OwnerAccount | null>(null);

  // Add dialog
  const [addDialogOpen, setAddDialogOpen] = useState(false);

  // Bulk selection
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
  const [bulkStageUpdating, setBulkStageUpdating] = useState(false);

  // Action dialogs
  const [actionDialog, setActionDialog] = useState<string | null>(null);
  const [actionNotes, setActionNotes] = useState("");
  const [actionStatus, setActionStatus] = useState("");

  // Last notice date manual update
  const [editingNoticeDate, setEditingNoticeDate] = useState(false);
  const [noticeDateSaving, setNoticeDateSaving] = useState(false);

  // Fee calculation
  const [calculatingFee, setCalculatingFee] = useState<string | null>(null);

  // ─── Data Loading ────────────────────────────────────────────────
  const fetchAccounts = useCallback(async () => {
    setLoading(true);
    try {
      // Paginated fetch for ledger entries (Supabase caps at 1000 per request)
      const fetchAllLedger = async () => {
        const all: any[] = [];
        const pageSize = 1000;
        let from = 0;
        while (true) {
          const { data, error } = await supabase
            .from("owner_ledger_entries")
            .select("owner_id, transaction_type, debit, credit, date")
            .range(from, from + pageSize - 1);
          if (error) throw error;
          if (!data || data.length === 0) break;
          all.push(...data);
          if (data.length < pageSize) break;
          from += pageSize;
        }
        return all;
      };

      const [ownersRes, collectionsRes, ledgerData, plansRes] = await Promise.all([
        supabase.from("owners").select("id, first_name, last_name, balance, email, phone, association_id, unit_id, units(id, unit_number, address)").eq("status", "active").order("last_name"),
        supabase
          .from("collections")
          .select("id, owner_id, unit_id, status, amount_owed, notes, last_notice_date, created_at, updated_at")
          .order("updated_at", { ascending: false })
          .order("created_at", { ascending: false }),
        fetchAllLedger(),
        supabase.from("payment_plans").select("id, owner_id, status, total_amount, monthly_payment, start_date, end_date"),
      ]);

      if (ownersRes.error) throw ownersRes.error;
      if (collectionsRes.error) throw collectionsRes.error;
      if (plansRes.error) throw plansRes.error;
      const ledgerRes = { data: ledgerData, error: null as any };

      // Prefer the newest active collection when duplicates exist for the same unit/owner
      const collectionByUnit = new Map<string, any>();
      const collectionByOwner = new Map<string, any>();
      (collectionsRes.data || []).forEach((c: any) => {
        if (c.unit_id) {
          collectionByUnit.set(c.unit_id, preferCollection(collectionByUnit.get(c.unit_id), c));
        }
        if (c.owner_id) {
          collectionByOwner.set(c.owner_id, preferCollection(collectionByOwner.get(c.owner_id), c));
        }
      });

      const ledgerMap = new Map<string, any[]>();
      const ledgerBalanceMap = new Map<string, number>();
      (ledgerRes.data || []).forEach((e: any) => {
        if (!ledgerMap.has(e.owner_id)) ledgerMap.set(e.owner_id, []);
        ledgerMap.get(e.owner_id)!.push(e);
        const net = (e.debit || 0) - (e.credit || 0);
        ledgerBalanceMap.set(e.owner_id, (ledgerBalanceMap.get(e.owner_id) || 0) + net);
      });

      const planMap = new Map<string, any>();
      (plansRes.data || []).forEach((p: any) => { if (p.status === "active") planMap.set(p.owner_id, p); });

      // Group owners by unit_id to combine co-owners
      const unitGroupMap = new Map<string, any[]>();
      (ownersRes.data || []).forEach((o: any) => {
        const key = o.unit_id || `owner-${o.id}`;
        if (!unitGroupMap.has(key)) unitGroupMap.set(key, []);
        unitGroupMap.get(key)!.push(o);
      });

      const merged: OwnerAccount[] = [];
      unitGroupMap.forEach((groupOwners, key) => {
        const firstOwner = groupOwners[0];
        const unitId = firstOwner.unit_id;

        // Find collection: prefer unit-level, then any owner-level
        const col = (unitId && collectionByUnit.get(unitId))
          || groupOwners.map((o: any) => collectionByOwner.get(o.id)).find(Boolean)
          || null;

        // Combine ledger entries and balances for all owners in the unit
        const allEntries = groupOwners.flatMap((o: any) => ledgerMap.get(o.id) || []);
        // Live balance: prefer ledger (source of truth). If ANY owner has ledger entries, trust ledger
        // (including 0 = fully paid). Only fall back to snapshot when no ledger data exists at all.
        const hasLedger = groupOwners.some((o: any) => ledgerBalanceMap.has(o.id));
        const ledgerBalance = groupOwners.reduce((s: number, o: any) => s + (ledgerBalanceMap.get(o.id) || 0), 0);
        const combinedOwnerBalance = groupOwners.reduce((s: number, o: any) => s + (o.balance || 0), 0);
        const combinedBalance = hasLedger ? ledgerBalance : (col?.amount_owed || combinedOwnerBalance);
        const plan = groupOwners.map((o: any) => planMap.get(o.id)).find(Boolean) || null;

        const ownerNames = groupOwners.map((o: any) => `${o.last_name}, ${o.first_name}`);

        merged.push({
          id: unitId || firstOwner.id,
          owners: groupOwners.map((o: any) => ({
            id: o.id, first_name: o.first_name, last_name: o.last_name,
            email: o.email, phone: o.phone,
          })),
          first_name: groupOwners.map((o: any) => o.first_name).join(" & "),
          last_name: firstOwner.last_name + (groupOwners.length > 1 ? ` (+${groupOwners.length - 1})` : ""),
          balance: combinedBalance,
          email: firstOwner.email,
          phone: firstOwner.phone,
          association_id: firstOwner.association_id,
          unit_id: unitId,
          unit: firstOwner.units || null,
          collection: col,
          ledgerBreakdown: categorizeLedger(allEntries),
          daysDelinquent: calcDaysDelinquent(col),
          paymentPlan: plan,
        });
      });

      setAccounts(merged);
    } catch (err: any) {
      console.error("Error fetching accounts:", err);
      toast({ variant: "destructive", title: "Error", description: "Failed to load collections data." });
    } finally {
      setLoading(false);
    }
  }, [toast]);

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

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

  // ─── Filtering & Sorting ────────────────────────────────────────
  const filtered = useMemo(() => {
    let result = accounts.filter(a => a.collection && !isArchivedCollectionStatus(a.collection.status)); // Only active accounts in collections

    if (filterAssociation !== "all") {
      result = result.filter(a => a.association_id === filterAssociation);
    }

    if (stageTab !== "all") {
      result = result.filter(a => normalizeStage(a.collection!.status) === stageTab);
    }

    if (search) {
      const q = search.toLowerCase();
      result = result.filter(a =>
        getAccountOwnerNames(a).some((name) => name.toLowerCase().includes(q)) ||
        a.unit?.unit_number?.toLowerCase().includes(q) ||
        a.unit?.address?.toLowerCase().includes(q)
      );
    }

    if (filterDateFrom) {
      result = result.filter(a => {
        const d = new Date(a.collection!.created_at);
        return d >= filterDateFrom;
      });
    }
    if (filterDateTo) {
      result = result.filter(a => {
        const d = new Date(a.collection!.created_at);
        return d <= filterDateTo;
      });
    }

    if (filterBalance === "over1000") result = result.filter(a => a.balance > 1000);
    else if (filterBalance === "over5000") result = result.filter(a => a.balance > 5000);
    else if (filterBalance === "over10000") result = result.filter(a => a.balance > 10000);

    if (filterDays === "30") result = result.filter(a => (a.daysDelinquent || 0) >= 30);
    else if (filterDays === "60") result = result.filter(a => (a.daysDelinquent || 0) >= 60);
    else if (filterDays === "90") result = result.filter(a => (a.daysDelinquent || 0) >= 90);
    else if (filterDays === "180") result = result.filter(a => (a.daysDelinquent || 0) >= 180);

    result = [...result].sort((a, b) => {
      let cmp = 0;
      if (sortField === "name") cmp = getAccountOwnerNames(a).join(" ").localeCompare(getAccountOwnerNames(b).join(" "));
      else if (sortField === "balance") cmp = a.balance - b.balance;
      else if (sortField === "days") cmp = (a.daysDelinquent || 0) - (b.daysDelinquent || 0);
      else if (sortField === "lastNotice") cmp = new Date(a.collection?.last_notice_date || 0).getTime() - new Date(b.collection?.last_notice_date || 0).getTime();
      else if (sortField === "status") cmp = normalizeStage(a.collection?.status || "").localeCompare(normalizeStage(b.collection?.status || ""));
      return sortDir === "desc" ? -cmp : cmp;
    });

    return result;
  }, [accounts, search, stageTab, filterBalance, filterDays, filterAssociation, filterDateFrom, filterDateTo, sortField, sortDir]);

  // ─── Metrics ─────────────────────────────────────────────────────
  const metrics = useMemo(() => {
    const inCollections = accounts.filter(a => a.collection && !isArchivedCollectionStatus(a.collection.status));
    const totalDelinquency = inCollections.reduce((s, a) => s + a.balance, 0);
    const avgBalance = inCollections.length ? totalDelinquency / inCollections.length : 0;
    const activePlans = accounts.filter(a => a.paymentPlan).length;
    return { totalDelinquency, delinquentUnits: inCollections.length, avgBalance, activePlans };
  }, [accounts]);

  const stageCounts = useMemo(() => {
    const counts: Record<string, number> = {};
    COLLECTION_STAGES.forEach(s => { counts[s.value] = 0; });
    accounts.forEach(a => {
      if (a.collection) {
        const norm = normalizeStage(a.collection.status);
        counts[norm] = (counts[norm] || 0) + 1;
      }
    });
    return counts;
  }, [accounts]);

  // ─── Actions ─────────────────────────────────────────────────────
  const toggleSort = (field: string) => {
    if (sortField === field) setSortDir(d => d === "asc" ? "desc" : "asc");
    else { setSortField(field); setSortDir("desc"); }
  };

  const openDetail = (account: OwnerAccount) => {
    setSelectedAccount(account);
    setDetailOpen(true);
  };

  const handleDeleteCollection = async () => {
    if (!selectedAccount?.collection) return;
    try {
      const { error } = await supabase.from("collections").delete().eq("id", selectedAccount.collection.id);
      if (error) throw error;
      // Clear delinquent status on the unit if applicable
      if (selectedAccount.unit_id) {
        await supabase.from("units").update({ status: "active" }).eq("id", selectedAccount.unit_id);
      }
      toast({ title: "Deleted", description: "Collection account removed." });
      setActionDialog(null);
      setDetailOpen(false);
      fetchAccounts();
    } catch (err: any) {
      toast({ variant: "destructive", title: "Error", description: err.message });
    }
  };

  const handleAction = async (action: string) => {
    if (!selectedAccount?.collection) return;
    try {
      let newStatus = selectedAccount.collection.status;
      if (action === "send_notice") {
        const current = normalizeStage(newStatus);
        const idx = COLLECTION_STAGES.findIndex(s => s.value === current);
        if (idx < 2) newStatus = COLLECTION_STAGES[idx + 1]?.value || current;
        await supabase.from("collections").update({
          status: newStatus,
          last_notice_date: new Date().toISOString(),
          notes: actionNotes ? `${selectedAccount.collection.notes || ""}\n${new Date().toLocaleDateString()}: ${actionNotes}`.trim() : selectedAccount.collection.notes,
        }).eq("id", selectedAccount.collection.id);
        toast({ title: "Notice Sent", description: `Stage updated to ${getStageConfig(newStatus).label}.` });
      } else if (action === "escalate_attorney") {
        await supabase.from("collections").update({ status: "attorney", notes: actionNotes ? `${selectedAccount.collection.notes || ""}\n${new Date().toLocaleDateString()}: Escalated - ${actionNotes}`.trim() : selectedAccount.collection.notes }).eq("id", selectedAccount.collection.id);
        toast({ title: "Escalated", description: "Case escalated to attorney." });
      } else if (action === "record_payment") {
        toast({ title: "Record Payment", description: "Use the owner's ledger to record payments directly." });
      } else if (action === "update_status") {
        await supabase.from("collections").update({
          status: normalizeCollectionSaveStatus(actionStatus || selectedAccount.collection.status),
          notes: actionNotes ? `${selectedAccount.collection.notes || ""}\n${new Date().toLocaleDateString()}: ${actionNotes}`.trim() : selectedAccount.collection.notes,
        }).eq("id", selectedAccount.collection.id);
        toast({ title: "Updated", description: "Collection status updated." });
      }

      setActionDialog(null);
      setActionNotes("");
      setActionStatus("");
      fetchAccounts();
      setDetailOpen(false);
    } catch (err: any) {
      toast({ variant: "destructive", title: "Error", description: err.message });
    }
  };

  // ─── Manual Last Notice Date Update ─────────────────────────────
  const handleUpdateNoticeDate = async (date: Date | undefined) => {
    if (!selectedAccount?.collection || !date) return;
    setNoticeDateSaving(true);
    try {
      const { error } = await supabase.from("collections").update({
        last_notice_date: date.toISOString(),
      }).eq("id", selectedAccount.collection.id);
      if (error) throw error;
      toast({ title: "Updated", description: "Last notice date updated." });
      setEditingNoticeDate(false);
      fetchAccounts();
      // Update local state immediately
      setSelectedAccount(prev => prev ? {
        ...prev,
        collection: prev.collection ? { ...prev.collection, last_notice_date: date.toISOString() } : prev.collection,
      } : null);
    } catch (err: any) {
      toast({ variant: "destructive", title: "Error", description: err.message });
    } finally {
      setNoticeDateSaving(false);
    }
  };

  // ─── Calculate & Post Late Fee / Interest ───────────────────────
  const handleCalculateFee = async (type: "late_fee" | "interest") => {
    if (!selectedAccount) return;
    if (isPaymentPlanAccount(selectedAccount)) {
      toast({ title: "Payment Plan Active", description: "Interest and late fees are not added while this unit is tagged as Payment Plan." });
      return;
    }
    setCalculatingFee(type);
    try {
      // Fetch association fee rules
      const { data: rules } = await supabase
        .from("association_fee_rules")
        .select("*")
        .eq("association_id", selectedAccount.association_id)
        .maybeSingle();

      if (!rules) {
        toast({ variant: "destructive", title: "No Fee Rules", description: "No fee rules configured for this association. Set them up in Recurring Rules." });
        return;
      }

      let amount = 0;
      let description = "";
      const breakdown = selectedAccount.ledgerBreakdown;

      if (type === "late_fee") {
        if (!rules.late_fee_enabled) {
          toast({ title: "Late Fees Disabled", description: "Late fees are not enabled for this association." });
          return;
        }
        if (rules.late_fee_type === "percentage") {
          const assessmentBalance = breakdown?.assessments || 0;
          amount = Math.round((assessmentBalance * (rules.late_fee_amount / 100)) * 100) / 100;
        } else {
          const { start, end } = currentMonthRange();
          const { data: currentMonthPayments, error: paymentError } = await supabase
            .from("owner_ledger_entries")
            .select("id")
            .in("owner_id", selectedAccount.owners.map((owner) => owner.id))
            .in("transaction_type", PAYMENT_TYPES)
            .gte("date", start)
            .lte("date", end)
            .gt("credit", 0)
            .limit(1);

          if (paymentError) throw paymentError;
          if (currentMonthPayments?.length) {
            toast({ title: "Late Fee Not Applied", description: "A payment has already been received during the current month." });
            return;
          }
          amount = rules.late_fee_amount;
        }
        if (rules.late_fee_max && amount > rules.late_fee_max) {
          amount = rules.late_fee_max;
        }
        if (amount <= 0) {
          toast({ title: "No Late Fee", description: "Calculated late fee is $0.00." });
          return;
        }
        description = `Late fee - ${rules.late_fee_type === "percentage" ? `${rules.late_fee_amount}%` : "flat"} ($${amount.toFixed(2)})`;
      } else {
        if (!rules.interest_enabled) {
          toast({ title: "Interest Disabled", description: "Interest is not enabled for this association." });
          return;
        }
        const assessmentBalance = breakdown?.assessments || 0;
        if (assessmentBalance <= 0) {
          toast({ title: "No Interest", description: "No outstanding assessment balance to apply interest to." });
          return;
        }
        // Monthly interest from annual rate
        const monthlyRate = rules.interest_rate / 100 / 12;
        amount = Math.round(assessmentBalance * monthlyRate * 100) / 100;
        if (amount <= 0) {
          toast({ title: "No Interest", description: "Calculated interest is $0.00." });
          return;
        }
        description = `Interest charge - ${rules.interest_rate}% annual on $${assessmentBalance.toFixed(2)}`;
      }

      // Post to owner_ledger_entries for each owner
      for (const owner of selectedAccount.owners) {
        const perOwnerAmount = selectedAccount.owners.length > 1 
          ? Math.round((amount / selectedAccount.owners.length) * 100) / 100 
          : amount;

        const { error } = await supabase.from("owner_ledger_entries").insert({
          owner_id: owner.id,
          unit_id: selectedAccount.unit_id,
          association_id: selectedAccount.association_id,
          transaction_type: type,
          description,
          debit: perOwnerAmount,
          credit: 0,
          date: new Date().toISOString().split("T")[0],
          created_by: user?.id || null,
        });
        if (error) throw error;
      }

      toast({ title: type === "late_fee" ? "Late Fee Applied" : "Interest Applied", description: `${fmt(amount)} posted to ledger.` });
      fetchAccounts();
    } catch (err: any) {
      toast({ variant: "destructive", title: "Error", description: err.message });
    } finally {
      setCalculatingFee(null);
    }
  };

  const handleTrackInLegal = async (account: OwnerAccount, e?: React.MouseEvent) => {
    if (e) e.stopPropagation();
    if (!account.collection) return;
    setTrackingLegalId(account.id);
    try {
      // Check if a legal matter already exists for this collection
      const { data: existing } = await supabase
        .from("legal_matters")
        .select("id")
        .eq("collection_id", account.collection.id)
        .maybeSingle();

      if (existing) {
        toast({ title: "Already Tracked", description: "This collection is already linked to a legal matter." });
        setTrackingLegalId(null);
        return;
      }

      const ownerNames = account.owners.map(o => `${o.first_name} ${o.last_name}`).join(" & ");
      const title = `Collections – ${ownerNames}${account.unit ? ` (Unit ${account.unit.unit_number})` : ""}`;

      const { error } = await supabase.from("legal_matters").insert({
        title,
        association_id: account.association_id,
        collection_id: account.collection.id,
        unit_id: account.unit_id || null,
        amount_due: account.balance,
        status: "open",
        current_stage: "sent_to_attorney",
        case_type: "collection",
        category: "collections",
        description: `Auto-created from Collections. Balance: ${fmt(account.balance)}. Stage: ${getStageConfig(account.collection.status).label}.`,
        created_by: user?.id || null,
        opened_date: new Date().toISOString().split("T")[0],
      });

      if (error) throw error;
      toast({ title: "Legal Matter Created", description: "This collection is now tracked in Legal Matters." });
    } catch (err: any) {
      toast({ variant: "destructive", title: "Error", description: err.message });
    } finally {
      setTrackingLegalId(null);
    }
  };

  // ─── Render ──────────────────────────────────────────────────────
  return (
    <div className="space-y-6">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-bold text-foreground flex items-center gap-2">
            <DollarSign className="h-6 w-6 text-primary" /> Collections
          </h1>
          <p className="text-sm text-muted-foreground mt-1">
            Track delinquent homeowners and manage collection actions.
          </p>
        </div>
        <div className="flex gap-2">
          <RecordImportButton
            title="Import Collections"
            description="Upload a CSV or Excel file with collection case records."
            expectedColumns={[
              { key: "owner_name", label: "Owner Name", required: true },
              { key: "association_name", label: "Association Name", required: true },
              { key: "unit_number", label: "Unit Number" },
              { key: "amount_owed", label: "Amount Owed", required: true },
              { key: "status", label: "Status" },
              { key: "last_notice_date", label: "Last Notice Date" },
              { key: "notes", label: "Notes" },
            ]}
            onImport={async (rows) => {
              const [assocRes, ownersRes, unitsRes] = await Promise.all([
                supabase.from("associations").select("id, name").eq("status", "active"),

                supabase.from("owners").select("id, first_name, last_name, association_id").eq("status", "active"),
                supabase.from("units").select("id, unit_number, association_id"),
              ]);
              const assocMap = new Map((assocRes.data || []).map((a: any) => [a.name.toLowerCase(), a.id]));
              const ownerList = ownersRes.data || [];
              const unitList = unitsRes.data || [];

              const toInsert = rows.map((row) => {
                const assocId = assocMap.get((row.association_name || "").toLowerCase()) || "";
                const ownerName = (row.owner_name || "").toLowerCase();
                const owner = ownerList.find((o: any) =>
                  `${o.first_name} ${o.last_name}`.toLowerCase() === ownerName && o.association_id === assocId
                );
                const unit = row.unit_number
                  ? unitList.find((u: any) => u.unit_number === row.unit_number && u.association_id === assocId)
                  : null;
                return {
                  association_id: assocId,
                  owner_id: owner?.id || null,
                  unit_id: unit?.id || null,
                  amount_owed: parseFloat(row.amount_owed) || 0,
                  status: normalizeCollectionSaveStatus(row.status || "late_notice"),
                  last_notice_date: row.last_notice_date || null,
                  notes: row.notes || null,
                };
              }).filter((r) => r.association_id);

              if (!toInsert.length) throw new Error("No valid rows to import.");
              const { error } = await supabase.from("collections").insert(toInsert);
              if (error) throw error;
              fetchAccounts();
            }}
            templateFileName="collections_import_template.csv"
          />
          {selectedIds.size > 0 && (
            <DropdownMenu>
              <DropdownMenuTrigger asChild>
                <Button variant="outline" className="gap-2" disabled={bulkStageUpdating}>
                  <FileText className="h-4 w-4" />
                  {bulkStageUpdating ? "Updating…" : `Update Stage (${selectedIds.size})`}
                </Button>
              </DropdownMenuTrigger>
              <DropdownMenuContent>
                {COLLECTION_STAGES.map(s => (
                  <DropdownMenuItem key={s.value} onClick={async () => {
                    setBulkStageUpdating(true);
                    try {
                      const ids = Array.from(selectedIds);
                      const selectedAccounts = accounts.filter(a => ids.includes(a.id) && a.collection);
                      for (const acct of selectedAccounts) {
                        await supabase.from("collections").update({ status: normalizeCollectionSaveStatus(s.value) }).eq("id", acct.collection!.id);
                      }
                      toast({ title: "Bulk Update", description: `Updated ${selectedAccounts.length} accounts to "${s.label}".` });
                      setSelectedIds(new Set());
                      fetchAccounts();
                    } catch (err: any) {
                      toast({ variant: "destructive", title: "Error", description: err.message });
                    } finally {
                      setBulkStageUpdating(false);
                    }
                  }}>
                    <span className={`inline-block w-2 h-2 rounded-full mr-2 ${s.dotColor}`} />
                    {s.label}
                  </DropdownMenuItem>
                ))}
              </DropdownMenuContent>
            </DropdownMenu>
          )}
          <Button variant="outline" size="sm" onClick={() => {
            import("@/lib/collectionsPdfExport").then(({ exportCollectionsPdf }) => {
              const assocMap = new Map(associations.map((a: any) => [a.id, a.name]));
              exportCollectionsPdf(filtered.map((a) => ({
                ownerName: getAccountOwnerNames(a).join(" & "),
                unitNumber: a.unit?.unit_number || "",
                association: assocMap.get(a.association_id) || "—",
                balance: a.balance,
                stage: getStageConfig(a.collection!.status).label,
                daysDelinquent: a.daysDelinquent || 0,
                lastNoticeDate: a.collection!.last_notice_date,
                assessments: a.ledgerBreakdown?.assessments || 0,
                lateFees: a.ledgerBreakdown?.lateFees || 0,
                interest: a.ledgerBreakdown?.interest || 0,
                legalFees: a.ledgerBreakdown?.legalFees || 0,
                adminFees: a.ledgerBreakdown?.adminFees || 0,
                violations: a.ledgerBreakdown?.violations || 0,
                bankFees: a.ledgerBreakdown?.bankFees || 0,
                payments: a.ledgerBreakdown?.payments || 0,
              })));
            });
          }}>
            <FileDown className="h-4 w-4 mr-2" /> Export PDF
          </Button>
          <Button onClick={() => setAddDialogOpen(true)} className="gap-2">
            <Plus className="h-4 w-4" /> Add Collection
          </Button>
          <Button variant="outline" size="sm" onClick={fetchAccounts} disabled={loading}>
            <RefreshCw className={`h-4 w-4 mr-2 ${loading ? "animate-spin" : ""}`} /> Refresh
          </Button>
        </div>
      </div>

      {/* ── Metric Cards ─────────────────────────────────────────── */}
      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
        <Card>
          <CardContent className="p-5">
            <div className="flex items-center justify-between">
              <div>
                <p className="text-xs font-medium text-muted-foreground uppercase tracking-wide">Total Delinquency</p>
                <p className="text-2xl font-bold text-destructive mt-1">{fmt(metrics.totalDelinquency)}</p>
              </div>
              <div className="h-10 w-10 rounded-full bg-destructive/10 flex items-center justify-center">
                <TrendingUp className="h-5 w-5 text-destructive" />
              </div>
            </div>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="p-5">
            <div className="flex items-center justify-between">
              <div>
                <p className="text-xs font-medium text-muted-foreground uppercase tracking-wide">Delinquent Units</p>
                <p className="text-2xl font-bold text-foreground mt-1">{metrics.delinquentUnits}</p>
              </div>
              <div className="h-10 w-10 rounded-full bg-primary/10 flex items-center justify-center">
                <Users className="h-5 w-5 text-primary" />
              </div>
            </div>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="p-5">
            <div className="flex items-center justify-between">
              <div>
                <p className="text-xs font-medium text-muted-foreground uppercase tracking-wide">Average Balance</p>
                <p className="text-2xl font-bold text-foreground mt-1">{fmt(metrics.avgBalance)}</p>
              </div>
              <div className="h-10 w-10 rounded-full bg-amber-500/10 flex items-center justify-center">
                <Banknote className="h-5 w-5 text-amber-600" />
              </div>
            </div>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="p-5">
            <div className="flex items-center justify-between">
              <div>
                <p className="text-xs font-medium text-muted-foreground uppercase tracking-wide">Payment Plans</p>
                <p className="text-2xl font-bold text-foreground mt-1">{metrics.activePlans}</p>
              </div>
              <div className="h-10 w-10 rounded-full bg-blue-500/10 flex items-center justify-center">
                <CalendarClock className="h-5 w-5 text-blue-600" />
              </div>
            </div>
          </CardContent>
        </Card>
      </div>

      {/* ── Stage Pipeline ───────────────────────────────────────── */}
      <div className="grid grid-cols-6 gap-2">
        {COLLECTION_STAGES.filter(s => s.value !== "resolved").map(stage => {
          const count = stageCounts[stage.value] || 0;
          const Icon = stage.icon;
          return (
            <button
              key={stage.value}
              onClick={() => setStageTab(stageTab === stage.value ? "all" : stage.value)}
              className={`p-3 rounded-lg border text-left transition-all ${
                stageTab === stage.value
                  ? "ring-2 ring-primary border-primary bg-primary/5"
                  : "hover:bg-muted/50"
              }`}
            >
              <div className="flex items-center gap-2 mb-1">
                <div className={`h-2 w-2 rounded-full ${stage.dotColor}`} />
                <span className="text-xs font-medium text-muted-foreground truncate">{stage.label}</span>
              </div>
              <p className="text-xl font-bold text-foreground">{count}</p>
            </button>
          );
        })}
      </div>

      {/* ── Filters ──────────────────────────────────────────────── */}
      <div className="flex flex-col sm:flex-row gap-3 flex-wrap">
        <Select value={filterAssociation} onValueChange={setFilterAssociation}>
          <SelectTrigger className="w-[220px]">
            <SelectValue placeholder="All Associations" />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="all">All Associations</SelectItem>
            {associations.map((a) => (
              <SelectItem key={a.id} value={a.id}>{a.name}</SelectItem>
            ))}
          </SelectContent>
        </Select>
        <div className="relative flex-1 max-w-md">
          <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
          <Input placeholder="Search owner, unit, address..." className="pl-10" value={search} onChange={e => setSearch(e.target.value)} />
        </div>
        <Popover>
          <PopoverTrigger asChild>
            <Button variant="outline" className={cn("w-[150px] justify-start text-left font-normal", !filterDateFrom && "text-muted-foreground")}>
              <CalendarIcon className="mr-2 h-4 w-4" />
              {filterDateFrom ? format(filterDateFrom, "MM/dd/yy") : "From date"}
            </Button>
          </PopoverTrigger>
          <PopoverContent className="w-auto p-0" align="start">
            <Calendar mode="single" selected={filterDateFrom} onSelect={setFilterDateFrom} initialFocus className="p-3 pointer-events-auto" />
          </PopoverContent>
        </Popover>
        <Popover>
          <PopoverTrigger asChild>
            <Button variant="outline" className={cn("w-[150px] justify-start text-left font-normal", !filterDateTo && "text-muted-foreground")}>
              <CalendarIcon className="mr-2 h-4 w-4" />
              {filterDateTo ? format(filterDateTo, "MM/dd/yy") : "To date"}
            </Button>
          </PopoverTrigger>
          <PopoverContent className="w-auto p-0" align="start">
            <Calendar mode="single" selected={filterDateTo} onSelect={setFilterDateTo} initialFocus className="p-3 pointer-events-auto" />
          </PopoverContent>
        </Popover>
        <Select value={filterDays} onValueChange={setFilterDays}>
          <SelectTrigger className="w-[160px]">
            <SelectValue placeholder="Days Overdue" />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="all">All Days</SelectItem>
            <SelectItem value="30">30+ Days</SelectItem>
            <SelectItem value="60">60+ Days</SelectItem>
            <SelectItem value="90">90+ Days</SelectItem>
            <SelectItem value="180">180+ Days</SelectItem>
          </SelectContent>
        </Select>
        <Select value={filterBalance} onValueChange={setFilterBalance}>
          <SelectTrigger className="w-[160px]">
            <SelectValue placeholder="Balance Range" />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="all">All Balances</SelectItem>
            <SelectItem value="over1000">Over $1,000</SelectItem>
            <SelectItem value="over5000">Over $5,000</SelectItem>
            <SelectItem value="over10000">Over $10,000</SelectItem>
          </SelectContent>
        </Select>
        {(stageTab !== "all" || filterDays !== "all" || filterBalance !== "all" || search || filterAssociation !== "all" || filterDateFrom || filterDateTo) && (
          <Button variant="ghost" size="sm" onClick={() => { setStageTab("all"); setFilterDays("all"); setFilterBalance("all"); setSearch(""); setFilterAssociation("all"); setFilterDateFrom(undefined); setFilterDateTo(undefined); }}>
            <X className="h-4 w-4 mr-1" /> Clear
          </Button>
        )}
      </div>

      {/* ── Delinquency Table ────────────────────────────────────── */}
      {loading ? (
        <div className="flex justify-center py-16">
          <div className="h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent" />
        </div>
      ) : filtered.length === 0 ? (
        <Card>
          <CardContent className="py-16 text-center">
            <AlertTriangle className="h-10 w-10 text-muted-foreground mx-auto mb-3" />
            <p className="text-muted-foreground font-medium">No delinquent accounts match the current filters.</p>
          </CardContent>
        </Card>
      ) : (
        <Card className="overflow-hidden">
          <Table>
            <TableHeader>
              <TableRow className="bg-muted/30">
                <TableHead className="w-10">
                  <Checkbox
                    checked={selectedIds.size === filtered.length && filtered.length > 0}
                    onCheckedChange={(checked) => {
                      if (checked) setSelectedIds(new Set(filtered.map(a => a.id)));
                      else setSelectedIds(new Set());
                    }}
                  />
                </TableHead>
                <TableHead className="cursor-pointer select-none" onClick={() => toggleSort("name")}>
                  <span className="flex items-center gap-1">Owner <ArrowUpDown className="h-3 w-3" /></span>
                </TableHead>
                <TableHead>Property</TableHead>
                <TableHead className="cursor-pointer select-none text-right" onClick={() => toggleSort("balance")}>
                  <span className="flex items-center justify-end gap-1">Balance <ArrowUpDown className="h-3 w-3" /></span>
                </TableHead>
                <TableHead className="cursor-pointer select-none text-right" onClick={() => toggleSort("days")}>
                  <span className="flex items-center justify-end gap-1">Days <ArrowUpDown className="h-3 w-3" /></span>
                </TableHead>
                <TableHead className="text-right">Late Fees</TableHead>
                <TableHead className="text-right">Interest</TableHead>
                <TableHead className="cursor-pointer select-none" onClick={() => toggleSort("lastNotice")}>
                  <span className="flex items-center gap-1">Last Notice <ArrowUpDown className="h-3 w-3" /></span>
                </TableHead>
                <TableHead className="cursor-pointer select-none" onClick={() => toggleSort("status")}>
                  <span className="flex items-center gap-1">Stage <ArrowUpDown className="h-3 w-3" /></span>
                </TableHead>
                <TableHead>Next Action</TableHead>
                <TableHead className="w-10" />
              </TableRow>
            </TableHeader>
            <TableBody>
              {filtered.map(a => {
                const stage = getStageConfig(a.collection!.status);
                const nextAction = getNextAction(normalizeStage(a.collection!.status));
                return (
                  <TableRow
                    key={a.id}
                    className={`cursor-pointer hover:bg-muted/40 transition-colors ${selectedIds.has(a.id) ? "bg-primary/5" : ""}`}
                    onClick={() => openDetail(a)}
                  >
                    <TableCell onClick={(e) => e.stopPropagation()}>
                      <Checkbox
                        checked={selectedIds.has(a.id)}
                        onCheckedChange={(checked) => {
                          setSelectedIds(prev => {
                            const next = new Set(prev);
                            if (checked) next.add(a.id);
                            else next.delete(a.id);
                            return next;
                          });
                        }}
                      />
                    </TableCell>
                    <TableCell>
                      <div>
                        {a.owners.length > 1 ? (
                          <>
                            <p className="font-medium text-foreground">{a.owners.map(o => `${o.first_name} ${o.last_name}`).join(" & ")}</p>
                            <p className="text-xs text-muted-foreground">{a.owners.length} co-owners</p>
                          </>
                        ) : (
                          <>
                            <p className="font-medium text-foreground">{a.first_name} {a.last_name}</p>
                            {a.email && <p className="text-xs text-muted-foreground">{a.email}</p>}
                          </>
                        )}
                      </div>
                    </TableCell>
                    <TableCell>
                      {a.unit ? (
                        <div>
                          <p className="font-medium">{a.unit.unit_number}</p>
                          {a.unit.address && <p className="text-xs text-muted-foreground truncate max-w-[180px]">{a.unit.address}</p>}
                        </div>
                      ) : <span className="text-muted-foreground">—</span>}
                    </TableCell>
                    <TableCell className="text-right">
                      <span className="font-semibold text-destructive">{fmt(a.balance)}</span>
                    </TableCell>
                    <TableCell className="text-right">
                      <span className={`font-medium ${(a.daysDelinquent || 0) >= 90 ? "text-destructive" : (a.daysDelinquent || 0) >= 60 ? "text-amber-600" : "text-foreground"}`}>
                        {a.daysDelinquent || 0}
                      </span>
                    </TableCell>
                    <TableCell className="text-right text-sm">{fmt(a.ledgerBreakdown?.lateFees || 0)}</TableCell>
                    <TableCell className="text-right text-sm">{fmt(a.ledgerBreakdown?.interest || 0)}</TableCell>
                    <TableCell>
                      <span className="text-sm text-muted-foreground">
                        {a.collection?.last_notice_date ? format(new Date(a.collection.last_notice_date), "MMM d, yyyy") : "—"}
                      </span>
                    </TableCell>
                    <TableCell>
                      <Badge className={`${stage.color} border-0 text-xs font-medium`}>{stage.label}</Badge>
                    </TableCell>
                    <TableCell>
                      <span className="text-xs text-muted-foreground">{nextAction}</span>
                    </TableCell>
                    <TableCell onClick={(e) => e.stopPropagation()}>
                      <Button
                        variant="outline"
                        size="sm"
                        className="text-xs gap-1 whitespace-nowrap"
                        disabled={trackingLegalId === a.id}
                        onClick={(e) => handleTrackInLegal(a, e)}
                      >
                        <Briefcase className="h-3 w-3" />
                        {trackingLegalId === a.id ? "Creating…" : "Track in Legal"}
                      </Button>
                    </TableCell>
                    <TableCell>
                      <ChevronRight className="h-4 w-4 text-muted-foreground" />
                    </TableCell>
                  </TableRow>
                );
              })}
            </TableBody>
          </Table>
        </Card>
      )}

      {/* ── Detail Panel (Sheet) ─────────────────────────────────── */}
      <Sheet open={detailOpen} onOpenChange={setDetailOpen}>
        <SheetContent className="w-full sm:max-w-lg overflow-y-auto">
          {selectedAccount && (
            <div className="space-y-6">
               <SheetHeader>
                <SheetTitle className="text-xl">
                  {selectedAccount.unit ? `Unit ${selectedAccount.unit.unit_number}` : `${selectedAccount.first_name} ${selectedAccount.last_name}`}
                </SheetTitle>
                <div className="flex items-center gap-2 mt-1 flex-wrap">
                  {selectedAccount.owners.map(o => (
                    <Badge key={o.id} variant="secondary" className="text-xs">
                      {o.first_name} {o.last_name}
                    </Badge>
                  ))}
                  {selectedAccount.collection && (
                    <Badge className={`${getStageConfig(selectedAccount.collection.status).color} border-0 text-xs`}>
                      {getStageConfig(selectedAccount.collection.status).label}
                    </Badge>
                  )}
                </div>
                {selectedAccount.unit?.address && (
                  <p className="text-sm text-muted-foreground">{selectedAccount.unit.address}</p>
                )}
              </SheetHeader>

              {/* Total Balance */}
              <Card className="border-destructive/20 bg-destructive/5">
                <CardContent className="p-4">
                  <p className="text-xs font-medium text-muted-foreground uppercase">Total Balance Due</p>
                  <p className="text-3xl font-bold text-destructive">{fmt(selectedAccount.balance)}</p>
                  {selectedAccount.daysDelinquent ? (
                    <p className="text-xs text-muted-foreground mt-1">{selectedAccount.daysDelinquent} days delinquent</p>
                  ) : null}
                </CardContent>
              </Card>

              {/* Balance Breakdown */}
              <div>
                <h3 className="text-sm font-semibold text-foreground mb-3">Balance Breakdown</h3>
                <div className="space-y-2">
                  {[
                    { label: "Assessments", value: selectedAccount.ledgerBreakdown?.assessments || 0, color: "bg-primary" },
                    { label: "Late Fees", value: selectedAccount.ledgerBreakdown?.lateFees || 0, color: "bg-amber-500" },
                    { label: "Interest", value: selectedAccount.ledgerBreakdown?.interest || 0, color: "bg-orange-500" },
                    { label: "Legal Fees", value: selectedAccount.ledgerBreakdown?.legalFees || 0, color: "bg-purple-500" },
                    { label: "Admin Fees", value: selectedAccount.ledgerBreakdown?.adminFees || 0, color: "bg-blue-500" },
                    { label: "Violations", value: selectedAccount.ledgerBreakdown?.violations || 0, color: "bg-red-500" },
                    { label: "Bank Fees", value: selectedAccount.ledgerBreakdown?.bankFees || 0, color: "bg-slate-500" },
                  ].filter(r => r.value > 0).map(row => (
                    <div key={row.label} className="flex items-center justify-between py-1.5 px-3 bg-muted/30 rounded">
                      <div className="flex items-center gap-2">
                        <div className={`h-2 w-2 rounded-full ${row.color}`} />
                        <span className="text-sm text-foreground">{row.label}</span>
                      </div>
                      <span className="text-sm font-medium text-foreground">{fmt(row.value)}</span>
                    </div>
                  ))}
                  {(selectedAccount.ledgerBreakdown?.payments || 0) > 0 && (
                    <div className="flex items-center justify-between py-1.5 px-3 bg-emerald-50 dark:bg-emerald-900/10 rounded">
                      <div className="flex items-center gap-2">
                        <div className="h-2 w-2 rounded-full bg-emerald-500" />
                        <span className="text-sm text-foreground">Payments (AR)</span>
                      </div>
                      <span className="text-sm font-medium text-emerald-700 dark:text-emerald-400">-{fmt(selectedAccount.ledgerBreakdown?.payments || 0)}</span>
                    </div>
                  )}
                </div>
              </div>

              {/* Last Notice Date */}
              <div>
                <h3 className="text-sm font-semibold text-foreground mb-2">Last Notice Date</h3>
                <div className="flex items-center gap-2">
                  {editingNoticeDate ? (
                    <Popover open onOpenChange={(open) => { if (!open) setEditingNoticeDate(false); }}>
                      <PopoverTrigger asChild>
                        <Button variant="outline" className={cn("flex-1 justify-start text-left font-normal", !selectedAccount.collection?.last_notice_date && "text-muted-foreground")}>
                          <CalendarIcon className="mr-2 h-4 w-4" />
                          {selectedAccount.collection?.last_notice_date
                            ? format(new Date(selectedAccount.collection.last_notice_date), "MMM d, yyyy")
                            : "Select date"}
                        </Button>
                      </PopoverTrigger>
                      <PopoverContent className="w-auto p-0 z-[9999]" align="start" side="bottom" sideOffset={4}>
                        <Calendar
                          mode="single"
                          selected={selectedAccount.collection?.last_notice_date ? new Date(selectedAccount.collection.last_notice_date) : undefined}
                          onSelect={(date) => handleUpdateNoticeDate(date)}
                          initialFocus
                          className="p-3 pointer-events-auto"
                        />
                      </PopoverContent>
                    </Popover>
                  ) : (
                    <>
                      <div className="flex-1 p-2 bg-muted/30 rounded text-sm">
                        {selectedAccount.collection?.last_notice_date
                          ? format(new Date(selectedAccount.collection.last_notice_date), "MMM d, yyyy")
                          : <span className="text-muted-foreground">Not set</span>}
                      </div>
                      <Button variant="outline" size="sm" onClick={() => setEditingNoticeDate(true)} disabled={noticeDateSaving}>
                        <CalendarIcon className="h-4 w-4 mr-1" /> Edit
                      </Button>
                    </>
                  )}
                </div>
              </div>

              {/* Apply Late Fee / Interest */}
              <div>
                <h3 className="text-sm font-semibold text-foreground mb-2">Calculate & Post Fees</h3>
                <div className="grid grid-cols-2 gap-2">
                  <Button
                    variant="outline"
                    size="sm"
                    className="justify-start"
                    disabled={calculatingFee === "late_fee" || isPaymentPlanAccount(selectedAccount)}
                    onClick={() => handleCalculateFee("late_fee")}
                  >
                    {calculatingFee === "late_fee" ? <RefreshCw className="h-4 w-4 mr-2 animate-spin" /> : <DollarSign className="h-4 w-4 mr-2" />}
                    Apply Late Fee
                  </Button>
                  <Button
                    variant="outline"
                    size="sm"
                    className="justify-start"
                    disabled={calculatingFee === "interest" || isPaymentPlanAccount(selectedAccount)}
                    onClick={() => handleCalculateFee("interest")}
                  >
                    {calculatingFee === "interest" ? <RefreshCw className="h-4 w-4 mr-2 animate-spin" /> : <TrendingUp className="h-4 w-4 mr-2" />}
                    Apply Interest
                  </Button>
                </div>
                {isPaymentPlanAccount(selectedAccount) && (
                  <p className="mt-2 text-xs text-muted-foreground">
                    Fees are paused while this unit is tagged as Payment Plan.
                  </p>
                )}
              </div>

              <Separator />

              {/* Payment Plan Info */}
              {selectedAccount.paymentPlan && (
                <>
                  <div>
                    <h3 className="text-sm font-semibold text-foreground mb-2">Active Payment Plan</h3>
                    <Card>
                      <CardContent className="p-4 space-y-2">
                        <div className="flex justify-between text-sm">
                          <span className="text-muted-foreground">Monthly Payment</span>
                          <span className="font-medium">{fmt(selectedAccount.paymentPlan.monthly_payment)}</span>
                        </div>
                        <div className="flex justify-between text-sm">
                          <span className="text-muted-foreground">Total Amount</span>
                          <span className="font-medium">{fmt(selectedAccount.paymentPlan.total_amount)}</span>
                        </div>
                        {selectedAccount.paymentPlan.start_date && (
                          <div className="flex justify-between text-sm">
                            <span className="text-muted-foreground">Start Date</span>
                            <span>{new Date(selectedAccount.paymentPlan.start_date).toLocaleDateString()}</span>
                          </div>
                        )}
                      </CardContent>
                    </Card>
                  </div>
                  <Separator />
                </>
              )}

              {/* Collection Notes */}
              {selectedAccount.collection?.notes && (
                <>
                  <div>
                    <h3 className="text-sm font-semibold text-foreground mb-2">Notes</h3>
                    <div className="p-3 bg-muted/30 rounded text-sm text-muted-foreground whitespace-pre-wrap">
                      {selectedAccount.collection.notes}
                    </div>
                  </div>
                  <Separator />
                </>
              )}

              {/* Actions */}
              <div>
                <h3 className="text-sm font-semibold text-foreground mb-3">Actions</h3>
                <div className="grid grid-cols-2 gap-2">
                  <Button variant="outline" className="justify-start" onClick={() => { setActionDialog("send_notice"); setActionNotes(""); }}>
                    <Send className="h-4 w-4 mr-2" /> Send Notice
                  </Button>
                  <Button variant="outline" className="justify-start" onClick={() => { setActionDialog("payment_plan"); setActionNotes(""); }}>
                    <CreditCard className="h-4 w-4 mr-2" /> Add Plan
                  </Button>
                  <Button variant="outline" className="justify-start text-purple-700 dark:text-purple-400 hover:bg-purple-50 dark:hover:bg-purple-900/20" onClick={() => { setActionDialog("escalate_attorney"); setActionNotes(""); }}>
                    <Gavel className="h-4 w-4 mr-2" /> Escalate
                  </Button>
                  <Button variant="outline" className="justify-start" onClick={() => { setActionDialog("record_payment"); }}>
                    <Banknote className="h-4 w-4 mr-2" /> Record Payment
                  </Button>
                </div>
                <div className="mt-3 space-y-2">
                  <Button
                    variant="outline"
                    size="sm"
                    className="w-full justify-start"
                    disabled={trackingLegalId === selectedAccount.id}
                    onClick={() => handleTrackInLegal(selectedAccount)}
                  >
                    <Briefcase className="h-4 w-4 mr-2" />
                    {trackingLegalId === selectedAccount.id ? "Creating…" : "Track in Legal Matters"}
                  </Button>
                  <Button variant="outline" size="sm" className="w-full" onClick={() => { setActionDialog("update_status"); setActionStatus(selectedAccount.collection?.status || ""); setActionNotes(""); }}>
                    <MoreHorizontal className="h-4 w-4 mr-2" /> Update Stage
                  </Button>
                  <Button variant="outline" size="sm" className="w-full text-destructive hover:bg-destructive/10" onClick={() => setActionDialog("delete_collection")}>
                    <Trash2 className="h-4 w-4 mr-2" /> Delete Collection
                  </Button>
                </div>
              </div>
            </div>
          )}
        </SheetContent>
      </Sheet>

      {/* ── Action Dialogs ───────────────────────────────────────── */}
      <Dialog open={actionDialog === "send_notice"} onOpenChange={() => setActionDialog(null)}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Send Notice</DialogTitle>
            <DialogDescription>Advance to the next collection stage and record the notice.</DialogDescription>
          </DialogHeader>
          <div className="space-y-3">
            <Label>Notes (optional)</Label>
            <Textarea value={actionNotes} onChange={e => setActionNotes(e.target.value)} placeholder="Notice details..." rows={3} />
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setActionDialog(null)}>Cancel</Button>
            <Button onClick={() => handleAction("send_notice")}>
              <Send className="h-4 w-4 mr-2" /> Send & Advance
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={actionDialog === "escalate_attorney"} onOpenChange={() => setActionDialog(null)}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Escalate to Attorney</DialogTitle>
            <DialogDescription>This will move the case to attorney stage.</DialogDescription>
          </DialogHeader>
          <div className="space-y-3">
            <Label>Escalation Notes</Label>
            <Textarea value={actionNotes} onChange={e => setActionNotes(e.target.value)} placeholder="Reason for escalation..." rows={3} />
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setActionDialog(null)}>Cancel</Button>
            <Button variant="destructive" onClick={() => handleAction("escalate_attorney")}>
              <Gavel className="h-4 w-4 mr-2" /> Escalate
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={actionDialog === "record_payment"} onOpenChange={() => setActionDialog(null)}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Record Payment</DialogTitle>
            <DialogDescription>Payments should be recorded directly in the owner's unit ledger for proper accounting.</DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button onClick={() => { handleAction("record_payment"); setActionDialog(null); }}>Got It</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={actionDialog === "payment_plan"} onOpenChange={() => setActionDialog(null)}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Add Payment Plan</DialogTitle>
            <DialogDescription>Navigate to Payment Plans to set up a plan for this owner.</DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setActionDialog(null)}>Close</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={actionDialog === "update_status"} onOpenChange={() => setActionDialog(null)}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Update Collection Stage</DialogTitle>
          </DialogHeader>
          <div className="space-y-4">
            <div>
              <Label>Stage</Label>
              <Select value={actionStatus} onValueChange={setActionStatus}>
                <SelectTrigger><SelectValue /></SelectTrigger>
                <SelectContent>
                  {COLLECTION_STAGES.map(s => (
                    <SelectItem key={s.value} value={s.value}>{s.label}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div>
              <Label>Notes (optional)</Label>
              <Textarea value={actionNotes} onChange={e => setActionNotes(e.target.value)} placeholder="Update notes..." rows={3} />
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setActionDialog(null)}>Cancel</Button>
            <Button onClick={() => handleAction("update_status")}>Save</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <CollectionDialog
        open={addDialogOpen}
        onOpenChange={setAddDialogOpen}
        collection={null}
        onSuccess={fetchAccounts}
      />

      <Dialog open={actionDialog === "delete_collection"} onOpenChange={() => setActionDialog(null)}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Delete Collection Account</DialogTitle>
            <DialogDescription>
              This will permanently remove this collection record and reset the unit status to active. This cannot be undone.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setActionDialog(null)}>Cancel</Button>
            <Button variant="destructive" onClick={handleDeleteCollection}>
              <Trash2 className="h-4 w-4 mr-2" /> Delete
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}

// ─── Helper ────────────────────────────────────────────────────────
function getNextAction(stage: string): string {
  switch (stage) {
    case "late_notice": return "Send NOLA";
    case "second_notice": return "File intent to lien";
    case "intent_to_lien": return "Escalate to attorney";
    case "attorney": return "Awaiting legal action";
    case "payment_plan": return "Monitor payments";
    case "resolved": return "—";
    default: return "Review";
  }
}
