import { createFileRoute } from "@tanstack/react-router";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useMemo, useState } from "react";
import { supabase } from "@/integrations/supabase/client";
import { GlassCard, SectionLabel } from "@/components/GlassCard";
import { CategoryIcon } from "@/components/CategoryIcon";
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 { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ui/sheet";
import { formatCurrency } from "@/lib/format";
import { EXPENSE_CATEGORIES } from "@/lib/categories";
import { monthProgress, projectedSpend } from "@/lib/finance";
import { toast } from "sonner";
import { Plus, Trash2, AlertTriangle, CheckCircle2, Gauge } from "lucide-react";

export const Route = createFileRoute("/_authenticated/budgets")({
  head: () => ({
    meta: [
      { title: "Budgets — PRUDENTIA" },
      { name: "description", content: "Set intelligent monthly budgets in PRUDENTIA." },
      { property: "og:title", content: "Budgets — PRUDENTIA" },
      { property: "og:description", content: "Spend with intent." },
    ],
  }),
  component: BudgetsPage,
});

function BudgetsPage() {
  const { user } = Route.useRouteContext();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const [category, setCategory] = useState("Dining");
  const [limit, setLimit] = useState("");
  const [threshold, setThreshold] = useState("80");

  const profileQ = useQuery({ queryKey: ["profile", user.id], queryFn: async () => (await supabase.from("profiles").select("currency").eq("id", user.id).single()).data });
  const currency = profileQ.data?.currency ?? "USD";

  const budgetsQ = useQuery({ queryKey: ["budgets", user.id], queryFn: async () => (await supabase.from("budgets").select("*").eq("user_id", user.id).order("category")).data ?? [] });
  const txQ = useQuery({ queryKey: ["tx", user.id], queryFn: async () => (await supabase.from("transactions").select("category,amount,type,occurred_at").eq("user_id", user.id)).data ?? [] });

  const now = new Date();
  const dayOfMonth = now.getDate();
  const daysInMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate();
  const progress = monthProgress(now);

  const spentByCat = useMemo(() => {
    const m = new Map<string, number>();
    (txQ.data ?? []).forEach((t: any) => {
      const d = new Date(t.occurred_at);
      if (t.type === "expense" && d.getMonth() === now.getMonth() && d.getFullYear() === now.getFullYear()) {
        m.set(t.category, (m.get(t.category) ?? 0) + Number(t.amount));
      }
    });
    return m;
  }, [txQ.data]);

  const budgets = (budgetsQ.data ?? []) as any[];

  const summary = useMemo(() => {
    let limitTotal = 0, spentTotal = 0, alerts = 0;
    for (const b of budgets) {
      const spent = spentByCat.get(b.category) ?? 0;
      limitTotal += Number(b.monthly_limit);
      spentTotal += spent;
      const pct = (spent / Number(b.monthly_limit)) * 100;
      if (pct >= (b.alert_threshold ?? 80)) alerts++;
    }
    return { limitTotal, spentTotal, alerts, remaining: limitTotal - spentTotal };
  }, [budgets, spentByCat]);

  async function save() {
    const n = Number(limit);
    if (!n || n <= 0) return toast.error("Enter a valid limit");
    const { error } = await supabase.from("budgets").upsert(
      { user_id: user.id, category, monthly_limit: n, alert_threshold: Math.min(100, Math.max(10, Number(threshold) || 80)) },
      { onConflict: "user_id,category" },
    );
    if (error) return toast.error(error.message);
    toast.success("Budget saved");
    setLimit(""); setOpen(false);
    qc.invalidateQueries({ queryKey: ["budgets", user.id] });
  }

  async function del(id: string) {
    await supabase.from("budgets").delete().eq("id", id);
    qc.invalidateQueries({ queryKey: ["budgets", user.id] });
  }

  return (
    <div className="px-4 pt-8 space-y-5">
      <header className="flex items-end justify-between px-1">
        <div>
          <p className="text-[11px] text-muted-foreground uppercase tracking-widest">Guardrails</p>
          <h1 className="text-2xl font-semibold">Budgets</h1>
        </div>
        <Sheet open={open} onOpenChange={setOpen}>
          <SheetTrigger asChild>
            <Button size="sm" className="rounded-full bg-gradient-to-r from-electric to-purple text-primary-foreground"><Plus className="size-4 mr-1" /> New</Button>
          </SheetTrigger>
          <SheetContent side="bottom" className="rounded-t-3xl bg-background border-white/10">
            <SheetHeader><SheetTitle>New budget</SheetTitle></SheetHeader>
            <div className="space-y-3 mt-4">
              <div>
                <Label>Category</Label>
                <Select value={category} onValueChange={setCategory}>
                  <SelectTrigger className="mt-1"><SelectValue /></SelectTrigger>
                  <SelectContent>{EXPENSE_CATEGORIES.map((c) => <SelectItem key={c} value={c}>{c}</SelectItem>)}</SelectContent>
                </Select>
              </div>
              <div>
                <Label>Monthly limit</Label>
                <Input type="number" inputMode="decimal" value={limit} onChange={(e) => setLimit(e.target.value)} className="mt-1" />
              </div>
              <div>
                <Label>Alert me at (% of limit)</Label>
                <Input type="number" inputMode="numeric" value={threshold} onChange={(e) => setThreshold(e.target.value)} className="mt-1" />
              </div>
              <Button onClick={save} className="w-full h-11 rounded-full bg-gradient-to-r from-electric to-purple text-primary-foreground glow-electric">Save</Button>
            </div>
          </SheetContent>
        </Sheet>
      </header>

      {budgets.length > 0 && (
        <GlassCard className="space-y-3">
          <div className="flex items-center justify-between">
            <div>
              <p className="text-[10px] uppercase tracking-widest text-muted-foreground">This month</p>
              <p className="text-xl font-semibold tabular-nums mt-0.5">{formatCurrency(summary.spentTotal, currency)} <span className="text-sm text-muted-foreground font-normal">of {formatCurrency(summary.limitTotal, currency)}</span></p>
            </div>
            <div className={`flex items-center gap-1.5 text-[11px] font-medium ${summary.alerts ? "text-warning" : "text-success"}`}>
              {summary.alerts ? <AlertTriangle className="size-4" /> : <CheckCircle2 className="size-4" />}
              {summary.alerts ? `${summary.alerts} alert${summary.alerts > 1 ? "s" : ""}` : "All on pace"}
            </div>
          </div>
          <div className="h-1.5 rounded-full bg-white/10 overflow-hidden relative">
            <div className="h-full bg-gradient-to-r from-electric to-purple" style={{ width: `${Math.min(100, (summary.spentTotal / (summary.limitTotal || 1)) * 100)}%` }} />
            <div className="absolute inset-y-0 w-px bg-foreground/50" style={{ left: `${progress * 100}%` }} title="Month progress" />
          </div>
          <p className="text-[11px] text-muted-foreground">
            Day {dayOfMonth} of {daysInMonth} · {formatCurrency(Math.max(0, summary.remaining), currency)} left ({formatCurrency(Math.max(0, summary.remaining) / Math.max(1, daysInMonth - dayOfMonth + 1), currency)}/day)
          </p>
        </GlassCard>
      )}

      <SectionLabel>Categories</SectionLabel>
      <div className="space-y-3">
        {budgets.length === 0 && (
          <GlassCard className="text-center text-sm text-muted-foreground py-10">Set a budget for any category.</GlassCard>
        )}
        {budgets.map((b: any) => {
          const spent = spentByCat.get(b.category) ?? 0;
          const lim = Number(b.monthly_limit);
          const rawPct = (spent / lim) * 100;
          const pct = Math.min(100, rawPct);
          const over = spent > lim;
          const alertAt = b.alert_threshold ?? 80;
          const nearing = !over && rawPct >= alertAt;
          const projected = projectedSpend(spent, now);
          const paceOver = projected > lim * 1.02;
          return (
            <GlassCard key={b.id} className="p-4">
              <div className="flex items-center justify-between gap-3">
                <div className="flex items-center gap-3 min-w-0">
                  <CategoryIcon category={b.category} />
                  <div className="min-w-0">
                    <p className="text-sm font-medium">{b.category}</p>
                    <p className="text-[11px] text-muted-foreground mt-0.5">{formatCurrency(spent, currency)} of {formatCurrency(lim, currency)}</p>
                  </div>
                </div>
                <button onClick={() => del(b.id)} className="text-muted-foreground hover:text-destructive" aria-label="Delete budget"><Trash2 className="size-4" /></button>
              </div>
              <div className="mt-3 h-1.5 rounded-full bg-white/10 overflow-hidden relative">
                <div className={`h-full ${over ? "bg-destructive" : nearing ? "bg-warning" : "bg-gradient-to-r from-electric to-purple"}`} style={{ width: `${pct}%` }} />
                <div className="absolute inset-y-0 w-px bg-foreground/40" style={{ left: `${alertAt}%` }} />
              </div>
              <div className="mt-2 flex items-center justify-between text-[11px]">
                <span className={over ? "text-destructive" : nearing ? "text-warning" : "text-muted-foreground"}>
                  {over
                    ? `Over by ${formatCurrency(spent - lim, currency)}`
                    : nearing
                      ? `${rawPct.toFixed(0)}% used — past your ${alertAt}% alert`
                      : `${formatCurrency(lim - spent, currency)} left`}
                </span>
                <span className={`flex items-center gap-1 ${paceOver ? "text-warning" : "text-muted-foreground"}`}>
                  <Gauge className="size-3.5" /> Projected {formatCurrency(projected, currency)}
                </span>
              </div>
            </GlassCard>
          );
        })}
      </div>
    </div>
  );
}
