import { useState, useEffect, useMemo } from "react";
import { supabase } from "@/integrations/supabase/client";
import { useToast } from "@/hooks/use-toast";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Badge } from "@/components/ui/badge";
import { Checkbox } from "@/components/ui/checkbox";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from "@/components/ui/dialog";
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Switch } from "@/components/ui/switch";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import {
  Plus, Search, Trash2, Download, Edit, DollarSign, Loader2, X,
  FolderTree, CheckSquare, RotateCcw, Receipt, Settings, FileText, Upload, RefreshCw, CalendarClock
} from "lucide-react";
import { format } from "date-fns";
import type { Tables } from "@/integrations/supabase/types";
import { generateInvoicePdf } from "@/lib/generateInvoicePdf";
import { FeeScheduleDialog } from "@/components/FeeScheduleDialog";
import ExpenseBundleDialog from "@/components/ExpenseBundleDialog";

import ExpenseSettingsPanel from "@/components/ExpenseSettingsPanel";

type Expense = {
  id: string; association_id: string; date: string; description: string | null;
  amount: number; category: string | null; billable_type: string | null;
  status: string; is_credit: boolean; credit_reason: string | null;
  quantity: number | null; unit_price: number | null; vendor_name: string | null;
  address: string | null; receipt_url: string | null; created_at: string;
  is_recurring?: boolean; recurring_day?: number | null; recurring_next_date?: string | null;
  recurring_end_date?: string | null; recurring_parent_id?: string | null;
  associations?: { name: string } | null;
};

type LineItem = {
  category: string;
  billable_type: string;
  description: string;
  quantity: string;
  unit_price: string;
  amount: string;
};

const emptyLineItem: LineItem = { category: "", billable_type: "", description: "", quantity: "1", unit_price: "0", amount: "0.00" };

const parseDecimalInput = (value: string | number | null | undefined, fallback = 0) => {
  if (value === null || value === undefined || value === "") return fallback;
  const parsed = Number(String(value).replace(/,/g, ""));
  return Number.isFinite(parsed) ? parsed : fallback;
};

const getLineItemAmount = (li: LineItem) => {
  const qty = parseDecimalInput(li.quantity, 1);
  const rate = parseDecimalInput(li.unit_price, 0);
  return qty * rate;
};

const emptyForm = {
  date: "", is_credit: false, credit_reason: "",
  vendor_name: "", addresses: [] as string[], association_id: "",
  is_recurring: false, recurring_day: 1, recurring_end_date: "",
};

function computeNextRecurringDate(day: number): string {
  const now = new Date();
  let year = now.getFullYear();
  let month = now.getMonth();
  if (now.getDate() >= day) month += 1;
  if (month > 11) { month = 0; year += 1; }
  const d = new Date(year, month, Math.min(day, 28));
  return d.toISOString().split("T")[0];
}

