import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useState } from "react";
import { accounting } from "@/lib/accountingClient";
import { supabase } from "@/integrations/supabase/client";
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, DialogTrigger, 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 { Checkbox } from "@/components/ui/checkbox";
import { Plus, Trash2, Upload, FileText, Wallet, Loader2 } from "lucide-react";
import { toast } from "sonner";
import { money, fmtDate } from "./lib/format";
import { EmptyState } from "./components/EmptyState";
import { TableSkeleton } from "./components/TableSkeleton";
import { handlePayment, applyPaymentToBill } from "./lib/autoBill";
import { MatchBillDialog } from "./components/MatchBillDialog";

const CATEGORIES = [
  "Advertising", "Travel", "Meals & Entertainment", "Office Supplies",
  "Software", "Utilities", "Rent", "Payroll", "Professional Services",
  "Equipment", "Insurance", "Bank Fees", "Other",
];

const CURRENCIES = ["USD", "EUR", "GBP", "CAD", "AUD", "INR", "JPY"];

export default function AccountingExpensesPage() {
  const { companyId, loading: companyLoading, error: companyError, associationId } = useCompanyId();
  const cid = companyId ?? "";
  const cur = "USD";
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const [uploading, setUploading] = useState(false);

  const [date, setDate] = useState(new Date().toLocaleDateString("en-CA", { timeZone: "America/New_York" }));
  const [category, setCategory] = useState("");
  const [vendorId, setVendorId] = useState<string>("");
  const [vendorName, setVendorName] = useState("");
  const [amount, setAmount] = useState<number>(0);
  const [currency, setCurrency] = useState(cur);
  const [paidThrough, setPaidThrough] = useState<string>("");
  const [reimbursable, setReimbursable] = useState(false);
  const [receiptUrl, setReceiptUrl] = useState("");
  const [notes, setNotes] = useState("");
  const [matchOpen, setMatchOpen] = useState(false);
  const [matchCandidates, setMatchCandidates] = useState<any[]>([]);
  const [pendingPayment, setPendingPayment] = useState<{ amount: number; vendorId: string; date: string; category: string; sourceId: string } | null>(null);

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

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

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

  const reset = () => {
    setDate(new Date().toLocaleDateString("en-CA", { timeZone: "America/New_York" }));
    setCategory(""); setVendorId(""); setVendorName(""); setAmount(0);
    setCurrency(cur); setPaidThrough("");
    setReimbursable(false); setReceiptUrl(""); setNotes("");
  };

  const uploadReceipt = async (file: File) => {
    if (file.size > 10 * 1024 * 1024) return toast.error("File must be under 10MB");
    setUploading(true);
    const path = `${cid}/${Date.now()}-${file.name}`;
    const { error } = await supabase.storage.from("receipts").upload(path, file);
    setUploading(false);
    if (error) return toast.error(error.message);
    const { data } = supabase.storage.from("receipts").getPublicUrl(path);
    setReceiptUrl(data.publicUrl);
    toast.success("Receipt uploaded");
  };

  const save = async () => {
    if (!category) return toast.error("Category is required");
    if (!amount || amount <= 0) return toast.error("Amount must be greater than 0");
    const selectedVendor = (vendors as any[]).find((v: any) => v.id === vendorId);
    const { data: inserted, error } = await accounting.from("expenses").insert({
      company_id: cid, date, category,
      vendor_id: vendorId || null,
      vendor_name: selectedVendor?.name ?? vendorName ?? null,
      amount, currency,
      paid_through_account_id: paidThrough || null,
      reimbursable, receipt_url: receiptUrl || null,
      notes: notes || null,
    }).select("id").single();
    if (error || !inserted) return toast.error(error?.message ?? "Failed");
    toast.success("Expense recorded");
    setOpen(false);
    reset();
    qc.invalidateQueries({ queryKey: ["expenses", cid] });

    // Auto-bill creation
    if (vendorId) {
      const result = await handlePayment({
        companyId: cid, vendorId, amount, date,
        category, description: notes,
        sourceKind: "expense", sourceId: inserted.id,
      });
      if (result.kind === "created") {
        toast.warning(`No existing bill found — a bill was automatically created and marked as paid for ${selectedVendor?.name ?? "vendor"}.`, {
          action: { label: "View Bill", onClick: () => window.location.assign("/dashboard/accounting/bills") },
          duration: 8000,
        });
        qc.invalidateQueries({ queryKey: ["bills", cid] });
      } else if (result.kind === "matched") {
        setMatchCandidates(result.candidates);
        setPendingPayment({ amount, vendorId, date, category, sourceId: inserted.id });
        setMatchOpen(true);
      }
    }
  };

  const remove = async (id: string) => {
    await accounting.from("expenses").delete().eq("id", id);
    qc.invalidateQueries({ queryKey: ["expenses", cid] });
  };

  const total = (expenses as any[]).reduce((s: number, e: any) => s + Number(e.amount), 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">Expenses</h1>
          <p className="text-sm text-muted-foreground">{(expenses as any[]).length} expenses · {money(total, cur)} total</p>
        </div>
        <Dialog open={open} onOpenChange={(v) => { setOpen(v); if (!v) reset(); }}>
          <DialogTrigger asChild>
            <Button><Plus className="mr-1 h-4 w-4" /> New Expense</Button>
          </DialogTrigger>
          <DialogContent className="max-w-2xl">
            <DialogHeader><DialogTitle>Record expense</DialogTitle></DialogHeader>
            <div className="space-y-4">
              <div className="grid grid-cols-2 gap-3">
                <div>
                  <Label>Date</Label>
                  <Input type="date" value={date} onChange={(e) => setDate(e.target.value)} />
                </div>
                <div>
                  <Label>Category</Label>
                  <Select value={category} onValueChange={setCategory}>
                    <SelectTrigger><SelectValue placeholder="Select category" /></SelectTrigger>
                    <SelectContent>{CATEGORIES.map(c => <SelectItem key={c} value={c}>{c}</SelectItem>)}</SelectContent>
                  </Select>
                </div>
                <div>
                  <Label>Vendor</Label>
                  <Select value={vendorId} onValueChange={setVendorId}>
                    <SelectTrigger><SelectValue placeholder="Select vendor (optional)" /></SelectTrigger>
                    <SelectContent>{(vendors as any[]).map((v: any) => <SelectItem key={v.id} value={v.id}>{v.name}</SelectItem>)}</SelectContent>
                  </Select>
                  {!vendorId && (
                    <Input className="mt-2" placeholder="Or type vendor name" maxLength={120} value={vendorName} onChange={(e) => setVendorName(e.target.value)} />
                  )}
                </div>
                <div>
                  <Label>Paid through</Label>
                  <Select value={paidThrough} onValueChange={setPaidThrough}>
                    <SelectTrigger><SelectValue placeholder="Bank / cash / card" /></SelectTrigger>
                    <SelectContent>{(accounts as any[]).map((a: any) => <SelectItem key={a.id} value={a.id}>{a.name}</SelectItem>)}</SelectContent>
                  </Select>
                </div>
                <div>
                  <Label>Amount</Label>
                  <Input type="number" min={0} step="0.01" value={amount} onChange={(e) => setAmount(Number(e.target.value))} />
                </div>
                <div>
                  <Label>Currency</Label>
                  <Select value={currency} onValueChange={setCurrency}>
                    <SelectTrigger><SelectValue /></SelectTrigger>
                    <SelectContent>{CURRENCIES.map(c => <SelectItem key={c} value={c}>{c}</SelectItem>)}</SelectContent>
                  </Select>
                </div>
              </div>

              <div>
                <Label>Receipt</Label>
                <label className="mt-1 flex cursor-pointer items-center justify-center gap-2 rounded-md border-2 border-dashed border-border bg-muted/30 px-4 py-6 text-sm text-muted-foreground hover:bg-muted/50">
                  <Upload className="h-4 w-4" />
                  {uploading ? "Uploading…" : receiptUrl ? "Replace receipt" : "Click to upload receipt (PDF or image, max 10MB)"}
                  <input type="file" className="hidden" accept="image/*,.pdf" onChange={(e) => e.target.files?.[0] && uploadReceipt(e.target.files[0])} />
                </label>
                {receiptUrl && (
                  <a href={receiptUrl} target="_blank" rel="noreferrer" className="mt-2 inline-flex items-center gap-1 text-xs text-primary hover:underline">
                    <FileText className="h-3 w-3" /> View uploaded receipt
                  </a>
                )}
              </div>

              <div>
                <Label>Notes</Label>
                <Textarea maxLength={500} value={notes} onChange={(e) => setNotes(e.target.value)} placeholder="Optional notes" />
              </div>

              <label className="flex items-center gap-2 text-sm">
                <Checkbox checked={reimbursable} onCheckedChange={(v) => setReimbursable(!!v)} />
                Reimbursable
              </label>
            </div>
            <DialogFooter><Button onClick={save}>Save expense</Button></DialogFooter>
          </DialogContent>
        </Dialog>
      </div>

      <Card>
        <CardHeader><CardTitle>All expenses</CardTitle></CardHeader>
        <CardContent>
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>Date</TableHead>
                <TableHead>Category</TableHead>
                <TableHead>Vendor</TableHead>
                <TableHead>Paid through</TableHead>
                <TableHead className="text-right">Amount</TableHead>
                <TableHead>Reimbursable</TableHead>
                <TableHead>Receipt</TableHead>
                <TableHead></TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {isLoading && <TableSkeleton columns={8} />}
              {!isLoading && (expenses as any[]).map((e: any) => (
                <TableRow key={e.id}>
                  <TableCell>{fmtDate(e.date)}</TableCell>
                  <TableCell><Badge variant="outline">{e.category}</Badge></TableCell>
                  <TableCell>{e.vendors?.name ?? e.vendor_name ?? "—"}</TableCell>
                  <TableCell>{e.accounts?.name ?? "—"}</TableCell>
                  <TableCell className="text-right font-medium">{money(e.amount, e.currency)}</TableCell>
                  <TableCell>
                    {e.reimbursable
                      ? <Badge className="bg-amber-100 text-amber-700 hover:bg-amber-100 border-0">Reimbursable</Badge>
                      : <span className="text-xs text-muted-foreground">—</span>}
                  </TableCell>
                  <TableCell>
                    {e.receipt_url
                      ? <a href={e.receipt_url} target="_blank" rel="noreferrer" className="text-primary hover:underline text-xs inline-flex items-center gap-1"><FileText className="h-3 w-3" />View</a>
                      : <span className="text-xs text-muted-foreground">—</span>}
                  </TableCell>
                  <TableCell>
                    <Button size="icon" variant="ghost" onClick={() => remove(e.id)}><Trash2 className="h-4 w-4" /></Button>
                  </TableCell>
                </TableRow>
              ))}
              {!isLoading && (expenses as any[]).length === 0 && (
                <TableRow className="hover:bg-transparent"><TableCell colSpan={8} className="p-0">
                  <EmptyState icon={Wallet} title="No expenses yet" description="Track money spent — categorize, attach receipts, and mark reimbursable." />
                </TableCell></TableRow>
              )}
            </TableBody>
          </Table>
        </CardContent>
      </Card>
      <MatchBillDialog
        open={matchOpen}
        onOpenChange={setMatchOpen}
        candidates={matchCandidates}
        currency={cur}
        onMatch={async (billId) => {
          if (!pendingPayment) return;
          await applyPaymentToBill(billId, pendingPayment.amount);
          toast.success("Payment applied to existing bill");
          qc.invalidateQueries({ queryKey: ["bills", cid] });
          setMatchOpen(false);
        }}
        onCreateNew={async () => {
          if (!pendingPayment) return;
          const { createAutoBill } = await import("./lib/autoBill");
          const bill = await createAutoBill({
            companyId: cid, vendorId: pendingPayment.vendorId,
            amount: pendingPayment.amount, date: pendingPayment.date,
            category: pendingPayment.category, sourceKind: "expense", sourceId: pendingPayment.sourceId,
          });
          if (bill) {
            toast.success(`Bill ${bill.number} auto-created.`);
            qc.invalidateQueries({ queryKey: ["bills", cid] });
          }
          setMatchOpen(false);
        }}
      />
    </div>
  );
}
