import { useState, useEffect, useMemo, useCallback } from "react";
import { todayLocal } from "@/lib/dateUtils";
import { useAuth } from "@/contexts/AuthContext";
import { supabase } from "@/integrations/supabase/client";
import { useToast } from "@/hooks/use-toast";
import {
  Dialog, DialogContent, DialogFooter, DialogDescription
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Loader2, Plus, Trash2, SplitSquareHorizontal, DollarSign, Calendar as CalendarIcon, FileText } from "lucide-react";
import { Checkbox } from "@/components/ui/checkbox";
import { calculateRemainingUnpaidAssessmentBalance, computePaymentWaterfallAllocation, type WaterfallAllocation } from "@/lib/unitLedgerAccountBreakdown";

interface EditEntry {
  id: string;
  date: string;
  description: string | null;
  debit: number;
  credit: number;
  transaction_type: string;
  owner_id: string;
  chart_of_account_id?: string | null;
}

interface Props {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  unitId?: string;
  associationId?: string;
  onSuccess?: () => void;
  editEntry?: EditEntry | null;
}

export default function UnitLedgerTransactionForm({ open, onOpenChange, unitId: propUnitId, associationId: propAssociationId, onSuccess, editEntry }: Props) {
  const { user } = useAuth();
  const { toast } = useToast();

  const [loading, setLoading] = useState(false);
  const [fetchingData, setFetchingData] = useState(false);

  // Association/Unit pickers (when not provided via props)
  const [associations, setAssociations] = useState<any[]>([]);
  const [units, setUnits] = useState<any[]>([]);
  const [selectedAssociationId, setSelectedAssociationId] = useState("");
  const [selectedUnitId, setSelectedUnitId] = useState("");

  const needsPickers = !propUnitId;
  const activeUnitId = propUnitId || selectedUnitId;
  const activeAssociationId = propAssociationId || selectedAssociationId;

  const [owners, setOwners] = useState<any[]>([]);
  const [accounts, setAccounts] = useState<any[]>([]);

  const isEditing = !!editEntry;

  const [formData, setFormData] = useState({
    type: "Payment",
    chargeType: "assessment",
    date: "",
    ownerId: "",
    description: "",
    amount: "",
    chart_of_account_id: "",
  });

  const fieldsDisabled = !formData.date;

  const CHARGE_TYPES = [
    { value: "assessment", label: "Assessment" },
    { value: "late_fee", label: "Late Fee" },
    { value: "interest", label: "Interest" },
    { value: "admin_fee", label: "Admin Fee" },
    { value: "legal_fee", label: "Legal Fee" },
    { value: "violation", label: "Violation Fine" },
    { value: "bank_fee", label: "Bank Fee" },
    { value: "special_assessment", label: "Special Assessment" },
    { value: "other", label: "Other" },
  ];

  const CREDIT_WRITE_OFF_TYPES = new Set(CHARGE_TYPES.map((type) => type.value));

  // Pre-fill form when editing
  useEffect(() => {
    if (open && editEntry) {
      const isDebit = Number(editEntry.debit || 0) > 0;
      const txType = editEntry.transaction_type || "";
      const isPaymentType = ["Payment", "payment", "Prepayment", "prepayment", "refund", "Refund"].includes(txType);
      const isWriteOffCredit = !isDebit && CREDIT_WRITE_OFF_TYPES.has(txType);
      const chargeType = isDebit && !isPaymentType
        ? (CHARGE_TYPES.some(ct => ct.value === txType) ? txType : "assessment")
        : isWriteOffCredit
          ? txType
        : "assessment";
      setFormData({
        type: isDebit ? "Charge" : isWriteOffCredit ? "WriteOff" : (txType === "Prepayment" || txType === "prepayment" ? "Prepayment" : "Payment"),
        chargeType,
        date: editEntry.date || todayLocal(),
        ownerId: editEntry.owner_id || "",
        description: editEntry.description || "",
        amount: String(isDebit ? editEntry.debit : editEntry.credit),
        chart_of_account_id: editEntry.chart_of_account_id || "",
      });
    } else if (open && !editEntry) {
      setFormData({
        type: "Payment",
        chargeType: "assessment",
        date: "",
        ownerId: "",
        description: "",
        amount: "",
        chart_of_account_id: "",
      });
    }
  }, [open, editEntry]);

  const [addToBillable, setAddToBillable] = useState(false);
  const [feeRules, setFeeRules] = useState<any>(null);

  const [splits, setSplits] = useState<{ id: string; accountId: string; amount: string }[]>([]);
  const [useSplits, setUseSplits] = useState(false);
  const [waterfallAllocations, setWaterfallAllocations] = useState<WaterfallAllocation[]>([]);
  const [waterfallLoading, setWaterfallLoading] = useState(false);

  // Auto-compute waterfall allocation when payment type, owner, or amount changes
  useEffect(() => {
    if (formData.type !== "Payment" || !formData.ownerId || !formData.amount) {
      setWaterfallAllocations([]);
      return;
    }
    const amount = parseFloat(formData.amount);
    if (isNaN(amount) || amount <= 0) {
      setWaterfallAllocations([]);
      return;
    }

    let cancelled = false;
    setWaterfallLoading(true);

    (async () => {
      try {
        const { data: entries } = await supabase
          .from("owner_ledger_entries")
          .select("id, date, created_at, debit, credit, transaction_type, description")
          .eq("owner_id", formData.ownerId)
          .order("date", { ascending: true })
          .order("created_at", { ascending: true });

        if (cancelled) return;

        const { allocations } = computePaymentWaterfallAllocation(entries || [], amount);
        setWaterfallAllocations(allocations);

        // Auto-populate description with waterfall breakdown
        if (allocations.length > 0) {
          const parts = allocations
            .filter(a => a.applied > 0)
            .map(a => `${a.label}: $${a.applied.toFixed(2)}`);
          const autoDesc = `Payment applied: ${parts.join(", ")}`;
          setFormData(prev => {
            // Only auto-fill if description is empty or was previously auto-generated
            if (!prev.description || prev.description.startsWith("Payment applied:")) {
              return { ...prev, description: autoDesc };
            }
            return prev;
          });
        }
      } catch (err) {
        console.error("Waterfall allocation error:", err);
      } finally {
        if (!cancelled) setWaterfallLoading(false);
      }
    })();

    return () => { cancelled = true; };
  }, [formData.type, formData.ownerId, formData.amount]);

  // Fetch fee rules for the association (interest rate)
  useEffect(() => {
    if (!activeAssociationId) { setFeeRules(null); return; }
    supabase.from("association_fee_rules").select("interest_rate").eq("association_id", activeAssociationId).maybeSingle()
      .then(({ data }) => setFeeRules(data));
  }, [activeAssociationId]);

  // Auto-calculate interest when charge type is "interest"
  useEffect(() => {
    if (formData.type !== "Charge" || formData.chargeType !== "interest" || !feeRules || !activeUnitId || !formData.date) return;
    const rate = feeRules.interest_rate || 0;
    if (rate <= 0) return;

    const autoInterestDescriptionPattern = /^Interest @ .*remaining unpaid assessment balance$/i;

    // Fetch ledger entries up to the selected date to compute unpaid assessment balance for the selected unit
    (async () => {
      const { data: entries } = await supabase
        .from("owner_ledger_entries")
        .select("id, date, created_at, debit, credit, transaction_type, description")
        .eq("unit_id", activeUnitId)
        .lte("date", formData.date)
        .order("date", { ascending: true })
        .order("created_at", { ascending: true });

      if (!entries) return;

      const assessmentBalance = calculateRemainingUnpaidAssessmentBalance(entries);
      const interest = parseFloat((assessmentBalance * rate / 100).toFixed(2));
      const defaultDescription = `Interest @ ${rate}% on $${assessmentBalance.toLocaleString("en-US", { minimumFractionDigits: 2 })} remaining unpaid unit assessment balance`;

      setFormData(prev => ({
        ...prev,
        amount: interest > 0 ? interest.toString() : "",
        description: !prev.description || autoInterestDescriptionPattern.test(prev.description)
          ? defaultDescription
          : prev.description,
      }));
    })();
  }, [formData.type, formData.chargeType, formData.date, activeUnitId, feeRules]);

  // Fetch associations when pickers are needed
  useEffect(() => {
    if (!open || !needsPickers) return;
    supabase.from("associations").select("id, name").eq("status", "active").order("name").then(({ data }) => {
      setAssociations(data || []);
    });
  }, [open, needsPickers]);

  // Fetch units when association is selected
  useEffect(() => {
    if (!open || !needsPickers || !selectedAssociationId) {
      setUnits([]);
      return;
    }
    supabase
      .from("units")
      .select("id, unit_number, address")
      .eq("association_id", selectedAssociationId)
      .order("unit_number")
      .then(({ data }) => {
        setUnits(data || []);
      });
  }, [open, needsPickers, selectedAssociationId]);

  // Fetch owners & accounts when unit is determined
  useEffect(() => {
    if (!open || !activeUnitId) return;
    const fetchLookups = async () => {
      setFetchingData(true);
      try {
        const { data: ownersData } = await supabase
          .from("owners")
          .select("id, first_name, last_name")
          .eq("unit_id", activeUnitId)
          .eq("status", "active")
          .order("last_name");
        setOwners(ownersData || []);

        if (ownersData && ownersData.length > 0 && !formData.ownerId) {
          setFormData((prev) => ({ ...prev, ownerId: ownersData[0].id }));
        }

        if (activeAssociationId) {
          // Resolve the association's accounting system (zoho vs buildium)
          // so the COA list is scoped accordingly.
          const { data: assocRow } = await supabase
            .from("associations")
            .select("zoho_organization_id")
            .eq("id", activeAssociationId)
            .maybeSingle();
          const system = assocRow?.zoho_organization_id ? "zoho" : "buildium";

          const { data: accts } = await supabase
            .from("chart_of_accounts")
            .select("id, account_name, account_number, account_type, accounting_system")
            .eq("is_active", true)
            .eq("accounting_system", system)
            .order("account_number", { ascending: true });

          setAccounts(accts || []);
        }
      } catch (err) {
        console.error("Error fetching lookups:", err);
      } finally {
        setFetchingData(false);
      }
    };
    fetchLookups();
  }, [open, activeUnitId, activeAssociationId]);

  // Reset form when dialog opens fresh (skip when editing — handled above)
  useEffect(() => {
    if (open && !editEntry) {
      setFormData({
        type: "Payment",
        chargeType: "assessment",
        date: "",
        ownerId: "",
        description: "",
        amount: "",
        chart_of_account_id: "",
      });
      setSplits([]);
      setUseSplits(false);
      setAddToBillable(false);
      if (needsPickers) {
        setSelectedAssociationId("");
        setSelectedUnitId("");
      }
      setOwners([]);
      setAccounts([]);
    }
  }, [open, editEntry]);

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

  const handleSelectChange = (name: string, value: string) => {
    setFormData((prev) => ({ ...prev, [name]: value }));
  };

  const handleAddSplit = () => {
    setUseSplits(true);
    setSplits([...splits, { id: crypto.randomUUID(), accountId: "", amount: "" }]);
  };

  const handleRemoveSplit = (id: string) => {
    const newSplits = splits.filter((s) => s.id !== id);
    setSplits(newSplits);
    if (newSplits.length === 0) setUseSplits(false);
  };

  const handleSplitChange = (id: string, field: string, value: string) => {
    setSplits(splits.map((s) => (s.id === id ? { ...s, [field]: value } : s)));
  };

  const totalSplitAmount = useMemo(() => splits.reduce((sum, s) => sum + (parseFloat(s.amount) || 0), 0), [splits]);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    if (!activeUnitId) {
      toast({ variant: "destructive", title: "Error", description: "Please select a unit." });
      return;
    }

    if (!formData.ownerId) {
      toast({ variant: "destructive", title: "Error", description: "Please select an owner." });
      return;
    }

    if (!formData.date) {
      toast({ variant: "destructive", title: "Date Required", description: "Please choose a transaction date first." });
      return;
    }

    const numAmount = parseFloat(formData.amount);
    // Allow a $0.00 charge (used as a note/memo on the ledger). Payments and
    // prepayments still require a positive amount.
    const allowZero = ["Charge", "Expense", "WriteOff"].includes(formData.type);
    if (isNaN(numAmount) || numAmount < 0 || (numAmount === 0 && !allowZero)) {
      toast({
        variant: "destructive",
        title: "Invalid Amount",
        description: allowZero ? "Please enter a valid amount ($0.00 is allowed)." : "Please enter a valid positive amount.",
      });
      return;
    }

    if (!formData.description.trim()) {
      toast({ variant: "destructive", title: "Invalid Description", description: "Please enter a description." });
      return;
    }

    if (useSplits && splits.length > 0) {
      const hasEmpty = splits.some((s) => !s.accountId || !s.amount || parseFloat(s.amount) <= 0);
      if (hasEmpty) {
        toast({ variant: "destructive", title: "Invalid Splits", description: "All splits must have an account and valid amount." });
        return;
      }
      if (Math.abs(totalSplitAmount - numAmount) > 0.01) {
        toast({ variant: "destructive", title: "Amounts Mismatch", description: `Split total ($${totalSplitAmount.toFixed(2)}) must equal amount ($${numAmount.toFixed(2)}).` });
        return;
      }
    }

    setLoading(true);
    try {
      const isCharge = ["Charge", "Expense"].includes(formData.type);
      const isWriteOff = formData.type === "WriteOff";
      const isPrepayment = formData.type === "Prepayment";

      const payload: any = {
        unit_id: activeUnitId,
        association_id: activeAssociationId,
        owner_id: formData.ownerId,
        date: formData.date,
        description: formData.description.trim() || (isPrepayment ? "Prepayment / Account Credit" : isWriteOff ? "Write-Off Credit" : ""),
        transaction_type: isCharge || isWriteOff ? formData.chargeType : (isPrepayment ? "prepayment" : "payment"),
        debit: isCharge ? numAmount : 0,
        credit: isCharge ? 0 : numAmount,
        created_by: user?.id,
      };

      let data: any;
      if (isEditing && editEntry) {
        const { data: updated, error } = await supabase.from("owner_ledger_entries").update(payload).eq("id", editEntry.id).select().single();
        if (error) throw error;
        data = updated;
      } else {
        const { data: inserted, error } = await supabase.from("owner_ledger_entries").insert([payload]).select().single();
        if (error) throw error;
        data = inserted;
      }

      toast({ title: isEditing ? "Transaction Updated" : "Transaction Saved", description: `Successfully ${isEditing ? "updated" : "posted"} ${isWriteOff ? "Write-Off Credit" : formData.type} for $${numAmount.toFixed(2)}.` });

      // Create billable expense if checkbox was checked
      if (addToBillable && isCharge && activeAssociationId) {
        try {
          await supabase.from("billable_expenses").insert([{
            association_id: activeAssociationId,
            date: formData.date,
            description: formData.description.trim(),
            amount: numAmount,
            category: formData.chargeType || "other",
            status: "review",
            created_by: user?.id,
          }]);
        } catch (billableErr) {
          console.warn("Failed to create billable expense (non-blocking):", billableErr);
        }
      }

      // Journal entries for GL
      if (activeAssociationId) {
        if (isPrepayment) {
          // Auto-post to Prepayment/Unearned Revenue account if it exists
          const { data: prepayAcct } = await supabase
            .from("chart_of_accounts")
            .select("id")
            .eq("association_id", activeAssociationId)
            .eq("is_active", true)
            .or("account_name.ilike.%prepay%,account_name.ilike.%unearned%,account_name.ilike.%advance%,account_name.ilike.%credit balance%")
            .limit(1)
            .maybeSingle();

          if (prepayAcct) {
            await supabase.from("journal_entries").insert([{
              association_id: activeAssociationId,
              date: formData.date,
              description: `Prepayment: ${formData.description.trim() || "Account Credit"}`,
              amount: numAmount,
              type: "credit",
              chart_of_account_id: prepayAcct.id,
              created_by: user?.id,
            }]);
          }
        } else if (useSplits && splits.length > 0) {
          const entries = splits.map((split) => ({
            association_id: activeAssociationId,
            date: formData.date,
            description: `Unit Ledger (Split): ${formData.description.trim()}`,
            amount: parseFloat(split.amount),
            type: isCharge ? "debit" : "credit",
            chart_of_account_id: split.accountId,
            created_by: user?.id,
          }));
          await supabase.from("journal_entries").insert(entries);
        } else if (formData.chart_of_account_id) {
          await supabase.from("journal_entries").insert([{
            association_id: activeAssociationId,
            date: formData.date,
            description: `Unit Ledger: ${formData.description.trim()}`,
            amount: numAmount,
            type: isCharge ? "debit" : "credit",
            chart_of_account_id: formData.chart_of_account_id,
            created_by: user?.id,
          }]);
        }
      }

      if (onSuccess) onSuccess();
      onOpenChange(false);
    } catch (err: any) {
      console.error("[UnitLedgerTransactionForm] Error:", err);
      toast({ variant: "destructive", title: "Transaction Failed", description: err.message });
    } finally {
      setLoading(false);
    }
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-[750px] p-0 overflow-hidden">
        <div className="p-6 border-b">
          <h2 className="text-2xl font-semibold flex items-center gap-2">
            <FileText className="w-6 h-6 text-primary" />
            {isEditing ? "Edit Transaction" : "Record Transaction"}
          </h2>
          <DialogDescription className="text-muted-foreground mt-1.5 text-sm">
            {isEditing ? "Update the details of this ledger entry." : "Record a charge or payment to the unit ledger. This updates owner ledger entries and posts to the general ledger."}
          </DialogDescription>
        </div>

        <form id="record-tx-form" onSubmit={handleSubmit} className="overflow-y-auto max-h-[75vh]">
          <div className="p-6 space-y-6">

            {/* Association & Unit pickers when not provided */}
            {needsPickers && (
              <div className="grid grid-cols-1 md:grid-cols-2 gap-5">
                <div className="space-y-2">
                  <Label>Association <span className="text-destructive">*</span></Label>
                  <Select value={selectedAssociationId} onValueChange={(v) => { setSelectedAssociationId(v); setSelectedUnitId(""); setFormData(prev => ({ ...prev, ownerId: "", chart_of_account_id: "" })); }} disabled={fieldsDisabled}>
                    <SelectTrigger className="h-10"><SelectValue placeholder="Select association" /></SelectTrigger>
                    <SelectContent>
                      {associations.map(a => <SelectItem key={a.id} value={a.id}>{a.name}</SelectItem>)}
                    </SelectContent>
                  </Select>
                </div>
                <div className="space-y-2">
                  <Label>Unit <span className="text-destructive">*</span></Label>
                  <Select value={selectedUnitId} onValueChange={(v) => { setSelectedUnitId(v); setFormData(prev => ({ ...prev, ownerId: "", chart_of_account_id: "" })); }} disabled={fieldsDisabled || !selectedAssociationId}>
                    <SelectTrigger className="h-10"><SelectValue placeholder="Select unit" /></SelectTrigger>
                    <SelectContent>
                      {units.map(u => (
                        <SelectItem key={u.id} value={u.id}>
                          Unit {u.unit_number}{u.address ? ` — ${u.address}` : ""}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
              </div>
            )}

            <div className={`grid grid-cols-1 ${["Charge", "WriteOff"].includes(formData.type) ? "md:grid-cols-3" : "md:grid-cols-2"} gap-5`}>
              <div className="space-y-2">
                <Label>Transaction Type <span className="text-destructive">*</span></Label>
                <Select value={formData.type} onValueChange={(v) => handleSelectChange("type", v)} disabled={fieldsDisabled}>
                  <SelectTrigger className="h-10"><SelectValue placeholder="Select type" /></SelectTrigger>
                  <SelectContent>
                    <SelectItem value="Payment">Payment</SelectItem>
                    <SelectItem value="Charge">Charge</SelectItem>
                    <SelectItem value="WriteOff">Write-Off Credit</SelectItem>
                    <SelectItem value="Prepayment">Prepayment (Account Credit)</SelectItem>
                  </SelectContent>
                </Select>
              </div>

              {["Charge", "WriteOff"].includes(formData.type) && (
                <div className="space-y-2">
                  <Label>{formData.type === "WriteOff" ? "Write-Off Category" : "Charge Type"} <span className="text-destructive">*</span></Label>
                  <Select value={formData.chargeType} onValueChange={(v) => handleSelectChange("chargeType", v)} disabled={fieldsDisabled}>
                    <SelectTrigger className="h-10"><SelectValue placeholder="Select charge type" /></SelectTrigger>
                    <SelectContent>
                      {CHARGE_TYPES.map(ct => (
                        <SelectItem key={ct.value} value={ct.value}>{ct.label}</SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
              )}

              <div className="space-y-2">
                <Label>Date <span className="text-destructive">*</span></Label>
                <div className="relative">
                  <CalendarIcon className="absolute left-3 top-2.5 h-4 w-4 text-muted-foreground" />
                  <Input name="date" type="date" required value={formData.date} onChange={handleChange} className="pl-9 h-10" />
                </div>
              </div>
            </div>

            <div className="space-y-2">
              <Label>Owner <span className="text-destructive">*</span></Label>
              <Select value={formData.ownerId} onValueChange={(v) => handleSelectChange("ownerId", v)} disabled={fieldsDisabled || fetchingData || !activeUnitId}>
                <SelectTrigger className="h-10"><SelectValue placeholder={!activeUnitId ? "Select a unit first" : "Select owner"} /></SelectTrigger>
                <SelectContent>
                  {owners.map((o) => (
                    <SelectItem key={o.id} value={o.id}>{o.first_name} {o.last_name}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>

            <div className="grid grid-cols-1 md:grid-cols-[2fr_1fr] gap-5">
              <div className="space-y-2">
                <Label>Description <span className="text-destructive">*</span></Label>
                <Input name="description" required placeholder="E.g., Monthly Assessment" value={formData.description} onChange={handleChange} disabled={fieldsDisabled} className="h-10" />
              </div>
              <div className="space-y-2">
                <Label>Total Amount <span className="text-destructive">*</span></Label>
                <div className="relative">
                  <DollarSign className="absolute left-3 top-2.5 h-4 w-4 text-muted-foreground" />
                  <Input name="amount" type="number" step="0.01" min="0.01" required placeholder="0.00" value={formData.amount} onChange={handleChange} disabled={fieldsDisabled} className="pl-8 h-10 font-mono" />
                </div>
                </div>
                {formData.type === "Charge" && formData.chargeType === "interest" && feeRules && (
                  <p className="text-xs text-muted-foreground col-span-full">
                    Auto-calculated at {feeRules.interest_rate}% on outstanding assessment balance as of {formData.date}. You can override.
                  </p>
                )}
              </div>

            {/* Waterfall allocation preview for payments */}
            {formData.type === "Payment" && waterfallAllocations.length > 0 && (
              <div className="border rounded-lg overflow-hidden bg-muted/30">
                <div className="px-4 py-2.5 border-b bg-muted/50 flex items-center justify-between">
                  <h4 className="text-sm font-semibold flex items-center gap-2">
                    <SplitSquareHorizontal className="w-4 h-4 text-primary" />
                    Payment Application Preview
                  </h4>
                  <span className="text-[11px] text-muted-foreground">Applied by priority</span>
                </div>
                <table className="w-full text-sm">
                  <thead className="border-b">
                    <tr className="text-xs text-muted-foreground">
                      <th className="text-left p-2.5 font-medium">Charge Type</th>
                      <th className="text-right p-2.5 font-medium">Balance Due</th>
                      <th className="text-right p-2.5 font-medium">Applied</th>
                      <th className="text-right p-2.5 font-medium">Remaining</th>
                    </tr>
                  </thead>
                  <tbody className="divide-y">
                    {waterfallAllocations.map((a) => (
                      <tr key={a.type} className={a.applied > 0 ? "" : "opacity-50"}>
                        <td className="p-2.5 font-medium">{a.label}</td>
                        <td className="p-2.5 text-right font-mono text-muted-foreground">${a.openBefore.toFixed(2)}</td>
                        <td className="p-2.5 text-right font-mono text-emerald-600 font-semibold">
                          {a.applied > 0 ? `-$${a.applied.toFixed(2)}` : "—"}
                        </td>
                        <td className="p-2.5 text-right font-mono">${a.openAfter.toFixed(2)}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
            {formData.type === "Payment" && waterfallLoading && (
              <p className="text-xs text-muted-foreground flex items-center gap-1.5">
                <Loader2 className="h-3 w-3 animate-spin" /> Calculating allocation…
              </p>
            )}

            {/* Add to Billable Expenses checkbox — only for charges */}
            {["Charge", "Expense"].includes(formData.type) && !isEditing && (
              <div className="flex items-center gap-2 bg-muted/50 p-3 rounded-lg border">
                <Checkbox
                  id="addToBillable"
                  checked={addToBillable}
                  disabled={fieldsDisabled}
                  onCheckedChange={(checked) => setAddToBillable(!!checked)}
                />
                <label htmlFor="addToBillable" className="text-sm font-medium cursor-pointer select-none">
                  Add to Client Billable Expenses
                </label>
                {addToBillable && (
                  <span className="text-xs text-muted-foreground ml-auto">Will appear in Review tab</span>
                )}
              </div>
            )}

            <div className="h-px bg-border w-full my-2" />

            {/* Ledger Allocation */}
            <div className="space-y-4">
              <div>
                <h4 className="text-sm font-semibold flex items-center gap-2">
                  <SplitSquareHorizontal className="w-4 h-4 text-muted-foreground" />
                  Ledger Allocation
                </h4>
                <p className="text-xs text-muted-foreground mt-1">Select the offset account, or split across multiple.</p>
              </div>

              {!useSplits ? (
                <div className="space-y-2 bg-muted/50 p-4 rounded-lg border">
                  <Label className="text-sm font-medium">Offsetting Account</Label>
                  <Select value={formData.chart_of_account_id} onValueChange={(v) => handleSelectChange("chart_of_account_id", v)} disabled={fieldsDisabled}>
                    <SelectTrigger className="h-9"><SelectValue placeholder="Select Account (optional)" /></SelectTrigger>
                    <SelectContent className="max-h-[250px]">
                      {accounts.map((acc) => (
                        <SelectItem key={acc.id} value={acc.id}>{acc.account_name}</SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                  <Button type="button" variant="ghost" size="sm" onClick={handleAddSplit} disabled={fieldsDisabled} className="text-primary mt-2 h-8 px-2">
                    Split multiple accounts
                  </Button>
                </div>
              ) : (
                <div className="border rounded-lg overflow-hidden">
                  <table className="w-full text-left text-sm">
                    <thead className="bg-muted/50 border-b">
                      <tr>
                        <th className="font-medium p-3 w-3/5">Ledger Account</th>
                        <th className="font-medium p-3 w-1/3">Amount</th>
                        <th className="font-medium p-3 text-center" />
                      </tr>
                    </thead>
                    <tbody className="divide-y">
                      {splits.map((split) => (
                        <tr key={split.id} className="hover:bg-muted/30">
                          <td className="p-3">
                            <Select value={split.accountId} onValueChange={(val) => handleSplitChange(split.id, "accountId", val)} disabled={fieldsDisabled}>
                              <SelectTrigger className="h-9 text-sm"><SelectValue placeholder="Select Account" /></SelectTrigger>
                              <SelectContent className="max-h-[250px]">
                                {accounts.map((acc) => (
                                  <SelectItem key={acc.id} value={acc.id}>{acc.account_name}</SelectItem>
                                ))}
                              </SelectContent>
                            </Select>
                          </td>
                          <td className="p-3">
                            <div className="relative">
                              <DollarSign className="absolute left-2.5 top-2.5 h-3.5 w-3.5 text-muted-foreground" />
                              <Input type="number" step="0.01" min="0.01" placeholder="0.00" value={split.amount} onChange={(e) => handleSplitChange(split.id, "amount", e.target.value)} disabled={fieldsDisabled} className="pl-7 h-9 font-mono text-sm" />
                            </div>
                          </td>
                          <td className="p-3 text-center">
                            <Button type="button" variant="ghost" size="icon" onClick={() => handleRemoveSplit(split.id)} className="h-8 w-8 text-muted-foreground hover:text-destructive hover:bg-destructive/10">
                              <Trash2 className="h-4 w-4" />
                            </Button>
                          </td>
                        </tr>
                      ))}
                      <tr className="bg-muted/50 border-t">
                        <td className="p-3 font-medium text-right">Allocated Total:</td>
                        <td className="p-3 font-mono font-medium">
                          <span className={Math.abs(totalSplitAmount - parseFloat(formData.amount || "0")) > 0.01 && formData.amount ? "text-destructive" : "text-emerald-600"}>
                            ${totalSplitAmount.toFixed(2)}
                          </span>
                        </td>
                        <td />
                      </tr>
                    </tbody>
                  </table>
                  <div className="p-3 bg-muted/50 border-t flex gap-2">
                    <Button type="button" variant="outline" size="sm" onClick={handleAddSplit} disabled={fieldsDisabled} className="text-primary">
                      <Plus className="w-3.5 h-3.5 mr-1" /> Add Line
                    </Button>
                    <Button type="button" variant="ghost" size="sm" onClick={() => setUseSplits(false)} className="text-muted-foreground">
                      Cancel Splits
                    </Button>
                  </div>
                </div>
              )}
            </div>
          </div>
        </form>

        <DialogFooter className="p-5 border-t sm:justify-between items-center flex-col sm:flex-row gap-3">
              <div className="text-xs text-muted-foreground font-medium hidden sm:block">
            Write-off credits reduce the selected category balance.
          </div>
          <div className="flex items-center gap-3 w-full sm:w-auto">
            <Button type="button" variant="outline" onClick={() => onOpenChange(false)} disabled={loading} className="h-10 px-6 w-full sm:w-auto">
              Cancel
            </Button>
            <Button type="submit" form="record-tx-form" disabled={loading || fieldsDisabled} className="h-10 px-6 w-full sm:w-auto">
              {loading ? <><Loader2 className="w-4 h-4 mr-2 animate-spin" /> Saving...</> : "Save Transaction"}
            </Button>
          </div>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
