import { Link, useParams } from "react-router-dom";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useEffect, 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 { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from "@/components/ui/table";
import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@/components/ui/sheet";
import { Badge } from "@/components/ui/badge";
import { ArrowLeft, Download, Mail, FileText, Pencil, Check, X } from "lucide-react";
import { toast } from "sonner";
import { money, fmtDate } from "./lib/format";
import { generateLedgerStatement } from "@/components/unit-profile/UnitLedgerStatementPDF";

function today() {
  return new Date().toLocaleDateString("en-CA", { timeZone: "America/New_York" });
}

type LedgerRow = {
  date: string;
  type: string;
  ref: string;
  description: string;
  debit: number;
  credit: number;
  sourceId: string;
  sourceKind: "invoice" | "payment";
  dueDate?: string | null;
};

export default function AccountingCustomerDetailPage() {
  const { id = "" } = useParams();
  const [tab, setTab] = useState("overview");
  const { companyId, associationName } = useCompanyId();
  const cid = companyId ?? "";
  const cur = "USD";
  const qc = useQueryClient();
  // Default the ledger/statement to the full history so it matches the main-app
  // owner ledger (all-time). Set to the earliest transaction once data loads;
  // the user can still narrow the range. "" means "no lower bound" (show all).
  const [from, setFrom] = useState("");
  const [fromTouched, setFromTouched] = useState(false);
  const [to, setTo] = useState(today());
  const [toTouched, setToTouched] = useState(false);
  const [drawer, setDrawer] = useState<LedgerRow | null>(null);
  const [editing, setEditing] = useState(false);
  const [editForm, setEditForm] = useState<any>(null);
  const [saving, setSaving] = useState(false);

  const { data: homeowner } = useQuery({
    queryKey: ["customer", id],
    enabled: !!id,
    queryFn: async () => {
      const { data } = await accounting.from("customers").select("*").eq("id", id).maybeSingle();
      return data;
    },
  });

  const { data: invoices = [] } = useQuery({
    queryKey: ["customer-invoices", id],
    enabled: !!id && !!cid,
    queryFn: async () => {
      const { data } = await accounting
        .from("invoices")
        .select("id,number,issue_date,due_date,total,paid_amount,status,updated_at,notes,external_source")
        .eq("company_id", cid)
        .eq("customer_id", id)
        .order("issue_date", { ascending: true });
      return data ?? [];
    },
  });

  // Payments recorded against this homeowner (incl. those synced from the main
  // app's owner ledger). Shown as real ledger credits so dates/amounts are exact.
  const { data: payments = [] } = useQuery({
    queryKey: ["customer-payments", id],
    enabled: !!id && !!cid,
    queryFn: async () => {
      const { data } = await accounting
        .from("payments_received")
        .select("id,payment_date,amount,method,reference,memo,deposited")
        .eq("company_id", cid)
        .eq("customer_id", id)
        .order("payment_date", { ascending: true });
      return data ?? [];
    },
  });

  const allRows = useMemo<LedgerRow[]>(() => {
    const rows: LedgerRow[] = [];
    for (const inv of invoices as any[]) {
      const total = Number(inv.total ?? 0);
      const paid = Number(inv.paid_amount ?? 0);
      if (total > 0) {
        rows.push({
          date: inv.issue_date,
          type: "Invoice",
          ref: inv.number,
          description: inv.notes ? `Invoice ${inv.number} — ${inv.notes}` : `Invoice ${inv.number}`,
          debit: total,
          credit: 0,
          sourceId: inv.id,
          sourceKind: "invoice",
          dueDate: inv.due_date,
        });
      }
      // Manual invoices track payment via paid_amount (no payments_received row).
      // Synced ledger payments are rendered from payments_received below, so skip
      // their paid_amount here to avoid double-counting.
      if (paid > 0 && inv.external_source !== "acmacc_ledger") {
        rows.push({
          date: (inv.updated_at ?? inv.issue_date).slice(0, 10),
          type: "Payment",
          ref: `PMT-${inv.number}`,
          description: `Payment received on Invoice ${inv.number}`,
          debit: 0,
          credit: paid,
          sourceId: inv.id,
          sourceKind: "payment",
        });
      }
    }
    for (const p of payments as any[]) {
      rows.push({
        date: p.payment_date,
        type: "Payment",
        ref: p.reference || "Payment",
        description: [p.method, p.memo].filter(Boolean).join(" · ") || "Payment received",
        debit: 0,
        credit: Number(p.amount ?? 0),
        sourceId: p.id,
        sourceKind: "payment",
      });
    }
    rows.sort((a, b) => a.date.localeCompare(b.date));
    return rows;
  }, [invoices, payments]);

  // Default the "From" date to the earliest entry so the full ledger shows
  // (matches the main-app owner ledger). Honors a user-chosen range thereafter.
  useEffect(() => {
    if (!fromTouched && !from && allRows.length) setFrom(allRows[0].date);
  }, [allRows, fromTouched, from]);

  // Extend "To" to the latest entry if it's beyond today, so recently-dated
  // payments (e.g. an invoice marked paid today) aren't filtered out.
  useEffect(() => {
    if (toTouched || !allRows.length) return;
    const latest = allRows[allRows.length - 1].date;
    if (latest > to) setTo(latest);
  }, [allRows, toTouched, to]);

  const openingBalance = useMemo(
    () => allRows.filter((r) => r.date < from).reduce((s, r) => s + r.debit - r.credit, 0),
    [allRows, from]
  );

  const periodRows = useMemo(
    () => allRows.filter((r) => r.date >= from && r.date <= to),
    [allRows, from, to]
  );

  const withRunning = useMemo(() => {
    let bal = openingBalance;
    return periodRows.map((r) => {
      bal += r.debit - r.credit;
      return { ...r, running: bal };
    });
  }, [periodRows, openingBalance]);

  const currentBalance = useMemo(
    () => allRows.reduce((s, r) => s + r.debit - r.credit, 0),
    [allRows]
  );

  const totalInvoiced = periodRows.reduce((s, r) => s + r.debit, 0);
  const totalPaid = periodRows.reduce((s, r) => s + r.credit, 0);
  const creditBalance = currentBalance < 0 ? Math.abs(currentBalance) : 0;
  const outstanding = currentBalance > 0 ? currentBalance : 0;
  const lastPayment = [...allRows].reverse().find((r) => r.credit > 0);

  const aging = useMemo(() => {
    const buckets = { current: 0, d30: 0, d60: 0, d90: 0, d90p: 0 };
    const now = new Date();
    for (const inv of invoices as any[]) {
      const open = Number(inv.total ?? 0) - Number(inv.paid_amount ?? 0);
      if (open <= 0) continue;
      const due = inv.due_date ? new Date(inv.due_date) : new Date(inv.issue_date);
      const days = Math.floor((now.getTime() - due.getTime()) / 86400000);
      if (days <= 0) buckets.current += open;
      else if (days <= 30) buckets.d30 += open;
      else if (days <= 60) buckets.d60 += open;
      else if (days <= 90) buckets.d90 += open;
      else buckets.d90p += open;
    }
    return buckets;
  }, [invoices]);

  const overdue = aging.d30 + aging.d60 + aging.d90 + aging.d90p > 0;

  const startEditing = () => {
    if (!homeowner) return;
    setEditForm({
      name: homeowner.name ?? "",
      email: homeowner.email ?? "",
      phone: homeowner.phone ?? "",
      account_number: homeowner.account_number ?? "",
      unit_id: homeowner.unit_id ?? "",
      property_address: homeowner.property_address ?? "",
      lot_number: homeowner.lot_number ?? "",
      unit_number: homeowner.unit_number ?? "",
      mailing_address: homeowner.mailing_address ?? "",
      move_in_date: homeowner.move_in_date ?? "",
    });
    setEditing(true);
  };

  const cancelEditing = () => {
    setEditing(false);
    setEditForm(null);
  };

  const saveEdit = async () => {
    if (!editForm.name.trim()) return toast.error("Name required");
    setSaving(true);
    const { error } = await accounting.from("customers").update({
      name: editForm.name,
      email: editForm.email || null,
      phone: editForm.phone || null,
      account_number: editForm.account_number.trim() || null,
      unit_id: editForm.unit_id.trim() || null,
      property_address: editForm.property_address || null,
      lot_number: editForm.lot_number || null,
      unit_number: editForm.unit_number || null,
      mailing_address: editForm.mailing_address || null,
      move_in_date: editForm.move_in_date || null,
      billing_address: editForm.mailing_address || editForm.property_address || null,
    }).eq("id", id);
    setSaving(false);
    if (error) return toast.error(error.message);
    toast.success("Homeowner updated");
    setEditing(false);
    setEditForm(null);
    qc.invalidateQueries({ queryKey: ["customer", id] });
    qc.invalidateQueries({ queryKey: ["customers", cid] });
  };

  const exportStatement = () => {
    if (!homeowner) return;
    if (!allRows.length) { toast.error("No ledger activity to export"); return; }
    // Use the same account-statement layout as the main-app owner ledger
    // (account holder, amounts-due breakdown, categorized columns, no cover).
    const entries = allRows.map((r) => ({
      date: r.date,
      debit: r.debit,
      credit: r.credit,
      transaction_type: r.credit > 0 ? "payment" : (r.description || ""),
      description: r.description,
    }));
    generateLedgerStatement({
      unitData: {
        unit_number: homeowner.unit_number,
        address: homeowner.property_address,
        account_number: homeowner.account_number,
      },
      owners: [{ is_primary: true, first_name: homeowner.name, last_name: "" }],
      entries,
      associationName: associationName ?? "Association",
    });
  };

  const emailStatement = () => {
    if (!homeowner) return;
    exportStatement();
    const subject = encodeURIComponent(`Statement from ${associationName ?? "us"}`);
    const body = encodeURIComponent(
      `Hello ${homeowner.name},\n\nPlease find attached your homeowner statement for the period ${fmtDate(from)} – ${fmtDate(to)}.\nCurrent balance due: ${money(currentBalance, cur)}.\n\nThank you.`
    );
    window.location.href = `mailto:${homeowner.email ?? ""}?subject=${subject}&body=${body}`;
    toast.info("Statement downloaded — attach it to the email window.");
  };

  if (!homeowner) return <div className="p-6 text-muted-foreground">Loading homeowner…</div>;

  return (
    <div className="space-y-6">
      <div className="flex items-center gap-3">
        <Button variant="ghost" size="sm" asChild>
          <Link to="/dashboard/accounting/customers"><ArrowLeft className="h-4 w-4 mr-1" /> Homeowners</Link>
        </Button>
        <div>
          <h1 className="text-2xl font-semibold">{homeowner.name}</h1>
          {homeowner.property_address && (
            <p className="text-sm text-muted-foreground">
              {homeowner.property_address}
              {homeowner.unit_number ? `, ${homeowner.unit_number}` : ""}
              {homeowner.lot_number ? ` · Lot ${homeowner.lot_number}` : ""}
            </p>
          )}
        </div>
      </div>

      <Tabs value={tab} onValueChange={setTab}>
        <TabsList>
          <TabsTrigger value="overview">Overview</TabsTrigger>
          <TabsTrigger value="invoices">Invoices</TabsTrigger>
          <TabsTrigger value="ledger">Ledger</TabsTrigger>
        </TabsList>

        {/* ── Overview tab ── */}
        <TabsContent value="overview" className="mt-4">
          <Card>
            <CardHeader className="flex flex-row items-center justify-between">
              <CardTitle>Homeowner info</CardTitle>
              {!editing ? (
                <Button size="sm" variant="outline" onClick={startEditing}>
                  <Pencil className="h-3.5 w-3.5 mr-1" /> Edit
                </Button>
              ) : (
                <div className="flex gap-2">
                  <Button size="sm" variant="ghost" onClick={cancelEditing} disabled={saving}>
                    <X className="h-3.5 w-3.5 mr-1" /> Cancel
                  </Button>
                  <Button size="sm" onClick={saveEdit} disabled={saving}>
                    <Check className="h-3.5 w-3.5 mr-1" /> Save
                  </Button>
                </div>
              )}
            </CardHeader>
            <CardContent>
              {editing && editForm ? (
                <div className="grid grid-cols-2 gap-4">
                  <div className="col-span-2">
                    <Label>Full name *</Label>
                    <Input value={editForm.name} onChange={(e) => setEditForm({ ...editForm, name: e.target.value })} />
                  </div>
                  <div>
                    <Label>Email</Label>
                    <Input type="email" value={editForm.email} onChange={(e) => setEditForm({ ...editForm, email: e.target.value })} />
                  </div>
                  <div>
                    <Label>Phone</Label>
                    <Input value={editForm.phone} onChange={(e) => setEditForm({ ...editForm, phone: e.target.value })} />
                  </div>
                  <div>
                    <Label>Account number</Label>
                    <Input value={editForm.account_number} onChange={(e) => setEditForm({ ...editForm, account_number: e.target.value })} />
                  </div>
                  <div>
                    <Label>Unit ID</Label>
                    <Input value={editForm.unit_id} onChange={(e) => setEditForm({ ...editForm, unit_id: e.target.value })} />
                  </div>
                  <div className="col-span-2">
                    <Label>Property address</Label>
                    <Input value={editForm.property_address} onChange={(e) => setEditForm({ ...editForm, property_address: e.target.value })} />
                  </div>
                  <div>
                    <Label>Lot number</Label>
                    <Input value={editForm.lot_number} onChange={(e) => setEditForm({ ...editForm, lot_number: e.target.value })} />
                  </div>
                  <div>
                    <Label>Unit / Apt</Label>
                    <Input value={editForm.unit_number} onChange={(e) => setEditForm({ ...editForm, unit_number: e.target.value })} />
                  </div>
                  <div className="col-span-2">
                    <Label>Mailing address <span className="text-muted-foreground text-xs">(if different from property)</span></Label>
                    <Input value={editForm.mailing_address} onChange={(e) => setEditForm({ ...editForm, mailing_address: e.target.value })} />
                  </div>
                  <div>
                    <Label>Move-in date</Label>
                    <Input type="date" value={editForm.move_in_date} onChange={(e) => setEditForm({ ...editForm, move_in_date: e.target.value })} />
                  </div>
                </div>
              ) : (
                <div className="grid grid-cols-2 gap-4 text-sm">
                  <div>
                    <div className="text-muted-foreground">Email</div>
                    <div>{homeowner.email ? <a href={`mailto:${homeowner.email}`} className="text-primary hover:underline">{homeowner.email}</a> : "—"}</div>
                  </div>
                  <div>
                    <div className="text-muted-foreground">Phone</div>
                    <div>{homeowner.phone ? <a href={`tel:${homeowner.phone}`} className="hover:underline">{homeowner.phone}</a> : "—"}</div>
                  </div>
                  <div>
                    <div className="text-muted-foreground">Account number</div>
                    <div>{homeowner.account_number ?? "—"}</div>
                  </div>
                  <div>
                    <div className="text-muted-foreground">Unit ID</div>
                    <div>{homeowner.unit_id ?? "—"}</div>
                  </div>
                  <div className="col-span-2">
                    <div className="text-muted-foreground">Property address</div>
                    <div>{homeowner.property_address ?? "—"}{homeowner.unit_number ? `, ${homeowner.unit_number}` : ""}</div>
                  </div>
                  <div>
                    <div className="text-muted-foreground">Lot number</div>
                    <div>{homeowner.lot_number ?? "—"}</div>
                  </div>
                  <div>
                    <div className="text-muted-foreground">Move-in date</div>
                    <div>{homeowner.move_in_date ? fmtDate(homeowner.move_in_date) : "—"}</div>
                  </div>
                  {homeowner.mailing_address && (
                    <div className="col-span-2">
                      <div className="text-muted-foreground">Mailing address</div>
                      <div>{homeowner.mailing_address}</div>
                    </div>
                  )}
                  <div>
                    <div className="text-muted-foreground">Current balance</div>
                    <div className="font-semibold">{money(homeowner.balance, cur)}</div>
                  </div>
                  <div>
                    <div className="text-muted-foreground">Open invoices</div>
                    <div>{(invoices as any[]).filter(i => Number(i.total) - Number(i.paid_amount ?? 0) > 0).length}</div>
                  </div>
                </div>
              )}
            </CardContent>
          </Card>
        </TabsContent>

        {/* ── Invoices tab ── */}
        <TabsContent value="invoices" className="mt-4">
          <Card>
            <CardContent className="p-0">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>#</TableHead>
                    <TableHead>Issue</TableHead>
                    <TableHead>Due</TableHead>
                    <TableHead>Status</TableHead>
                    <TableHead className="text-right">Total</TableHead>
                    <TableHead className="text-right">Paid</TableHead>
                    <TableHead className="text-right">Open</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {(invoices as any[]).map((i) => {
                    const open = Number(i.total) - Number(i.paid_amount ?? 0);
                    return (
                      <TableRow key={i.id}>
                        <TableCell className="font-medium">{i.number}</TableCell>
                        <TableCell>{fmtDate(i.issue_date)}</TableCell>
                        <TableCell>{fmtDate(i.due_date)}</TableCell>
                        <TableCell><Badge variant="outline">{i.status}</Badge></TableCell>
                        <TableCell className="text-right">{money(i.total, cur)}</TableCell>
                        <TableCell className="text-right">{money(i.paid_amount, cur)}</TableCell>
                        <TableCell className="text-right">{money(open, cur)}</TableCell>
                      </TableRow>
                    );
                  })}
                  {(invoices as any[]).length === 0 && (
                    <TableRow>
                      <TableCell colSpan={7} className="text-center text-muted-foreground">No invoices.</TableCell>
                    </TableRow>
                  )}
                </TableBody>
              </Table>
            </CardContent>
          </Card>
        </TabsContent>

        {/* ── Ledger tab ── */}
        <TabsContent value="ledger" className="mt-4 space-y-4">
          <div className="grid grid-cols-2 md:grid-cols-5 gap-3">
            <SummaryStat label="Total Charged" value={money(totalInvoiced, cur)} />
            <SummaryStat label="Total Paid" value={money(totalPaid, cur)} />
            <SummaryStat label="Outstanding" value={money(outstanding, cur)} className={overdue ? "text-destructive" : ""} />
            <SummaryStat label="Credit Balance" value={money(creditBalance, cur)} />
            <SummaryStat label="Last Payment" value={lastPayment ? `${money(lastPayment.credit, cur)} · ${fmtDate(lastPayment.date)}` : "—"} />
          </div>

          <Card>
            <CardContent className="p-4 flex flex-wrap items-end gap-3">
              <div><Label className="text-xs">From</Label><Input type="date" value={from} onChange={(e) => { setFromTouched(true); setFrom(e.target.value); }} className="w-40" /></div>
              <div><Label className="text-xs">To</Label><Input type="date" value={to} onChange={(e) => { setToTouched(true); setTo(e.target.value); }} className="w-40" /></div>
              <div className="ml-auto flex gap-2">
                <Button variant="outline" onClick={exportStatement}><Download className="h-4 w-4 mr-1" /> Export Statement</Button>
                <Button variant="outline" onClick={emailStatement}><Mail className="h-4 w-4 mr-1" /> Email Statement</Button>
              </div>
            </CardContent>
          </Card>

          <Card>
            <CardContent className="p-0">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>Date</TableHead>
                    <TableHead>Type</TableHead>
                    <TableHead>Ref #</TableHead>
                    <TableHead>Description</TableHead>
                    <TableHead className="text-right">Charges</TableHead>
                    <TableHead className="text-right">Payments</TableHead>
                    <TableHead className="text-right">Running Balance</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  <TableRow className="bg-muted/40">
                    <TableCell>{fmtDate(from)}</TableCell>
                    <TableCell colSpan={3} className="italic text-muted-foreground">Opening Balance</TableCell>
                    <TableCell /><TableCell />
                    <TableCell className="text-right font-medium">{money(openingBalance, cur)}</TableCell>
                  </TableRow>
                  {withRunning.map((r, idx) => {
                    const isOverdue = r.dueDate && new Date(r.dueDate) < new Date() && r.running > 0;
                    return (
                      <TableRow key={idx}>
                        <TableCell>{fmtDate(r.date)}</TableCell>
                        <TableCell>{r.type}</TableCell>
                        <TableCell>
                          <button className="text-primary hover:underline" onClick={() => setDrawer(r)}>{r.ref}</button>
                        </TableCell>
                        <TableCell className="max-w-[300px] truncate">{r.description}</TableCell>
                        <TableCell className="text-right">{r.debit ? money(r.debit, cur) : ""}</TableCell>
                        <TableCell className="text-right">{r.credit ? money(r.credit, cur) : ""}</TableCell>
                        <TableCell className={`text-right ${isOverdue ? "text-destructive font-medium" : ""}`}>{money(r.running, cur)}</TableCell>
                      </TableRow>
                    );
                  })}
                  {withRunning.length === 0 && (
                    <TableRow>
                      <TableCell colSpan={7} className="text-center text-muted-foreground">No transactions in this period.</TableCell>
                    </TableRow>
                  )}
                  <TableRow className="bg-muted">
                    <TableCell colSpan={6} className="font-bold">Current Balance</TableCell>
                    <TableCell className={`text-right font-bold ${overdue ? "text-destructive" : ""}`}>{money(currentBalance, cur)}</TableCell>
                  </TableRow>
                </TableBody>
              </Table>
              <div className="p-4 border-t flex flex-wrap gap-2 items-center">
                <span className="text-xs text-muted-foreground mr-2">Aging:</span>
                <AgingPill label="Current" amount={aging.current} cur={cur} tone="emerald" />
                <AgingPill label="1–30" amount={aging.d30} cur={cur} tone="amber" />
                <AgingPill label="31–60" amount={aging.d60} cur={cur} tone="orange" />
                <AgingPill label="61–90" amount={aging.d90} cur={cur} tone="rose" />
                <AgingPill label="90+" amount={aging.d90p} cur={cur} tone="red" />
              </div>
            </CardContent>
          </Card>
        </TabsContent>
      </Tabs>

      <Sheet open={!!drawer} onOpenChange={(o) => !o && setDrawer(null)}>
        <SheetContent>
          <SheetHeader><SheetTitle>{drawer?.type} · {drawer?.ref}</SheetTitle></SheetHeader>
          {drawer && (
            <div className="mt-4 space-y-3 text-sm">
              <div><div className="text-muted-foreground">Date</div><div>{fmtDate(drawer.date)}</div></div>
              <div><div className="text-muted-foreground">Description</div><div>{drawer.description}</div></div>
              {drawer.debit > 0 && <div><div className="text-muted-foreground">Charge</div><div className="font-medium">{money(drawer.debit, cur)}</div></div>}
              {drawer.credit > 0 && <div><div className="text-muted-foreground">Payment</div><div className="font-medium">{money(drawer.credit, cur)}</div></div>}
              <Button asChild className="mt-2"><Link to="/dashboard/accounting/invoices"><FileText className="h-4 w-4 mr-1" /> Open in Invoices</Link></Button>
            </div>
          )}
        </SheetContent>
      </Sheet>
    </div>
  );
}

function SummaryStat({ label, value, className = "" }: { label: string; value: string; className?: string }) {
  return (
    <Card><CardContent className="p-4">
      <div className="text-xs text-muted-foreground">{label}</div>
      <div className={`text-lg font-semibold ${className}`}>{value}</div>
    </CardContent></Card>
  );
}

function AgingPill({ label, amount, cur, tone }: { label: string; amount: number; cur: string; tone: string }) {
  const toneMap: Record<string, string> = {
    emerald: "bg-emerald-100 text-emerald-900",
    amber: "bg-amber-100 text-amber-900",
    orange: "bg-orange-100 text-orange-900",
    rose: "bg-rose-100 text-rose-900",
    red: "bg-red-200 text-red-900",
  };
  return (
    <span className={`px-2 py-1 rounded-full text-xs ${toneMap[tone]}`}>
      {label}: {money(amount, cur)}
    </span>
  );
}