export default function BillableExpensesPage() {
  const { toast } = useToast();
  const [expenses, setExpenses] = useState<Expense[]>([]);
  const [associations, setAssociations] = useState<Tables<"associations">[]>([]);
  const [vendors, setVendors] = useState<any[]>([]);
  const [loading, setLoading] = useState(true);
  const [activeTab, setActiveTab] = useState("expenses");

  // Filters
  const [searchTerm, setSearchTerm] = useState("");
  const [assocFilter, setAssocFilter] = useState("all");
  const [statusFilter, setStatusFilter] = useState("pending");
  const [categoryFilter, setCategoryFilter] = useState("all");
  const [creditFilter, setCreditFilter] = useState("all");
  const [billableTypeFilter, setBillableTypeFilter] = useState("all");
  const [groupByCategory, setGroupByCategory] = useState(false);
  const [dateRange, setDateRange] = useState({ start: "", end: "" });

  // Selection
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());

  // Dialogs
  const [formOpen, setFormOpen] = useState(false);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [form, setForm] = useState(emptyForm);
  const [lineItems, setLineItems] = useState<LineItem[]>([{ ...emptyLineItem }]);
  const [receiptFile, setReceiptFile] = useState<File | null>(null);
  const [saving, setSaving] = useState(false);
  const [deleteOpen, setDeleteOpen] = useState(false);
  const [deleteTarget, setDeleteTarget] = useState<string | null>(null);

  // Bulk Edit Dialog
  const [bulkEditOpen, setBulkEditOpen] = useState(false);
  const [bulkEditFields, setBulkEditFields] = useState({ category: "", billable_type: "" });
  const [bulkEditSaving, setBulkEditSaving] = useState(false);
  
  const [importOpen, setImportOpen] = useState(false);
  const [feeDialogOpen, setFeeDialogOpen] = useState(false);
  
  const [feeItems, setFeeItems] = useState<any[]>([]);
  const [editingFee, setEditingFee] = useState<any>(null);
  const [unitAddresses, setUnitAddresses] = useState<string[]>([]);
  const [expenseCategories, setExpenseCategories] = useState<any[]>([]);
  const [expenseSubcategories, setExpenseSubcategories] = useState<any[]>([]);
  const [selectedFeeIds, setSelectedFeeIds] = useState<Set<string>>(new Set());
  const [bundleDialogOpen, setBundleDialogOpen] = useState(false);
  const [bundlePreselectedFees, setBundlePreselectedFees] = useState<Set<string>>(new Set());

  useEffect(() => { fetchData(); fetchFeeItems(); fetchSettingsCategories(); }, []);

  const fetchSettingsCategories = async () => {
    const [catRes, subRes] = await Promise.all([
      supabase.from("expense_categories").select("*").eq("is_active", true).order("name"),
      supabase.from("expense_subcategories").select("*").eq("is_active", true).order("name"),
    ]);
    if (catRes.data) setExpenseCategories(catRes.data);
    if (subRes.data) setExpenseSubcategories(subRes.data);
  };

  const fetchFeeItems = async () => {
    const { data } = await supabase.from("fee_schedules").select("*").order("description");
    if (data) setFeeItems(data);
  };

  const handleBulkEditSave = async () => {
    setBulkEditSaving(true);
    const payload: Record<string, string | null> = {};
    if (bulkEditFields.category) payload.category = bulkEditFields.category;
    if (bulkEditFields.billable_type) payload.billable_type = bulkEditFields.billable_type;
    if (Object.keys(payload).length === 0) {
      toast({ variant: "destructive", title: "Select at least one field to update" });
      setBulkEditSaving(false);
      return;
    }
    try {
      const ids = Array.from(selectedIds);
      const { error } = await supabase.from("billable_expenses").update(payload).in("id", ids);
      if (error) throw error;
      toast({ title: `Updated ${ids.length} expense(s)` });
      setSelectedIds(new Set());
      setBulkEditOpen(false);
      setBulkEditFields({ category: "", billable_type: "" });
      fetchData();
    } catch (err: any) {
      toast({ variant: "destructive", title: "Error", description: err.message });
    } finally {
      setBulkEditSaving(false);
    }
  };


  const handleDeleteFee = async (id: string) => {
    if (!confirm("Delete this fee item?")) return;
    await supabase.from("fee_schedules").delete().eq("id", id);
    fetchFeeItems();
  };

  const fetchData = async () => {
    setLoading(true);
    const [expRes, assocRes, vendorRes] = await Promise.all([
      supabase.from("billable_expenses").select("*, associations(name)").order("date", { ascending: false }),
      supabase.from("associations").select("id, name").eq("status", "active").order("name"),
      supabase.from("vendors").select("*").order("name"),
    ]);
    if (expRes.data) setExpenses(expRes.data as Expense[]);
    if (assocRes.data) setAssociations(assocRes.data as Tables<"associations">[]);
    if (vendorRes.data) setVendors(vendorRes.data);
    setLoading(false);
  };

  const uniqueCategories = useMemo(() => [...new Set(expenses.map(e => e.category).filter(Boolean))].sort(), [expenses]);

  const filtered = useMemo(() => {
    return expenses.filter(e => {
      const q = searchTerm.toLowerCase();
      const matchSearch = !q || (e.description || "").toLowerCase().includes(q) || (e.vendor_name || "").toLowerCase().includes(q) || (e.address || "").toLowerCase().includes(q);
      const matchAssoc = assocFilter === "all" || e.association_id === assocFilter;
      const matchStatus = statusFilter === "all" || e.status === statusFilter;
      const matchCat = categoryFilter === "all" || e.category === categoryFilter;
      const isCredit = e.is_credit || Number(e.amount) < 0;
      const matchCredit = creditFilter === "all" || (creditFilter === "credits" ? isCredit : !isCredit);
      const matchType = billableTypeFilter === "all" || e.billable_type === billableTypeFilter;
      let matchDate = true;
      if (dateRange.start) matchDate = matchDate && e.date >= dateRange.start;
      if (dateRange.end) matchDate = matchDate && e.date <= dateRange.end;
      return matchSearch && matchAssoc && matchStatus && matchCat && matchCredit && matchType && matchDate;
    });
  }, [expenses, searchTerm, assocFilter, statusFilter, categoryFilter, creditFilter, billableTypeFilter, dateRange]);

  const pendingCharges = expenses.filter(e => e.status === "pending" && !e.is_credit && Number(e.amount) >= 0).reduce((s, e) => s + Number(e.amount), 0);
  const pendingCredits = expenses.filter(e => e.status === "pending" && (e.is_credit || Number(e.amount) < 0)).reduce((s, e) => s + Math.abs(Number(e.amount)), 0);
  const pendingNet = pendingCharges - pendingCredits;

  const handleSelectAll = (checked: boolean) => setSelectedIds(checked ? new Set(filtered.map(e => e.id)) : new Set());
  const handleSelectOne = (checked: boolean, id: string) => {
    const s = new Set(selectedIds);
    checked ? s.add(id) : s.delete(id);
    setSelectedIds(s);
  };

  const openAdd = () => {
    setEditingId(null);
    setForm({ ...emptyForm, date: format(new Date(), "yyyy-MM-dd") });
    setLineItems([{ ...emptyLineItem }]);
    setReceiptFile(null);
    setFormOpen(true);
  };

  const openEdit = (e: Expense) => {
    setEditingId(e.id);
    setForm({
      date: e.date, is_credit: e.is_credit,
      credit_reason: e.credit_reason || "", vendor_name: e.vendor_name || "",
      addresses: e.address ? e.address.split(" | ") : [], association_id: e.association_id,
      is_recurring: false, recurring_day: 1, recurring_end_date: "",
    });
    setLineItems([{
      category: e.category || "", billable_type: e.billable_type || "",
      description: e.description || "", quantity: String(e.quantity || 1),
      unit_price: e.unit_price ? String(e.unit_price) : "0",
      amount: String(Math.abs(Number(e.amount))),
    }]);
    setReceiptFile(null);
    setFormOpen(true);
  };

  const applyFeeScheduleItem = (idx: number, feeId: string) => {
    const fee = feeItems.find((f: any) => f.id === feeId);
    if (!fee) return;
    setLineItems(prev => {
      const updated = [...prev];
      const feeAmount = Number(fee.fee) || 0;
      updated[idx] = {
        ...updated[idx],
        category: fee.category || "",
        billable_type: fee.account || fee.subcategory || "",
        description: fee.description || "",
        unit_price: String(feeAmount),
        quantity: updated[idx].quantity || "1",
        amount: ((parseFloat(updated[idx].quantity) || 1) * feeAmount).toFixed(2),
      };
      return updated;
    });
  };

  const updateLineItem = (idx: number, field: keyof LineItem, value: string) => {
    setLineItems(prev => {
      const updated = [...prev];
      updated[idx] = { ...updated[idx], [field]: value };
      // Auto-calc amount from qty × rate
      if (field === "quantity" || field === "unit_price") {
        updated[idx].amount = getLineItemAmount(updated[idx]).toFixed(2);
      }
      return updated;
    });
  };

  const addLineItem = () => setLineItems(prev => [...prev, { ...emptyLineItem }]);
  const removeLineItem = (idx: number) => setLineItems(prev => prev.length > 1 ? prev.filter((_, i) => i !== idx) : prev);

  const grandTotal = lineItems.reduce((sum, li) => sum + getLineItemAmount(li), 0);

  const handleSave = async (addAnother = false) => {
    if (!form.association_id) {
      toast({ variant: "destructive", title: "Client is required" }); return;
    }
    const validItems = lineItems.filter(li => getLineItemAmount(li) > 0 || li.description);
    if (validItems.length === 0) {
      toast({ variant: "destructive", title: "Add at least one line item" }); return;
    }
    setSaving(true);

    // Upload receipt if present
    let receiptUrl: string | null = null;
    if (receiptFile) {
      const filePath = `receipts/${Date.now()}-${receiptFile.name}`;
      const { error: upErr } = await supabase.storage.from("files").upload(filePath, receiptFile);
      if (!upErr) {
        const { data: urlData } = supabase.storage.from("files").getPublicUrl(filePath);
        receiptUrl = urlData.publicUrl;
      }
    }

    if (editingId) {
      const li = validItems[0];
      const amt = getLineItemAmount(li) * (form.is_credit ? -1 : 1);
      const payload = {
        association_id: form.association_id, date: form.date || format(new Date(), "yyyy-MM-dd"),
        description: li.description || null, amount: amt, category: li.category || null,
        billable_type: li.billable_type || null, is_credit: form.is_credit,
        credit_reason: form.credit_reason || null, quantity: parseDecimalInput(li.quantity, 1),
        unit_price: li.unit_price ? parseDecimalInput(li.unit_price) : null,
        vendor_name: form.vendor_name || null, address: form.addresses.length > 0 ? form.addresses.join(" | ") : null,
        ...(receiptUrl ? { receipt_url: receiptUrl } : {}),
      };
      const { error } = await supabase.from("billable_expenses").update(payload).eq("id", editingId);
      if (error) { toast({ variant: "destructive", title: "Error", description: error.message }); setSaving(false); return; }
      toast({ title: "Expense updated" });
    } else {
      const rows = validItems.map(li => ({
        association_id: form.association_id,
        date: form.date || format(new Date(), "yyyy-MM-dd"),
        description: li.description || null,
        amount: getLineItemAmount(li) * (form.is_credit ? -1 : 1),
        category: li.category || null,
        billable_type: li.billable_type || null,
        is_credit: form.is_credit,
        credit_reason: form.credit_reason || null,
        quantity: parseDecimalInput(li.quantity, 1),
        unit_price: li.unit_price ? parseDecimalInput(li.unit_price) : null,
        vendor_name: form.vendor_name || null,
        address: form.addresses.length > 0 ? form.addresses.join(" | ") : null,
        ...(receiptUrl ? { receipt_url: receiptUrl } : {}),
        is_recurring: form.is_recurring,
        recurring_day: form.is_recurring ? form.recurring_day : null,
        recurring_next_date: form.is_recurring ? computeNextRecurringDate(form.recurring_day) : null,
        recurring_end_date: form.is_recurring && form.recurring_end_date ? form.recurring_end_date : null,
      }));
      const { error } = await supabase.from("billable_expenses").insert(rows);
      if (error) { toast({ variant: "destructive", title: "Error", description: error.message }); setSaving(false); return; }
      toast({ title: `${rows.length} expense${rows.length > 1 ? "s" : ""} added` });
    }

    if (addAnother) {
      setEditingId(null);
      setLineItems([{ ...emptyLineItem }]);
      setReceiptFile(null);
    } else {
      setFormOpen(false);
    }
    fetchData();
    setSaving(false);
  };

  const executeDelete = async () => {
    if (deleteTarget) {
      await supabase.from("billable_expenses").delete().eq("id", deleteTarget);
    } else {
      for (const id of selectedIds) await supabase.from("billable_expenses").delete().eq("id", id);
      setSelectedIds(new Set());
    }
    toast({ title: "Deleted" });
    setDeleteOpen(false); setDeleteTarget(null); fetchData();
  };

  const bulkUpdateStatus = async (status: string) => {
    for (const id of selectedIds) await supabase.from("billable_expenses").update({ status }).eq("id", id);
    setSelectedIds(new Set());
    toast({ title: `Marked as ${status}` }); fetchData();
  };

  const resetExpenseStatus = async (id: string) => {
    await supabase.from("billable_expenses").update({ status: "pending" }).eq("id", id);
    toast({ title: "Reset to Pending" }); fetchData();
  };

  const handleGenerateInvoice = async () => {
    const selected = expenses.filter(e => selectedIds.has(e.id));
    if (!selected.length) { toast({ variant: "destructive", title: "No expenses selected" }); return; }

    // Group by association
    const assocIds = [...new Set(selected.map(e => e.association_id))];
    if (assocIds.length > 1) {
      toast({ variant: "destructive", title: "Select expenses from a single client to generate an invoice." });
      return;
    }

    const assoc = associations.find(a => a.id === assocIds[0]);
    const clientName = assoc?.name || "Unknown Client";
    const invoiceNumber = `INV-${Date.now().toString(36).toUpperCase()}`;
    const issueDate = new Date().toISOString().split("T")[0];
    const dueDate = new Date(Date.now() + 30 * 86400000).toISOString().split("T")[0];

    const items = selected.map(e => ({
      date: e.date ? format(new Date(e.date + "T12:00:00"), "MM/dd/yyyy") : "",
      description: e.description || e.category || "Billable Expense",
      category: e.category || "",
      quantity: Number(e.quantity || 1),
      unitPrice: e.unit_price ? Number(e.unit_price) : Math.abs(Number(e.amount)),
      amount: Number(e.amount),
      isCredit: e.is_credit || Number(e.amount) < 0,
      address: e.address || undefined,
      vendor: e.vendor_name || undefined,
      receiptUrl: e.receipt_url || undefined,
    }));

    const charges = items.filter(i => !i.isCredit).reduce((s, i) => s + Math.abs(i.amount), 0);
    const credits = items.filter(i => i.isCredit).reduce((s, i) => s + Math.abs(i.amount), 0);

    // Save to client_invoices
    const { data: invData, error: invError } = await supabase.from("client_invoices").insert({
      invoice_number: invoiceNumber,
      association_id: assocIds[0],
      amount: charges,
      credits: credits,
      total: charges - credits,
      status: "sent",
      issue_date: issueDate,
      due_date: dueDate,
      source: "billable_expenses",
      created_by: (await supabase.auth.getUser()).data.user?.id,
    }).select().single();

    if (!invError && invData) {
      // Save line items
      const lineItems = selected.map(e => ({
        invoice_id: invData.id,
        billable_expense_id: e.id,
        description: e.description || e.category || "Billable Expense",
        category: e.category || "",
        date: e.date || null,
        quantity: Number(e.quantity || 1),
        unit_price: e.unit_price ? Number(e.unit_price) : Math.abs(Number(e.amount)),
        amount: Number(e.amount),
        is_credit: e.is_credit || Number(e.amount) < 0,
      }));
      await supabase.from("client_invoice_items").insert(lineItems);
    }

    // Fetch company settings for invoice
    const { data: settings } = await supabase.from("company_settings").select("key, value");
    const getSetting = (key: string) => settings?.find(s => s.key === key)?.value || "";

    await generateInvoicePdf({
      invoiceNumber,
      invoiceDate: issueDate,
      dueDate,
      clientName,
      clientAddress: assoc?.address || "",
      clientCity: assoc?.city || "",
      clientState: assoc?.state || "",
      clientZip: assoc?.zip || "",
      items,
      companyName: getSetting("company_name") || "ACM Community Management",
      companyAddress: getSetting("company_address") || "",
      companyEmail: getSetting("company_email") || assoc?.email || "",
      companyPhone: getSetting("company_phone") || assoc?.phone || "",
      companyWebsite: getSetting("company_website") || assoc?.website || "",
      logoUrl: getSetting("company_logo") || "",
    });

    toast({ title: "Invoice PDF generated", description: `Invoice for ${clientName} saved and downloaded.` });

    // Mark as invoiced
    bulkUpdateStatus("invoiced");
  };

  const exportCSV = async () => {
    if (!filtered.length) return;
    const rows = [
      ["Date", "Association", "Vendor", "Category", "Description", "Status", "Amount"].join(","),
      ...filtered.map(e => [
        e.date, `"${e.associations?.name || ""}"`, `"${e.vendor_name || ""}"`,
        `"${e.category || ""}"`, `"${(e.description || "").replace(/"/g, '""')}"`,
        e.status, Number(e.amount).toFixed(2)
      ].join(","))
    ].join("\n");
    const { saveCsv } = await import("@/lib/saveFile");
    await saveCsv(rows, `billable_expenses_${format(new Date(), "yyyy-MM-dd")}.csv`);
  };

  const fmtCurrency = (v: number) => new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(v);

  if (loading) {
    return <div className="flex items-center justify-center h-[50vh]"><Loader2 className="h-8 w-8 animate-spin text-muted-foreground" /></div>;
  }

  return (
    <div className="max-w-7xl mx-auto space-y-6">
      {/* Summary Card */}
      <Card className="bg-gradient-to-br from-rose-500 to-pink-600 text-white border-none">
        <CardContent className="p-6">
          <div className="flex items-start justify-between">
            <div>
              <p className="text-sm font-medium opacity-90">Pending Net</p>
              <p className="text-4xl font-bold mt-1">{fmtCurrency(pendingNet)}</p>
              <div className="flex gap-6 text-sm opacity-80 mt-2">
                <span>Charges: {fmtCurrency(pendingCharges)}</span>
                <span>Credits: -{fmtCurrency(pendingCredits)}</span>
              </div>
            </div>
            <div className="bg-white/20 rounded-full p-3">
              <DollarSign className="h-6 w-6" />
            </div>
          </div>
        </CardContent>
      </Card>

      {/* Tabs */}
      <Tabs value={activeTab} onValueChange={setActiveTab}>
        <TabsList className="bg-transparent border-b rounded-none w-full justify-start h-auto p-0 gap-0">
          {["expenses", "vendors", "fee-schedule", "settings"].map(tab => (
            <TabsTrigger
              key={tab}
              value={tab}
              className="rounded-none border-b-2 border-transparent data-[state=active]:border-primary data-[state=active]:shadow-none px-4 pb-3 pt-2 capitalize"
            >
              {tab === "fee-schedule" ? "Fee Schedule" : tab === "settings" ? "Settings" : tab.charAt(0).toUpperCase() + tab.slice(1)}
            </TabsTrigger>
          ))}
        </TabsList>

        <TabsContent value="expenses" className="space-y-6 mt-6">
          {/* Header */}
          <div className="flex items-center justify-between">
            <div>
              <h2 className="text-xl font-bold">Billable Expenses</h2>
              <p className="text-sm text-muted-foreground">Track billable items, credits, and generate invoices</p>
            </div>
            <div className="flex gap-2">
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button variant="outline" size="sm" className="gap-1.5" onClick={async () => {
                    const { data, error } = await supabase.functions.invoke("process-recurring-expenses");
                    if (error) { toast({ variant: "destructive", title: "Error", description: error.message }); return; }
                    toast({ title: `Recurring processed`, description: `${data?.created || 0} expense(s) created` });
                    fetchData();
                  }}><RefreshCw className="h-4 w-4" /> Process Recurring</Button>
                </TooltipTrigger>
                <TooltipContent>Generate any due recurring expenses</TooltipContent>
              </Tooltip>
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button variant="outline" size="icon" onClick={() => setActiveTab("settings")}><Settings className="h-4 w-4" /></Button>
                </TooltipTrigger>
                <TooltipContent>Expense Settings</TooltipContent>
              </Tooltip>
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button variant="outline" size="icon" onClick={() => setImportOpen(true)}><Upload className="h-4 w-4" /></Button>
                </TooltipTrigger>
                <TooltipContent>Import CSV/XLSX</TooltipContent>
              </Tooltip>
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button variant="outline" size="icon" onClick={exportCSV}><Download className="h-4 w-4" /></Button>
                </TooltipTrigger>
                <TooltipContent>Export CSV</TooltipContent>
              </Tooltip>
              <Button onClick={openAdd} className="gap-2"><Plus className="h-4 w-4" /> Add Expense</Button>
            </div>
          </div>

          {/* Filters */}
          <Card>
            <CardContent className="p-4 space-y-4">
              <div className="flex flex-col xl:flex-row gap-4">
                <div className="relative flex-1">
                  <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
                  <Input placeholder="Search description, address, vendor..." value={searchTerm} onChange={e => setSearchTerm(e.target.value)} className="pl-9" />
                </div>
                <div className="flex gap-2 items-center">
                  <Input type="date" value={dateRange.start} onChange={e => setDateRange(p => ({ ...p, start: e.target.value }))} className="w-[140px]" />
                  <span className="text-muted-foreground">–</span>
                  <Input type="date" value={dateRange.end} onChange={e => setDateRange(p => ({ ...p, end: e.target.value }))} className="w-[140px]" />
                  {(dateRange.start || dateRange.end) && <Button variant="ghost" size="icon" onClick={() => setDateRange({ start: "", end: "" })} className="h-8 w-8"><X className="h-3 w-3" /></Button>}
                </div>
              </div>
              <div className="flex flex-wrap gap-3 items-center">
                <div className="flex items-center gap-2">
                  <Switch id="grp" checked={groupByCategory} onCheckedChange={setGroupByCategory} />
                  <Label htmlFor="grp" className="text-sm flex items-center gap-1 cursor-pointer"><FolderTree className="h-4 w-4" /> Group by Category</Label>
                </div>
                <Select value={assocFilter} onValueChange={v => { setAssocFilter(v); setSelectedIds(new Set()); }}>
                  <SelectTrigger className="w-[160px]"><SelectValue placeholder="All Clients" /></SelectTrigger>
                  <SelectContent>
                    <SelectItem value="all">All Clients</SelectItem>
                    {associations.map(a => <SelectItem key={a.id} value={a.id}>{a.name}</SelectItem>)}
                  </SelectContent>
                </Select>
                <Select value={creditFilter} onValueChange={setCreditFilter}>
                  <SelectTrigger className="w-[160px]"><SelectValue /></SelectTrigger>
                  <SelectContent>
                    <SelectItem value="all">Charges & Credits</SelectItem>
                    <SelectItem value="charges">Charges Only</SelectItem>
                    <SelectItem value="credits">Credits Only</SelectItem>
                  </SelectContent>
                </Select>
                <Select value={categoryFilter} onValueChange={setCategoryFilter}>
                  <SelectTrigger className="w-[160px]"><SelectValue placeholder="All Categories" /></SelectTrigger>
                  <SelectContent>
                    <SelectItem value="all">All Categories</SelectItem>
                    {uniqueCategories.map(c => <SelectItem key={c!} value={c!}>{c}</SelectItem>)}
                  </SelectContent>
                </Select>
                <Select value={billableTypeFilter} onValueChange={setBillableTypeFilter}>
                  <SelectTrigger className="w-[160px]"><SelectValue placeholder="All Billable Types" /></SelectTrigger>
                  <SelectContent>
                    <SelectItem value="all">All Billable Types</SelectItem>
                  </SelectContent>
                </Select>
                <Select value={statusFilter} onValueChange={v => { setStatusFilter(v); setSelectedIds(new Set()); }}>
                  <SelectTrigger className="w-[130px]"><SelectValue /></SelectTrigger>
                  <SelectContent>
                    <SelectItem value="all">All Statuses</SelectItem>
                    <SelectItem value="review">Review</SelectItem>
                    <SelectItem value="pending">Pending</SelectItem>
                    <SelectItem value="invoiced">Invoiced</SelectItem>
                  </SelectContent>
                </Select>
              </div>
            </CardContent>
          </Card>

          {/* Bulk Actions */}
          {selectedIds.size > 0 && (
            <div className="flex flex-wrap gap-2 items-center">
              <Badge variant="secondary" className="h-9 px-3 flex items-center">{selectedIds.size} selected</Badge>
              <Button onClick={handleGenerateInvoice} className="gap-2 bg-emerald-600 hover:bg-emerald-700 text-white">
                <Receipt className="h-4 w-4" /> Generate Invoice PDF
              </Button>
              <DropdownMenu>
                <DropdownMenuTrigger asChild><Button variant="outline">Bulk Actions</Button></DropdownMenuTrigger>
                <DropdownMenuContent>
                  <DropdownMenuItem onClick={() => { setBulkEditFields({ category: "", billable_type: "" }); setBulkEditOpen(true); }}><Edit className="h-4 w-4 mr-2" /> Bulk Edit Category / Account</DropdownMenuItem>
                  <DropdownMenuItem onClick={() => bulkUpdateStatus("invoiced")}><CheckSquare className="h-4 w-4 mr-2" /> Mark Invoiced</DropdownMenuItem>
                  <DropdownMenuItem onClick={() => bulkUpdateStatus("pending")}><RotateCcw className="h-4 w-4 mr-2" /> Mark Pending</DropdownMenuItem>
                  <DropdownMenuItem onClick={() => { setDeleteTarget(null); setDeleteOpen(true); }} className="text-destructive"><Trash2 className="h-4 w-4 mr-2" /> Delete Selected</DropdownMenuItem>
                </DropdownMenuContent>
              </DropdownMenu>
              <Button variant="ghost" size="sm" onClick={() => setSelectedIds(new Set())}><X className="h-4 w-4 mr-1" /> Clear</Button>
            </div>
          )}

          {/* Table */}
          <div className="rounded-lg border bg-card overflow-hidden">
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead className="w-[40px]">
                    <Checkbox checked={filtered.length > 0 && selectedIds.size === filtered.length} onCheckedChange={handleSelectAll} />
                  </TableHead>
                  <TableHead className="text-xs font-bold uppercase">Date</TableHead>
                  <TableHead className="text-xs font-bold uppercase">Client</TableHead>
                  <TableHead className="text-xs font-bold uppercase">Details</TableHead>
                  <TableHead className="text-right text-xs font-bold uppercase">Qty</TableHead>
                  <TableHead className="text-center text-xs font-bold uppercase">Status</TableHead>
                  <TableHead className="text-right text-xs font-bold uppercase">Amount</TableHead>
                  <TableHead className="text-right text-xs font-bold uppercase w-24">Actions</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {filtered.length === 0 ? (
                  <TableRow><TableCell colSpan={8} className="text-center py-16 text-muted-foreground">No expenses found.</TableCell></TableRow>
                ) : groupByCategory ? (
                  uniqueCategories.map(cat => {
                    const items = filtered.filter(e => e.category === cat);
                    if (!items.length) return null;
                    const subtotal = items.reduce((s, e) => s + Number(e.amount), 0);
                    return (
                      <ExpenseGroup key={cat} category={cat || "Uncategorized"} count={items.length} subtotal={subtotal}>
                        {items.map(e => <ExpenseRow key={e.id} expense={e} selected={selectedIds.has(e.id)} onSelect={handleSelectOne} onEdit={() => openEdit(e)} onDelete={() => { setDeleteTarget(e.id); setDeleteOpen(true); }} onReset={() => resetExpenseStatus(e.id)} />)}
                      </ExpenseGroup>
                    );
                  })
                ) : (
                  filtered.map(e => <ExpenseRow key={e.id} expense={e} selected={selectedIds.has(e.id)} onSelect={handleSelectOne} onEdit={() => openEdit(e)} onDelete={() => { setDeleteTarget(e.id); setDeleteOpen(true); }} onReset={() => resetExpenseStatus(e.id)} />)
                )}
              </TableBody>
            </Table>
          </div>
        </TabsContent>

        <TabsContent value="vendors" className="space-y-6 mt-6">
          <div className="flex items-center justify-between">
            <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 vendors by name, service, email..." className="pl-9" />
            </div>
            <div className="flex gap-2">
              <Button variant="outline" className="gap-2"><Upload className="h-4 w-4" /> Import</Button>
              <Button className="gap-2"><Plus className="h-4 w-4" /> Add Vendor</Button>
            </div>
          </div>
          <div className="rounded-lg border bg-card overflow-hidden">
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>Vendor Name</TableHead>
                  <TableHead>Service Type</TableHead>
                  <TableHead>Email</TableHead>
                  <TableHead>Phone</TableHead>
                  <TableHead className="text-center">1099 Eligible</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {vendors.length === 0 ? (
                  <TableRow><TableCell colSpan={5} className="text-center py-12 text-muted-foreground">No vendors found.</TableCell></TableRow>
                ) : vendors.map(v => (
                  <TableRow key={v.id}>
                    <TableCell className="font-medium text-primary cursor-pointer hover:underline">{v.name}</TableCell>
                    <TableCell>{v.service_type || "Uncategorized"}</TableCell>
                    <TableCell>{v.email || "-"}</TableCell>
                    <TableCell>{v.phone || "-"}</TableCell>
                    <TableCell className="text-center"><Checkbox /></TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </div>
        </TabsContent>

        <TabsContent value="settings" className="space-y-6 mt-6">
          <ExpenseSettingsPanel />
        </TabsContent>

        <TabsContent value="fee-schedule" className="space-y-6 mt-6">
          <div className="flex items-center justify-between">
            <div>
              <h2 className="text-xl font-bold">Fee Schedule</h2>
              <p className="text-sm text-muted-foreground">Manage standard fees and service charges.</p>
            </div>
            <div className="flex gap-2">
              {selectedFeeIds.size > 0 && (
                <Button variant="outline" className="gap-2" onClick={() => {
                  setBundlePreselectedFees(new Set(Array.from(selectedFeeIds).map(id => `fee:${id}`)));
                  setBundleDialogOpen(true);
                }}>
                  <FolderTree className="h-4 w-4" /> Create Bundle ({selectedFeeIds.size})
                </Button>
              )}
              <Button className="gap-2" onClick={() => { setEditingFee(null); setFeeDialogOpen(true); }}><Plus className="h-4 w-4" /> Add Fee</Button>
            </div>
          </div>
          <Card>
            <CardHeader>
              <CardTitle className="text-lg">Current Fees</CardTitle>
              <p className="text-sm text-muted-foreground">Select fees and click "Create Bundle" to group them together.</p>
            </CardHeader>
            <CardContent>
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead className="w-10">
                      <Checkbox
                        checked={feeItems.length > 0 && selectedFeeIds.size === feeItems.length}
                        onCheckedChange={(checked) => {
                          setSelectedFeeIds(checked ? new Set(feeItems.map(f => f.id)) : new Set());
                        }}
                      />
                    </TableHead>
                    <TableHead>Service / Item Description</TableHead>
                    <TableHead>Category</TableHead>
                    <TableHead>Subcategory</TableHead>
                    <TableHead>Account</TableHead>
                    <TableHead className="text-right">Amount</TableHead>
                    <TableHead className="text-right">Actions</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {feeItems.length === 0 ? (
                    <TableRow><TableCell colSpan={7} className="text-center py-12 text-muted-foreground">No fees configured yet. Click "Add Fee" to get started.</TableCell></TableRow>
                  ) : feeItems.map(fee => (
                    <TableRow key={fee.id} className={selectedFeeIds.has(fee.id) ? "bg-primary/5" : ""}>
                      <TableCell>
                        <Checkbox
                          checked={selectedFeeIds.has(fee.id)}
                          onCheckedChange={(checked) => {
                            const next = new Set(selectedFeeIds);
                            if (checked) next.add(fee.id); else next.delete(fee.id);
                            setSelectedFeeIds(next);
                          }}
                        />
                      </TableCell>
                      <TableCell className="font-medium">{fee.description}</TableCell>
                      <TableCell><Badge variant="outline">{fee.category || "—"}</Badge></TableCell>
                      <TableCell>{fee.subcategory || "—"}</TableCell>
                      <TableCell>{fee.account || "—"}</TableCell>
                      <TableCell className="text-right font-mono">${Number(fee.fee).toFixed(2)}</TableCell>
                      <TableCell className="text-right">
                        <div className="flex justify-end gap-1">
                          <Button variant="ghost" size="icon" className="h-8 w-8" onClick={() => { setEditingFee(fee); setFeeDialogOpen(true); }}><Edit className="h-4 w-4" /></Button>
                          <Button variant="ghost" size="icon" className="h-8 w-8 text-destructive" onClick={() => handleDeleteFee(fee.id)}><Trash2 className="h-4 w-4" /></Button>
                        </div>
                      </TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </CardContent>
          </Card>
        </TabsContent>
      </Tabs>

      {/* Add/Edit Dialog */}
      <Dialog open={formOpen} onOpenChange={setFormOpen}>
        <DialogContent className="max-w-2xl max-h-[90vh] overflow-hidden flex flex-col">
          <DialogHeader>
            <DialogTitle>{editingId ? "Edit Expense" : "Add Expenses"}</DialogTitle>
            <DialogDescription>Create one or more billable expense records.</DialogDescription>
          </DialogHeader>
          <div className="space-y-4 overflow-y-auto pr-1 flex-1">
            <div className="grid grid-cols-2 gap-4">
              <div className="space-y-2">
                <Label>Client</Label>
                <Select value={form.association_id} onValueChange={async v => {
                  setForm({ ...form, association_id: v, addresses: [] });
                  const { data } = await supabase.from("units").select("address").eq("association_id", v).order("address");
                  setUnitAddresses((data || []).map(u => u.address).filter(Boolean) as string[]);
                }}>
                  <SelectTrigger><SelectValue placeholder="Select Client..." /></SelectTrigger>
                  <SelectContent>{associations.map(a => <SelectItem key={a.id} value={a.id}>{a.name}</SelectItem>)}</SelectContent>
                </Select>
              </div>
              <div className="space-y-2"><Label>Date</Label><Input type="date" value={form.date} onChange={e => setForm({ ...form, date: e.target.value })} /></div>
            </div>
            <div className="grid grid-cols-2 gap-4">
              <div className="space-y-2"><Label>Vendor (Optional)</Label>
                <Select value={form.vendor_name || "none"} onValueChange={v => setForm({ ...form, vendor_name: v === "none" ? "" : v })}>
                  <SelectTrigger><SelectValue placeholder="Select Vendor..." /></SelectTrigger>
                  <SelectContent>
                    <SelectItem value="none">No vendor</SelectItem>
                    {vendors.filter(v => v.name).map(v => <SelectItem key={v.id} value={v.name}>{v.name}</SelectItem>)}
                  </SelectContent>
                </Select>
              </div>
              <div className="space-y-2">
                <Label>Property Addresses (Optional)</Label>
                <DropdownMenu>
                  <DropdownMenuTrigger asChild>
                    <Button variant="outline" className="w-full justify-between font-normal h-10">
                      <span className="truncate text-left">
                        {form.addresses.length === 0
                          ? "Association-level"
                          : form.addresses.length === 1
                            ? form.addresses[0]
                            : `${form.addresses.length} properties selected`}
                      </span>
                    </Button>
                  </DropdownMenuTrigger>
                  <DropdownMenuContent className="w-80 max-h-60 overflow-y-auto" align="start">
                    <DropdownMenuItem onSelect={(e) => { e.preventDefault(); setForm({ ...form, addresses: [] }); }}>
                      <div className="flex items-center gap-2">
                        <Checkbox checked={form.addresses.length === 0} />
                        <span>Association-level (no specific property)</span>
                      </div>
                    </DropdownMenuItem>
                    {unitAddresses.map(addr => (
                      <DropdownMenuItem key={addr} onSelect={(e) => {
                        e.preventDefault();
                        setForm(prev => ({
                          ...prev,
                          addresses: prev.addresses.includes(addr)
                            ? prev.addresses.filter(a => a !== addr)
                            : [...prev.addresses, addr],
                        }));
                      }}>
                        <div className="flex items-center gap-2">
                          <Checkbox checked={form.addresses.includes(addr)} />
                          <span className="truncate">{addr}</span>
                        </div>
                      </DropdownMenuItem>
                    ))}
                  </DropdownMenuContent>
                </DropdownMenu>
                {form.addresses.length > 1 && (
                  <div className="flex flex-wrap gap-1 mt-1">
                    {form.addresses.map(addr => (
                      <Badge key={addr} variant="secondary" className="text-xs gap-1">
                        {addr}
                        <X className="h-3 w-3 cursor-pointer" onClick={() => setForm(prev => ({ ...prev, addresses: prev.addresses.filter(a => a !== addr) }))} />
                      </Badge>
                    ))}
                  </div>
                )}
              </div>
            </div>
            <div className="flex items-center gap-3 py-1 px-3 rounded-md border">
              <Switch checked={form.is_recurring} onCheckedChange={v => setForm({ ...form, is_recurring: v })} />
              <Label className="cursor-pointer flex items-center gap-2"><CalendarClock className="h-4 w-4" /> Monthly Recurring</Label>
            </div>
            {form.is_recurring && (
              <div className="grid grid-cols-2 gap-4 p-3 rounded-md border border-primary/20 bg-primary/5">
                <div className="space-y-2">
                  <Label className="text-xs">Day of Month (1-28)</Label>
                  <Input type="number" min={1} max={28} value={form.recurring_day} onChange={e => setForm({ ...form, recurring_day: Math.min(28, Math.max(1, parseInt(e.target.value) || 1)) })} className="h-9" />
                </div>
                <div className="space-y-2">
                  <Label className="text-xs">End Date (Optional)</Label>
                  <Input type="date" value={form.recurring_end_date} onChange={e => setForm({ ...form, recurring_end_date: e.target.value })} className="h-9" />
                </div>
                <p className="text-xs text-muted-foreground col-span-2">This expense will auto-generate on the {form.recurring_day}{form.recurring_day === 1 ? 'st' : form.recurring_day === 2 ? 'nd' : form.recurring_day === 3 ? 'rd' : 'th'} of each month.</p>
              </div>
            )}
            <div className="flex items-center gap-3 py-1 px-3 rounded-md border">
              <Switch checked={form.is_credit} onCheckedChange={v => setForm({ ...form, is_credit: v })} />
              <Label className="cursor-pointer">Mark as Credit/Refund</Label>
            </div>
            {form.is_credit && (
              <div className="space-y-2"><Label>Credit Reason</Label><Input value={form.credit_reason} onChange={e => setForm({ ...form, credit_reason: e.target.value })} /></div>
            )}

            {/* Line Items */}
            <div>
              <div className="flex items-center justify-between mb-3">
                <Label className="text-sm">Line Items <span className="text-muted-foreground text-xs">(Decimal quantities supported, e.g. 1.5 hours)</span></Label>
                <Button variant="link" size="sm" className="text-xs" onClick={addLineItem}>+ Add Row</Button>
              </div>
              <div className="space-y-4">
                {lineItems.map((li, idx) => (
                  <div key={idx} className="rounded-lg border bg-card p-4 space-y-4">
                    <div className="flex items-center justify-between">
                      <span className="text-xs font-medium text-muted-foreground">Item {idx + 1}</span>
                      {lineItems.length > 1 && (
                        <Button size="icon" variant="ghost" className="h-7 w-7 text-muted-foreground hover:text-destructive" onClick={() => removeLineItem(idx)}>
                          <Trash2 className="h-3.5 w-3.5" />
                        </Button>
                      )}
                    </div>
                    {/* Row 1: Fee Schedule, Category, Account */}
                    <div className="grid grid-cols-3 gap-4">
                      <div className="space-y-1.5">
                        <Label className="text-xs text-muted-foreground">Fee Schedule</Label>
                        <Select value="none" onValueChange={v => { if (v !== "none") applyFeeScheduleItem(idx, v); }}>
                          <SelectTrigger className="h-9 text-sm"><SelectValue placeholder="Select fee..." /></SelectTrigger>
                          <SelectContent>
                            <SelectItem value="none">-- Select --</SelectItem>
                            {feeItems.map((f: any) => (
                              <SelectItem key={f.id} value={f.id}>
                                {f.description} (${Number(f.fee).toFixed(2)})
                              </SelectItem>
                            ))}
                          </SelectContent>
                        </Select>
                      </div>
                      <div className="space-y-1.5">
                        <Label className="text-xs text-muted-foreground">Category</Label>
                        <Select value={li.category || "none"} onValueChange={v => updateLineItem(idx, "category", v === "none" ? "" : v)}>
                          <SelectTrigger className="h-9 text-sm"><SelectValue placeholder="Category..." /></SelectTrigger>
                          <SelectContent>
                            <SelectItem value="none">None</SelectItem>
                            {expenseSubcategories.map(s => <SelectItem key={s.id} value={s.name}>{s.name}</SelectItem>)}
                          </SelectContent>
                        </Select>
                      </div>
                      <div className="space-y-1.5">
                        <Label className="text-xs text-muted-foreground">Account</Label>
                        <Select value={li.billable_type || "none"} onValueChange={v => updateLineItem(idx, "billable_type", v === "none" ? "" : v)}>
                          <SelectTrigger className="h-9 text-sm"><SelectValue placeholder="Account..." /></SelectTrigger>
                          <SelectContent>
                            <SelectItem value="none">None</SelectItem>
                            {expenseCategories.map(c => <SelectItem key={c.id} value={c.name.toLowerCase()}>{c.name}</SelectItem>)}
                          </SelectContent>
                        </Select>
                      </div>
                    </div>
                    {/* Row 2: Description */}
                    <div className="space-y-1.5">
                      <Label className="text-xs text-muted-foreground">Description</Label>
                      <Input className="h-9 text-sm" value={li.description} onChange={e => updateLineItem(idx, "description", e.target.value)} placeholder="Item description..." />
                    </div>
                    {/* Row 3: Qty, Rate, Amount */}
                    <div className="grid grid-cols-3 gap-4">
                      <div className="space-y-1.5">
                        <Label className="text-xs text-muted-foreground">Qty</Label>
                        <Input className="h-9 text-sm" type="number" value={li.quantity} onChange={e => updateLineItem(idx, "quantity", e.target.value)} />
                      </div>
                      <div className="space-y-1.5">
                        <Label className="text-xs text-muted-foreground">Rate</Label>
                        <Input className="h-9 text-sm" type="number" step="0.01" value={li.unit_price} onChange={e => updateLineItem(idx, "unit_price", e.target.value)} placeholder="0" />
                      </div>
                      <div className="space-y-1.5">
                        <Label className="text-xs text-muted-foreground">Amount</Label>
                        <div className="h-9 flex items-center justify-end px-3 text-sm font-semibold rounded-md border bg-muted">
                          ${getLineItemAmount(li).toFixed(2)}
                        </div>
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            </div>

            {/* Summary Breakdown */}
            <div className="border-t pt-3">
              <div className="text-xs font-bold uppercase text-muted-foreground mb-2">Summary Breakdown</div>
              {lineItems.filter(li => getLineItemAmount(li) > 0).map((li, idx) => (
                <div key={idx} className="flex justify-between text-sm">
                  <span>{li.category || li.description || "General"}</span>
                  <span>${getLineItemAmount(li).toFixed(2)}</span>
                </div>
              ))}
              <div className="flex justify-between text-lg font-bold mt-2 border-t pt-2">
                <span>Grand Total</span>
                <span>${grandTotal.toFixed(2)}</span>
              </div>
            </div>

            {/* Receipt Attachment */}
            <div>
              <Label className="text-sm">Receipt Attachment</Label>
              <label className="mt-1 flex flex-col items-center justify-center border-2 border-dashed rounded-lg p-6 cursor-pointer hover:bg-muted/50 transition-colors">
                <Upload className="h-6 w-6 text-muted-foreground mb-1" />
                {receiptFile ? (
                  <p className="text-sm font-medium text-foreground">{receiptFile.name}</p>
                ) : (
                  <>
                    <p className="text-sm text-muted-foreground">Click to upload receipt</p>
                    <p className="text-xs text-muted-foreground">PDF, PNG, JPG up to 5MB</p>
                  </>
                )}
                <input type="file" accept=".pdf,.png,.jpg,.jpeg" className="hidden" onChange={e => setReceiptFile(e.target.files?.[0] || null)} />
              </label>
            </div>
          </div>
          <DialogFooter className="flex justify-between sm:justify-between gap-2 pt-4 border-t">
            <Button variant="ghost" onClick={() => setFormOpen(false)}>Cancel</Button>
            <div className="flex gap-2">
              {!editingId && (
                <Button variant="outline" onClick={() => handleSave(true)} disabled={saving} className="gap-2">
                  {saving && <Loader2 className="h-4 w-4 animate-spin" />} Save & Add Another
                </Button>
              )}
              <Button onClick={() => handleSave(false)} disabled={saving} className="gap-2">
                {saving && <Loader2 className="h-4 w-4 animate-spin" />} {editingId ? "Update" : `Save ${lineItems.filter(li => getLineItemAmount(li) > 0 || li.description).length} Expense${lineItems.filter(li => getLineItemAmount(li) > 0 || li.description).length !== 1 ? "s" : ""}`}
              </Button>
            </div>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Delete Confirmation */}
      <AlertDialog open={deleteOpen} onOpenChange={setDeleteOpen}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Confirm Deletion</AlertDialogTitle>
            <AlertDialogDescription>
              Delete {deleteTarget ? "this expense" : `${selectedIds.size} selected expenses`}? This cannot be undone.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>Cancel</AlertDialogCancel>
            <AlertDialogAction onClick={executeDelete} className="bg-destructive text-destructive-foreground hover:bg-destructive/90">Delete</AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      {/* Bulk Edit Category / Account Dialog */}
      <Dialog open={bulkEditOpen} onOpenChange={setBulkEditOpen}>
        <DialogContent className="sm:max-w-[480px]">
          <DialogHeader>
            <DialogTitle>Bulk Edit Expenses</DialogTitle>
            <DialogDescription>
              Update <span className="font-semibold text-foreground">{selectedIds.size}</span> selected expense{selectedIds.size !== 1 ? "s" : ""}. Only filled fields will be updated.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-4 py-4">
            <div className="space-y-2">
              <Label>Category</Label>
              <Select value={bulkEditFields.category || "none"} onValueChange={v => setBulkEditFields(p => ({ ...p, category: v === "none" ? "" : v }))}>
                <SelectTrigger><SelectValue placeholder="Leave unchanged" /></SelectTrigger>
                <SelectContent>
                  <SelectItem value="none">— Leave unchanged —</SelectItem>
                  {expenseSubcategories.map((s: any) => <SelectItem key={s.id} value={s.name}>{s.name}</SelectItem>)}
                </SelectContent>
              </Select>
            </div>
            <div className="space-y-2">
              <Label>Account</Label>
              <Select value={bulkEditFields.billable_type || "none"} onValueChange={v => setBulkEditFields(p => ({ ...p, billable_type: v === "none" ? "" : v }))}>
                <SelectTrigger><SelectValue placeholder="Leave unchanged" /></SelectTrigger>
                <SelectContent>
                  <SelectItem value="none">— Leave unchanged —</SelectItem>
                  {expenseCategories.map((c: any) => <SelectItem key={c.id} value={c.name.toLowerCase()}>{c.name}</SelectItem>)}
                </SelectContent>
              </Select>
            </div>
          </div>
          <DialogFooter>
            <Button variant="ghost" onClick={() => setBulkEditOpen(false)}>Cancel</Button>
            <Button onClick={handleBulkEditSave} disabled={bulkEditSaving} className="gap-2">
              {bulkEditSaving && <Loader2 className="h-4 w-4 animate-spin" />}
              Update {selectedIds.size} Expense{selectedIds.size !== 1 ? "s" : ""}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>


      {/* Import Dialog */}
      <Dialog open={importOpen} onOpenChange={setImportOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Import Expenses</DialogTitle>
            <DialogDescription>Upload a CSV or XLSX file with expense data.</DialogDescription>
          </DialogHeader>
          <div className="space-y-4 py-4">
            <div className="border-2 border-dashed rounded-lg p-8 text-center">
              <Upload className="h-8 w-8 mx-auto text-muted-foreground mb-2" />
              <p className="text-sm text-muted-foreground">Drag & drop your file here, or click to browse</p>
              <Input type="file" accept=".csv,.xlsx" className="mt-3 max-w-xs mx-auto" />
            </div>
            <p className="text-xs text-muted-foreground">Required columns: Date, Description, Amount, Association. Optional: Category, Vendor, Address.</p>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setImportOpen(false)}>Cancel</Button>
            <Button disabled>Import</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Fee Schedule Dialog */}
      <FeeScheduleDialog
        open={feeDialogOpen}
        onOpenChange={(v) => { setFeeDialogOpen(v); if (!v) setEditingFee(null); }}
        onSuccess={fetchFeeItems}
        item={editingFee}
      />

      {/* Expense Bundle Dialog */}
      <ExpenseBundleDialog
        open={bundleDialogOpen}
        onOpenChange={(v) => { setBundleDialogOpen(v); if (!v) { setSelectedFeeIds(new Set()); setBundlePreselectedFees(new Set()); } }}
        onSuccess={() => { setSelectedFeeIds(new Set()); setBundlePreselectedFees(new Set()); }}
        preselectedIds={bundlePreselectedFees}
      />

    </div>
  );
}

function ExpenseGroup({ category, count, subtotal, children }: { category: string; count: number; subtotal: number; children: React.ReactNode }) {
  return (
    <>
      <TableRow className="bg-muted/50">
        <TableCell colSpan={6} className="font-bold text-sm">{category} <span className="text-xs font-normal text-muted-foreground ml-2">({count} items)</span></TableCell>
        <TableCell className="text-right font-bold text-sm">${subtotal.toFixed(2)}</TableCell>
        <TableCell />
      </TableRow>
      {children}
    </>
  );
}

function ExpenseRow({ expense, selected, onSelect, onEdit, onDelete, onReset }: {
  expense: Expense; selected: boolean; onSelect: (c: boolean, id: string) => void; onEdit: () => void; onDelete: () => void; onReset: () => void;
}) {
  const isCredit = expense.is_credit || Number(expense.amount) < 0;
  return (
    <TableRow className={selected ? "bg-primary/5" : ""}>
      <TableCell><Checkbox checked={selected} onCheckedChange={c => onSelect(!!c, expense.id)} /></TableCell>
      <TableCell className="text-sm whitespace-nowrap">{expense.date ? format(new Date(expense.date + "T12:00:00"), "M/d/yyyy") : "—"}</TableCell>
      <TableCell className="text-sm font-medium">{expense.associations?.name || "—"}</TableCell>
      <TableCell>
        <div className="flex items-center gap-2">
          {expense.billable_type && <span className="text-sm font-medium capitalize">{expense.billable_type.replace(/_/g, " ")}</span>}
          {expense.billable_type && <Badge variant="secondary" className="text-[10px]">{expense.billable_type === "expense" ? "Expense" : expense.billable_type}</Badge>}
          {expense.is_recurring && <Badge variant="outline" className="text-[10px] gap-1 border-primary/30 text-primary"><CalendarClock className="h-3 w-3" />Recurring</Badge>}
          {expense.recurring_parent_id && <Badge variant="outline" className="text-[10px] gap-1"><RefreshCw className="h-3 w-3" />Auto</Badge>}
        </div>
        {expense.address && <div className="text-xs text-muted-foreground">{expense.address}</div>}
        {expense.description && <div className="text-xs italic text-muted-foreground">{expense.description}</div>}
        {expense.is_recurring && expense.recurring_next_date && (
          <div className="text-[10px] text-primary/70">Next: {expense.recurring_next_date}</div>
        )}
      </TableCell>
      <TableCell className="text-right text-sm">{expense.quantity ? Number(expense.quantity).toFixed(0) : "1"}</TableCell>
      <TableCell className="text-center">
        <Badge variant={expense.status === "invoiced" ? "secondary" : "default"} className={expense.status === "pending" ? "bg-amber-100 text-amber-700" : ""}>
          {expense.status === "invoiced" ? "Invoiced" : "Pending"}
        </Badge>
      </TableCell>
      <TableCell className={`text-right text-sm font-semibold ${isCredit ? "text-destructive" : ""}`}>
        {isCredit ? "-" : ""}${Math.abs(Number(expense.amount)).toFixed(2)}
      </TableCell>
      <TableCell className="text-right">
        <div className="flex justify-end gap-1">
          <Tooltip>
            <TooltipTrigger asChild>
              <Button variant="ghost" size="icon" className="h-8 w-8" onClick={onReset}><RotateCcw className="h-4 w-4" /></Button>
            </TooltipTrigger>
            <TooltipContent>Reset to Pending</TooltipContent>
          </Tooltip>
          <Tooltip>
            <TooltipTrigger asChild>
              <Button variant="ghost" size="icon" className="h-8 w-8" onClick={onEdit}><Edit className="h-4 w-4" /></Button>
            </TooltipTrigger>
            <TooltipContent>Edit</TooltipContent>
          </Tooltip>
          <Tooltip>
            <TooltipTrigger asChild>
              <Button variant="ghost" size="icon" className="h-8 w-8 text-destructive hover:text-destructive" onClick={onDelete}><Trash2 className="h-4 w-4" /></Button>
            </TooltipTrigger>
            <TooltipContent>Delete</TooltipContent>
          </Tooltip>
        </div>
      </TableCell>
    </TableRow>
  );
}
