import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useMemo, useState } from "react";
import { accounting } from "@/lib/accountingClient";
import { useCompanyId } from "./lib/useCompanyId";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from "@/components/ui/table";
import { Badge } from "@/components/ui/badge";
import { DollarSign, CheckSquare, Search, Loader2 } from "lucide-react";
import { toast } from "sonner";
import { money } from "./lib/format";

type PaymentRow = {
  customerId: string;
  customerName: string;
  propertyAddress: string | null;
  openInvoices: any[];
  totalBalance: number;
  amountToApply: string;
  reference: string;
  selected: boolean;
};

export default function AccountingReceivePaymentsPage() {
  const { companyId, loading: companyLoading, error: companyError, associationId } = useCompanyId();
  const cid = companyId ?? "";
  const cur = "USD";
  const qc = useQueryClient();

  const [depositAccountId, setDepositAccountId] = useState("");
  const [payDate, setPayDate] = useState(new Date().toLocaleDateString("en-CA", { timeZone: "America/New_York" }));
  const [payMethod, setPayMethod] = useState("check");
  const [search, setSearch] = useState("");
  const [saving, setSaving] = useState(false);
  const [rows, setRows] = useState<PaymentRow[]>([]);
  const [initialized, setInitialized] = useState(false);

  const { data: bankAccounts = [] } = useQuery({
    queryKey: ["bank-accounts", cid],
    enabled: !!cid,
    queryFn: async () =>
      (await accounting.from("accounts").select("id,name,code,balance").eq("company_id", cid).eq("is_bank", true).order("name")).data ?? [],
  });

  const { data: openInvoices = [] } = useQuery({
    queryKey: ["open-invoices-bulk", cid],
    enabled: !!cid,
    queryFn: async () =>
      (await accounting.from("invoices")
        .select("id,number,total,paid_amount,due_date,issue_date,status,customer_id,customers(id,name,property_address,lot_number)")
        .eq("company_id", cid)
        .in("status", ["sent", "overdue"])
        .order("issue_date", { ascending: true })
      ).data ?? [],
  });

  // Build homeowner payment rows from open invoices
  useMemo(() => {
    if (!(openInvoices as any[]).length || initialized) return;
    const map = new Map<string, PaymentRow>();
    for (const inv of openInvoices as any[]) {
      const cust = inv.customers;
      if (!cust) continue;
      const balance = Math.max(0, Number(inv.total ?? 0) - Number(inv.paid_amount ?? 0));
      if (balance <= 0) continue;
      const existing = map.get(cust.id);
      if (existing) {
        existing.openInvoices.push(inv);
        existing.totalBalance += balance;
        existing.amountToApply = String((parseFloat(existing.amountToApply) || 0) + balance);
      } else {
        map.set(cust.id, {
          customerId: cust.id,
          customerName: cust.name,
          propertyAddress: cust.property_address ?? null,
          openInvoices: [inv],
          totalBalance: balance,
          amountToApply: String(balance.toFixed(2)),
          reference: "",
          selected: false,
        });
      }
    }
    const sorted = Array.from(map.values()).sort((a, b) => a.customerName.localeCompare(b.customerName));
    setRows(sorted);
    setInitialized(true);
  }, [openInvoices, initialized]);

  const updateRow = (customerId: string, patch: Partial<PaymentRow>) => {
    setRows(prev => prev.map(r => r.customerId === customerId ? { ...r, ...patch } : r));
  };

  const filtered = useMemo(() => {
    if (!search.trim()) return rows;
    const q = search.toLowerCase();
    return rows.filter(r =>
      r.customerName.toLowerCase().includes(q) ||
      (r.propertyAddress ?? "").toLowerCase().includes(q)
    );
  }, [rows, search]);

  const selected = rows.filter(r => r.selected);
  const totalSelected = selected.reduce((s, r) => s + (parseFloat(r.amountToApply) || 0), 0);

  const toggleAll = () => {
    const allSelected = filtered.every(r => r.selected);
    const ids = new Set(filtered.map(r => r.customerId));
    setRows(prev => prev.map(r => ids.has(r.customerId) ? { ...r, selected: !allSelected } : r));
  };

  const recordPayments = async () => {
    if (!depositAccountId) return toast.error("Select a deposit account first");
    if (selected.length === 0) return toast.error("Select at least one homeowner");
    const invalid = selected.find(r => !parseFloat(r.amountToApply) || parseFloat(r.amountToApply) <= 0);
    if (invalid) return toast.error(`Enter an amount for ${invalid.customerName}`);

    setSaving(true);
    let successCount = 0;
    const errors: string[] = [];

    for (const row of selected) {
      try {
        let remaining = parseFloat(row.amountToApply) || 0;
        const refLabel = row.reference || payMethod.toUpperCase();

        // Create one bank transaction per homeowner
        const { error: txErr } = await accounting.from("transactions").insert({
          company_id: cid,
          account_id: depositAccountId,
          date: payDate,
          type: "credit",  // credit = money in on bank (deposit)
          amount: remaining,
          description: `Payment · ${row.customerName}`,
          category: "Homeowner Payment",
          reference: refLabel,
          customer_id: row.customerId,
        });
        if (txErr) throw new Error(txErr.message);

        // Apply payment to invoices FIFO (oldest first)
        const sorted = [...row.openInvoices].sort((a, b) =>
          (a.issue_date ?? "").localeCompare(b.issue_date ?? "")
        );
        for (const inv of sorted) {
          if (remaining <= 0) break;
          const invBalance = Math.max(0, Number(inv.total ?? 0) - Number(inv.paid_amount ?? 0));
          if (invBalance <= 0) continue;
          const applying = Math.min(remaining, invBalance);
          const newPaid = Number(inv.paid_amount ?? 0) + applying;
          const fullyPaid = newPaid >= Number(inv.total ?? 0);
          await accounting.from("invoices").update({
            paid_amount: newPaid,
            status: fullyPaid ? "paid" : "sent",
          }).eq("id", inv.id);
          remaining -= applying;
        }

        successCount++;
      } catch (e: any) {
        errors.push(`${row.customerName}: ${e.message}`);
      }
    }

    setSaving(false);

    if (errors.length) {
      toast.error(`${errors.length} error(s): ${errors.slice(0, 2).join("; ")}`);
    }
    if (successCount > 0) {
      toast.success(`${successCount} payment${successCount > 1 ? "s" : ""} recorded · ${money(totalSelected, cur)} total`);
      setInitialized(false); // Re-build rows from fresh data
      setRows([]);
      qc.invalidateQueries({ queryKey: ["open-invoices-bulk", cid] });
      qc.invalidateQueries({ queryKey: ["invoices", cid] });
      qc.invalidateQueries({ queryKey: ["transactions", cid] });
      qc.invalidateQueries({ queryKey: ["accounts", cid] });
    }
  };

  if (!associationId) return <p className="text-sm text-muted-foreground">Select an association.</p>;
  if (companyLoading) return <div className="flex justify-center py-12"><Loader2 className="h-6 w-6 animate-spin text-muted-foreground" /></div>;
  if (companyError || !companyId) return <p className="text-sm text-muted-foreground text-center py-12">{companyError || "Accounting setup is not ready."}</p>;

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-semibold">Receive Payments</h1>
          <p className="text-sm text-muted-foreground">Record multiple homeowner payments in one batch</p>
        </div>
      </div>

      {/* Batch settings */}
      <Card>
        <CardContent className="pt-4 pb-4">
          <div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
            <div>
              <Label>Deposit account *</Label>
              <Select value={depositAccountId} onValueChange={setDepositAccountId}>
                <SelectTrigger><SelectValue placeholder="Select bank account" /></SelectTrigger>
                <SelectContent>
                  {(bankAccounts as any[]).map((a) => (
                    <SelectItem key={a.id} value={a.id}>
                      {a.code ? `${a.code} · ` : ""}{a.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div>
              <Label>Payment date *</Label>
              <Input type="date" value={payDate} onChange={(e) => setPayDate(e.target.value)} />
            </div>
            <div>
              <Label>Payment method</Label>
              <Select value={payMethod} onValueChange={setPayMethod}>
                <SelectTrigger><SelectValue /></SelectTrigger>
                <SelectContent>
                  <SelectItem value="check">Check</SelectItem>
                  <SelectItem value="ach">ACH</SelectItem>
                  <SelectItem value="online">Online Portal</SelectItem>
                  <SelectItem value="cash">Cash</SelectItem>
                  <SelectItem value="wire">Wire</SelectItem>
                  <SelectItem value="other">Other</SelectItem>
                </SelectContent>
              </Select>
            </div>
          </div>
        </CardContent>
      </Card>

      {/* Summary bar */}
      {selected.length > 0 && (
        <div className="flex items-center justify-between rounded-lg border border-emerald-200 bg-emerald-50 px-4 py-3">
          <div className="flex items-center gap-3 text-sm text-emerald-800">
            <CheckSquare className="h-4 w-4" />
            <span><strong>{selected.length}</strong> homeowner{selected.length !== 1 ? "s" : ""} selected</span>
            <span className="text-emerald-600">·</span>
            <span>Total: <strong>{money(totalSelected, cur)}</strong></span>
          </div>
          <Button onClick={recordPayments} disabled={saving} className="bg-emerald-600 hover:bg-emerald-700">
            {saving ? "Recording…" : `Record ${selected.length} payment${selected.length !== 1 ? "s" : ""}`}
          </Button>
        </div>
      )}

      {/* Search */}
      <div className="relative max-w-sm">
        <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
        <Input className="pl-9" placeholder="Search homeowner or property…" value={search} onChange={(e) => setSearch(e.target.value)} />
      </div>

      {/* Homeowner table */}
      <Card>
        <CardHeader className="pb-2">
          <div className="flex items-center justify-between">
            <CardTitle className="text-base">
              Homeowners with outstanding balances
              <span className="ml-2 text-sm font-normal text-muted-foreground">({filtered.length})</span>
            </CardTitle>
            <Button variant="outline" size="sm" onClick={toggleAll}>
              {filtered.every(r => r.selected) ? "Deselect all" : "Select all"}
            </Button>
          </div>
        </CardHeader>
        <CardContent className="p-0">
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead className="w-10"></TableHead>
                <TableHead>Homeowner</TableHead>
                <TableHead>Property</TableHead>
                <TableHead className="text-right">Invoices</TableHead>
                <TableHead className="text-right">Balance due</TableHead>
                <TableHead className="w-36">Amount applying</TableHead>
                <TableHead className="w-32">Ref # (optional)</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {filtered.map((row) => (
                <TableRow key={row.customerId} className={row.selected ? "bg-emerald-50/50" : "hover:bg-muted/40"}>
                  <TableCell>
                    <input
                      type="checkbox"
                      checked={row.selected}
                      onChange={(e) => updateRow(row.customerId, { selected: e.target.checked })}
                      className="h-4 w-4 rounded"
                    />
                  </TableCell>
                  <TableCell className="font-medium">{row.customerName}</TableCell>
                  <TableCell className="text-sm text-muted-foreground">{row.propertyAddress ?? "—"}</TableCell>
                  <TableCell className="text-right text-sm">
                    <Badge variant="outline">{row.openInvoices.length}</Badge>
                  </TableCell>
                  <TableCell className="text-right font-semibold">
                    {money(row.totalBalance, cur)}
                  </TableCell>
                  <TableCell>
                    <Input
                      type="number"
                      min={0}
                      step="0.01"
                      className="h-8 text-right tabular-nums text-sm"
                      value={row.amountToApply}
                      onChange={(e) => updateRow(row.customerId, { amountToApply: e.target.value, selected: true })}
                    />
                  </TableCell>
                  <TableCell>
                    <Input
                      className="h-8 text-sm"
                      placeholder={payMethod === "check" ? "Check #" : "Ref #"}
                      value={row.reference}
                      onChange={(e) => updateRow(row.customerId, { reference: e.target.value })}
                    />
                  </TableCell>
                </TableRow>
              ))}
              {filtered.length === 0 && (
                <TableRow>
                  <TableCell colSpan={7} className="text-center text-muted-foreground py-10">
                    {rows.length === 0
                      ? "No outstanding invoices — all homeowners are current."
                      : "No homeowners match your search."}
                  </TableCell>
                </TableRow>
              )}
              {filtered.length > 0 && (
                <TableRow className="bg-muted/30 font-semibold border-t-2">
                  <TableCell colSpan={4} className="text-right text-sm">Totals</TableCell>
                  <TableCell className="text-right">{money(filtered.reduce((s, r) => s + r.totalBalance, 0), cur)}</TableCell>
                  <TableCell className="text-right">{money(filtered.reduce((s, r) => s + (parseFloat(r.amountToApply) || 0), 0), cur)}</TableCell>
                  <TableCell />
                </TableRow>
              )}
            </TableBody>
          </Table>
        </CardContent>
      </Card>

      {selected.length > 0 && (
        <div className="flex justify-end">
          <Button size="lg" onClick={recordPayments} disabled={saving} className="bg-emerald-600 hover:bg-emerald-700">
            <DollarSign className="h-4 w-4 mr-1" />
            {saving ? "Recording payments…" : `Record ${selected.length} payment${selected.length !== 1 ? "s" : ""} · ${money(totalSelected, cur)}`}
          </Button>
        </div>
      )}
    </div>
  );
}
