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 { Textarea } from "@/components/ui/textarea";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
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 { Plus, DollarSign, Users, AlertCircle, CheckCircle2, Loader2 } from "lucide-react";
import { toast } from "sonner";
import { money, fmtDate } from "./lib/format";

const STATUS_COLORS: Record<string, string> = {
  draft: "bg-slate-100 text-slate-700",
  posted: "bg-emerald-100 text-emerald-700",
  voided: "bg-red-100 text-red-700",
};

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

  const [open, setOpen] = useState(false);
  const [name, setName] = useState("Monthly HOA Dues");
  const [description, setDescription] = useState("");
  const [amount, setAmount] = useState("");
  const [issueDate, setIssueDate] = useState(new Date().toLocaleDateString("en-CA", { timeZone: "America/New_York" }));
  const [dueDate, setDueDate] = useState("");
  const [incomeAccountId, setIncomeAccountId] = useState("");
  const [selectedHomeowners, setSelectedHomeowners] = useState<Set<string>>(new Set());
  const [saving, setSaving] = useState(false);

  const { data: assessments = [] } = useQuery({
    queryKey: ["assessments", cid],
    enabled: !!cid,
    queryFn: async () =>
      (await accounting.from("assessments").select("*").eq("company_id", cid).order("issue_date", { ascending: false })).data ?? [],
  });

  const { data: homeowners = [] } = useQuery({
    queryKey: ["customers", cid],
    enabled: !!cid,
    queryFn: async () =>
      (await accounting.from("customers").select("id,name,property_address,lot_number,email").eq("company_id", cid).order("name")).data ?? [],
  });

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

  const allSelected = selectedHomeowners.size === (homeowners as any[]).length && (homeowners as any[]).length > 0;

  const toggleAll = () => {
    if (allSelected) {
      setSelectedHomeowners(new Set());
    } else {
      setSelectedHomeowners(new Set((homeowners as any[]).map((h: any) => h.id)));
    }
  };

  const toggleOne = (id: string) => {
    setSelectedHomeowners((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  const resetForm = () => {
    setName("Monthly HOA Dues");
    setDescription("");
    setAmount("");
    setIssueDate(new Date().toLocaleDateString("en-CA", { timeZone: "America/New_York" }));
    setDueDate("");
    setIncomeAccountId("");
    setSelectedHomeowners(new Set((homeowners as any[]).map((h: any) => h.id)));
  };

  const openDialog = () => {
    setSelectedHomeowners(new Set((homeowners as any[]).map((h: any) => h.id)));
    setOpen(true);
  };

  const totalCharge = useMemo(
    () => selectedHomeowners.size * (parseFloat(amount) || 0),
    [selectedHomeowners.size, amount]
  );

  const postAssessment = async () => {
    const amt = parseFloat(amount);
    if (!name.trim()) return toast.error("Name required");
    if (!amt || amt <= 0) return toast.error("Amount must be greater than zero");
    if (selectedHomeowners.size === 0) return toast.error("Select at least one homeowner");

    setSaving(true);
    try {
      // 1. Create assessment record
      const { data: assessment, error: aErr } = await accounting
        .from("assessments")
        .insert({
          company_id: cid,
          name,
          description: description || null,
          amount: amt,
          issue_date: issueDate,
          due_date: dueDate || null,
          income_account_id: incomeAccountId || null,
          status: "posted",
          homeowner_count: selectedHomeowners.size,
          total_charged: totalCharge,
        })
        .select("id")
        .single();
      if (aErr || !assessment) throw new Error(aErr?.message ?? "Failed to create assessment");

      // 2. Generate invoice number prefix
      const prefix = `ASM-${new Date().getFullYear()}-`;

      // 3. Bulk create invoices for each selected homeowner
      let num = 1;
      const failed: string[] = [];
      for (const homeownerId of selectedHomeowners) {
        const hw = (homeowners as any[]).find((h: any) => h.id === homeownerId);
        const invoiceNumber = `${prefix}${String(num).padStart(4, "0")}`;
        const { error: invErr } = await accounting.from("invoices").insert({
          company_id: cid,
          customer_id: homeownerId,
          number: invoiceNumber,
          issue_date: issueDate,
          due_date: dueDate || null,
          status: "sent",
          subtotal: amt,
          tax: 0,
          total: amt,
          notes: `${name}${description ? ` — ${description}` : ""}`,
        });
        if (invErr) failed.push(hw?.name ?? homeownerId);
        else {
          // Update homeowner balance
          await accounting.rpc("increment_account_balance", { acc_id: homeownerId, delta: amt }).maybeSingle();
          num++;
        }
      }

      if (failed.length > 0) {
        toast.warning(`Assessment posted with ${failed.length} errors: ${failed.slice(0, 3).join(", ")}${failed.length > 3 ? "…" : ""}`);
      } else {
        toast.success(`Assessment posted — ${selectedHomeowners.size} invoices created · ${money(totalCharge, cur)} total`);
      }
      setOpen(false);
      resetForm();
      qc.invalidateQueries({ queryKey: ["assessments", cid] });
      qc.invalidateQueries({ queryKey: ["invoices", cid] });
    } catch (e: any) {
      toast.error(e?.message ?? "Failed to post assessment");
    } finally {
      setSaving(false);
    }
  };

  const voidAssessment = async (id: string) => {
    if (!confirm("Void this assessment? This does not delete the invoices already created.")) return;
    await accounting.from("assessments").update({ status: "voided" }).eq("id", id);
    qc.invalidateQueries({ queryKey: ["assessments", cid] });
    toast.success("Assessment voided");
  };

  const totalPosted = (assessments as any[]).filter((a) => a.status === "posted").reduce((s: number, a: any) => s + Number(a.total_charged), 0);

  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">Assessments</h1>
          <p className="text-sm text-muted-foreground">Bulk charge homeowners for dues, special assessments, and fees</p>
        </div>
        <Button onClick={openDialog}>
          <Plus className="h-4 w-4 mr-1" /> Post Assessment
        </Button>
      </div>

      {/* Summary cards */}
      <div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
        <Card>
          <CardContent className="p-4 flex items-center gap-3">
            <DollarSign className="h-8 w-8 text-primary opacity-80" />
            <div>
              <div className="text-xs text-muted-foreground">Total assessed (YTD)</div>
              <div className="text-xl font-semibold">{money(totalPosted, cur)}</div>
            </div>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="p-4 flex items-center gap-3">
            <Users className="h-8 w-8 text-primary opacity-80" />
            <div>
              <div className="text-xs text-muted-foreground">Active homeowners</div>
              <div className="text-xl font-semibold">{(homeowners as any[]).length}</div>
            </div>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="p-4 flex items-center gap-3">
            <CheckCircle2 className="h-8 w-8 text-emerald-600 opacity-80" />
            <div>
              <div className="text-xs text-muted-foreground">Assessments posted</div>
              <div className="text-xl font-semibold">{(assessments as any[]).filter((a) => a.status === "posted").length}</div>
            </div>
          </CardContent>
        </Card>
      </div>

      {/* Assessment history */}
      <Card>
        <CardHeader><CardTitle>Assessment history</CardTitle></CardHeader>
        <CardContent className="p-0">
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>Name</TableHead>
                <TableHead>Issue date</TableHead>
                <TableHead>Due date</TableHead>
                <TableHead className="text-right">Per homeowner</TableHead>
                <TableHead className="text-right">Homeowners</TableHead>
                <TableHead className="text-right">Total charged</TableHead>
                <TableHead>Status</TableHead>
                <TableHead></TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {(assessments as any[]).map((a) => (
                <TableRow key={a.id}>
                  <TableCell className="font-medium">
                    {a.name}
                    {a.description && <div className="text-xs text-muted-foreground">{a.description}</div>}
                  </TableCell>
                  <TableCell>{fmtDate(a.issue_date)}</TableCell>
                  <TableCell>{a.due_date ? fmtDate(a.due_date) : "—"}</TableCell>
                  <TableCell className="text-right">{money(a.amount, cur)}</TableCell>
                  <TableCell className="text-right">{a.homeowner_count}</TableCell>
                  <TableCell className="text-right font-medium">{money(a.total_charged, cur)}</TableCell>
                  <TableCell>
                    <Badge className={`${STATUS_COLORS[a.status] ?? ""} border-0 text-xs`}>{a.status}</Badge>
                  </TableCell>
                  <TableCell>
                    {a.status === "posted" && (
                      <Button size="sm" variant="ghost" className="text-destructive hover:text-destructive text-xs" onClick={() => voidAssessment(a.id)}>
                        Void
                      </Button>
                    )}
                  </TableCell>
                </TableRow>
              ))}
              {assessments.length === 0 && (
                <TableRow>
                  <TableCell colSpan={8} className="text-center text-muted-foreground py-10">
                    No assessments yet. Click "Post Assessment" to charge homeowners.
                  </TableCell>
                </TableRow>
              )}
            </TableBody>
          </Table>
        </CardContent>
      </Card>

      {/* Post assessment dialog */}
      <Dialog open={open} onOpenChange={(o) => { if (!o) resetForm(); setOpen(o); }}>
        <DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>Post Assessment</DialogTitle>
          </DialogHeader>

          <div className="space-y-4">
            <div className="grid grid-cols-2 gap-3">
              <div className="col-span-2">
                <Label>Assessment name *</Label>
                <Input value={name} onChange={(e) => setName(e.target.value)} placeholder="Monthly HOA Dues" />
              </div>
              <div className="col-span-2">
                <Label>Description</Label>
                <Textarea rows={2} value={description} onChange={(e) => setDescription(e.target.value)} placeholder="Optional detail shown on invoice" />
              </div>
              <div>
                <Label>Amount per homeowner *</Label>
                <Input type="number" min={0} step="0.01" placeholder="0.00" value={amount} onChange={(e) => setAmount(e.target.value)} />
              </div>
              <div>
                <Label>Income account</Label>
                <Select value={incomeAccountId} onValueChange={setIncomeAccountId}>
                  <SelectTrigger><SelectValue placeholder="Select account (optional)" /></SelectTrigger>
                  <SelectContent>
                    {(incomeAccounts as any[]).map((a) => (
                      <SelectItem key={a.id} value={a.id}>{a.code ? `${a.code} · ` : ""}{a.name}</SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>
              <div>
                <Label>Issue date *</Label>
                <Input type="date" value={issueDate} onChange={(e) => setIssueDate(e.target.value)} />
              </div>
              <div>
                <Label>Due date</Label>
                <Input type="date" value={dueDate} onChange={(e) => setDueDate(e.target.value)} />
              </div>
            </div>

            {/* Homeowner selector */}
            <div>
              <div className="flex items-center justify-between mb-2">
                <Label>Select homeowners ({selectedHomeowners.size} of {(homeowners as any[]).length})</Label>
                <Button size="sm" variant="outline" onClick={toggleAll}>
                  {allSelected ? "Deselect all" : "Select all"}
                </Button>
              </div>
              <div className="border rounded-md max-h-48 overflow-y-auto">
                {(homeowners as any[]).map((h: any) => (
                  <label key={h.id} className="flex items-center gap-3 px-3 py-2 hover:bg-muted/50 cursor-pointer border-b last:border-0">
                    <input
                      type="checkbox"
                      checked={selectedHomeowners.has(h.id)}
                      onChange={() => toggleOne(h.id)}
                      className="rounded"
                    />
                    <div className="flex-1 min-w-0">
                      <div className="text-sm font-medium">{h.name}</div>
                      {h.property_address && <div className="text-xs text-muted-foreground truncate">{h.property_address}{h.lot_number ? ` · Lot ${h.lot_number}` : ""}</div>}
                    </div>
                  </label>
                ))}
                {(homeowners as any[]).length === 0 && (
                  <div className="px-3 py-4 text-sm text-muted-foreground text-center">No homeowners found</div>
                )}
              </div>
            </div>

            {/* Summary */}
            {parseFloat(amount) > 0 && selectedHomeowners.size > 0 && (
              <div className="rounded-md bg-primary/5 border border-primary/20 px-4 py-3">
                <div className="flex items-center gap-2 text-sm">
                  <AlertCircle className="h-4 w-4 text-primary shrink-0" />
                  <span>
                    Posting will create <strong>{selectedHomeowners.size} invoices</strong> for{" "}
                    <strong>{money(parseFloat(amount), cur)}</strong> each ={" "}
                    <strong>{money(totalCharge, cur)}</strong> total
                  </span>
                </div>
              </div>
            )}
          </div>

          <DialogFooter>
            <Button variant="outline" onClick={() => setOpen(false)}>Cancel</Button>
            <Button onClick={postAssessment} disabled={saving || !amount || selectedHomeowners.size === 0}>
              {saving ? "Posting…" : `Post — ${money(totalCharge, cur)}`}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
