import { createFileRoute } from "@tanstack/react-router";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useMemo, useRef, useState } from "react";
import { supabase } from "@/integrations/supabase/client";
import { GlassCard, SectionLabel } from "@/components/GlassCard";
import { MerchantAvatar } 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, relativeDay } from "@/lib/format";
import { ALL_CATEGORIES } from "@/lib/categories";
import { toast } from "sonner";
import { Plus, Trash2, Search, Paperclip, Receipt, X } from "lucide-react";
import { z } from "zod";

export const Route = createFileRoute("/_authenticated/transactions")({
  head: () => ({
    meta: [
      { title: "Activity — PRUDENTIA" },
      { name: "description", content: "Track every income and expense with PRUDENTIA." },
      { property: "og:title", content: "Activity — PRUDENTIA" },
      { property: "og:description", content: "Your money, tracked." },
    ],
  }),
  component: TransactionsPage,
});

function TransactionsPage() {
  const { user } = Route.useRouteContext();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const [q, setQ] = useState("");
  const [typeFilter, setTypeFilter] = useState<"all" | "income" | "expense">("all");
  const [catFilter, setCatFilter] = useState<string>("all");
  const [form, setForm] = useState({ amount: "", type: "expense" as "income" | "expense", category: "Groceries", merchant: "", note: "" });
  const [receipt, setReceipt] = useState<File | null>(null);
  const [saving, setSaving] = useState(false);
  const fileRef = useRef<HTMLInputElement>(null);

  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 txQ = useQuery({
    queryKey: ["tx", user.id],
    queryFn: async () => (await supabase.from("transactions").select("*").eq("user_id", user.id).order("occurred_at", { ascending: false })).data ?? [],
  });

  const all = txQ.data ?? [];

  const month = useMemo(() => {
    const now = new Date();
    let income = 0, expense = 0;
    for (const t of all as any[]) {
      const d = new Date(t.occurred_at);
      if (d.getMonth() !== now.getMonth() || d.getFullYear() !== now.getFullYear()) continue;
      if (t.type === "income") income += Number(t.amount); else expense += Number(t.amount);
    }
    return { income, expense, net: income - expense };
  }, [all]);

  const filtered = useMemo(() => {
    const needle = q.trim().toLowerCase();
    return (all as any[]).filter((t) => {
      if (typeFilter !== "all" && t.type !== typeFilter) return false;
      if (catFilter !== "all" && t.category !== catFilter) return false;
      if (!needle) return true;
      return [t.merchant, t.category, t.note, String(t.amount)].some((v) => (v ?? "").toString().toLowerCase().includes(needle));
    });
  }, [all, q, typeFilter, catFilter]);

  async function save() {
    const schema = z.object({ amount: z.coerce.number().positive(), type: z.enum(["income", "expense"]), category: z.string().min(1) });
    const parsed = schema.safeParse(form);
    if (!parsed.success) return toast.error("Enter a valid amount and category");
    setSaving(true);
    try {
      let receipt_url: string | null = null;
      if (receipt) {
        const ext = receipt.name.split(".").pop() ?? "jpg";
        const path = `${user.id}/${crypto.randomUUID()}.${ext}`;
        const { error: upErr } = await supabase.storage.from("receipts").upload(path, receipt, { upsert: false });
        if (upErr) throw upErr;
        receipt_url = path;
      }
      const { error } = await supabase.from("transactions").insert({
        user_id: user.id,
        amount: parsed.data.amount,
        type: parsed.data.type,
        category: parsed.data.category,
        merchant: form.merchant || null,
        note: form.note || null,
        receipt_url,
      });
      if (error) throw error;
      toast.success("Saved");
      setForm({ amount: "", type: "expense", category: "Groceries", merchant: "", note: "" });
      setReceipt(null);
      setOpen(false);
      qc.invalidateQueries({ queryKey: ["tx", user.id] });
      qc.invalidateQueries({ queryKey: ["health", user.id] });
      qc.invalidateQueries({ queryKey: ["brief", user.id] });
    } catch (e: any) {
      toast.error(e.message ?? "Failed to save");
    } finally {
      setSaving(false);
    }
  }

  async function openReceipt(path: string) {
    const { data, error } = await supabase.storage.from("receipts").createSignedUrl(path, 60);
    if (error || !data) return toast.error("Could not open receipt");
    window.open(data.signedUrl, "_blank", "noopener");
  }

  async function del(t: any) {
    const { error } = await supabase.from("transactions").delete().eq("id", t.id);
    if (error) return toast.error(error.message);
    if (t.receipt_url) await supabase.storage.from("receipts").remove([t.receipt_url]);
    qc.invalidateQueries({ queryKey: ["tx", user.id] });
  }

  const grouped = groupByDay(filtered);

  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">Ledger</p>
          <h1 className="text-2xl font-semibold">Activity</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" /> Add
            </Button>
          </SheetTrigger>
          <SheetContent side="bottom" className="rounded-t-3xl bg-background border-white/10 max-h-[92vh] overflow-y-auto">
            <SheetHeader><SheetTitle>New transaction</SheetTitle></SheetHeader>
            <div className="space-y-3 mt-4">
              <div className="grid grid-cols-2 gap-2">
                <button onClick={() => setForm({ ...form, type: "expense" })} className={`rounded-2xl py-2 text-sm ${form.type === "expense" ? "bg-electric text-primary-foreground" : "bg-white/5"}`}>Expense</button>
                <button onClick={() => setForm({ ...form, type: "income", category: "Income" })} className={`rounded-2xl py-2 text-sm ${form.type === "income" ? "bg-success text-primary-foreground" : "bg-white/5"}`}>Income</button>
              </div>
              <div>
                <Label>Amount</Label>
                <Input type="number" inputMode="decimal" value={form.amount} onChange={(e) => setForm({ ...form, amount: e.target.value })} className="mt-1" />
              </div>
              <div>
                <Label>Category</Label>
                <Select value={form.category} onValueChange={(v) => setForm({ ...form, category: v })}>
                  <SelectTrigger className="mt-1"><SelectValue /></SelectTrigger>
                  <SelectContent>{ALL_CATEGORIES.map((c) => <SelectItem key={c} value={c}>{c}</SelectItem>)}</SelectContent>
                </Select>
              </div>
              <div>
                <Label>Merchant</Label>
                <Input value={form.merchant} onChange={(e) => setForm({ ...form, merchant: e.target.value })} placeholder="Optional" className="mt-1" />
              </div>
              <div>
                <Label>Note</Label>
                <Input value={form.note} onChange={(e) => setForm({ ...form, note: e.target.value })} placeholder="Optional" className="mt-1" />
              </div>
              <div>
                <Label>Receipt</Label>
                <input ref={fileRef} type="file" accept="image/*,application/pdf" hidden onChange={(e) => setReceipt(e.target.files?.[0] ?? null)} />
                <button
                  type="button"
                  onClick={() => fileRef.current?.click()}
                  className="mt-1 w-full rounded-2xl bg-white/5 border border-white/10 px-4 py-3 text-sm flex items-center justify-between"
                >
                  <span className="flex items-center gap-2 text-muted-foreground truncate">
                    <Paperclip className="size-4" /> {receipt ? receipt.name : "Attach a photo or PDF"}
                  </span>
                  {receipt && <X className="size-4" onClick={(e) => { e.stopPropagation(); setReceipt(null); }} />}
                </button>
              </div>
              <Button onClick={save} disabled={saving} className="w-full h-11 rounded-full bg-gradient-to-r from-electric to-purple text-primary-foreground glow-electric">
                {saving ? "Saving…" : "Save"}
              </Button>
            </div>
          </SheetContent>
        </Sheet>
      </header>

      <GlassCard className="grid grid-cols-3 gap-2 py-4">
        {[
          { label: "In", value: month.income, cls: "text-success" },
          { label: "Out", value: month.expense, cls: "text-foreground" },
          { label: "Net", value: month.net, cls: month.net >= 0 ? "text-success" : "text-destructive" },
        ].map((s) => (
          <div key={s.label} className="text-center">
            <p className="text-[10px] uppercase tracking-widest text-muted-foreground">{s.label}</p>
            <p className={`text-base font-semibold tabular-nums mt-1 ${s.cls}`}>{formatCurrency(s.value, currency)}</p>
          </div>
        ))}
      </GlassCard>

      <div className="space-y-2">
        <div className="relative">
          <Search className="size-4 absolute left-3.5 top-1/2 -translate-y-1/2 text-muted-foreground" />
          <Input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Search merchant, note, amount" className="pl-10 rounded-full bg-white/5 border-white/10" />
        </div>
        <div className="flex gap-1.5 overflow-x-auto no-scrollbar pb-1">
          {(["all", "expense", "income"] as const).map((t) => (
            <Chip key={t} active={typeFilter === t} onClick={() => setTypeFilter(t)}>{t === "all" ? "All" : t === "expense" ? "Expenses" : "Income"}</Chip>
          ))}
          <span className="w-px bg-white/10 mx-1 shrink-0" />
          <Chip active={catFilter === "all"} onClick={() => setCatFilter("all")}>Any category</Chip>
          {ALL_CATEGORIES.map((c) => (
            <Chip key={c} active={catFilter === c} onClick={() => setCatFilter(c)}>{c}</Chip>
          ))}
        </div>
      </div>

      {grouped.length === 0 ? (
        <GlassCard className="text-center text-sm text-muted-foreground py-10">
          {all.length === 0 ? "Nothing yet. Add your first transaction." : "No transactions match those filters."}
        </GlassCard>
      ) : (
        grouped.map(([day, items]) => (
          <div key={day} className="space-y-2">
            <SectionLabel>{day}</SectionLabel>
            <div className="glass rounded-3xl divide-y divide-white/5">
              {items.map((t: any) => (
                <div key={t.id} className="p-4 flex items-center justify-between group">
                  <div className="flex items-center gap-3 min-w-0">
                    <MerchantAvatar merchant={t.merchant} category={t.category} />
                    <div className="min-w-0">
                      <p className="text-sm font-medium truncate">{t.merchant ?? t.category}</p>
                      <p className="text-[11px] text-muted-foreground truncate">{t.category}{t.note ? ` · ${t.note}` : ""}</p>
                    </div>
                  </div>
                  <div className="flex items-center gap-2 shrink-0">
                    {t.receipt_url && (
                      <button onClick={() => openReceipt(t.receipt_url)} className="text-muted-foreground hover:text-electric" aria-label="View receipt">
                        <Receipt className="size-4" />
                      </button>
                    )}
                    <p className={`text-sm font-medium tabular-nums ${t.type === "income" ? "text-success" : "text-foreground"}`}>
                      {t.type === "income" ? "+" : "-"}{formatCurrency(Number(t.amount), currency)}
                    </p>
                    <button onClick={() => del(t)} className="md:opacity-0 md:group-hover:opacity-100 text-muted-foreground hover:text-destructive transition" aria-label="Delete">
                      <Trash2 className="size-4" />
                    </button>
                  </div>
                </div>
              ))}
            </div>
          </div>
        ))
      )}
    </div>
  );
}

function Chip({ active, onClick, children }: { active: boolean; onClick: () => void; children: React.ReactNode }) {
  return (
    <button
      onClick={onClick}
      className={`shrink-0 rounded-full px-3 py-1.5 text-[11px] font-medium transition-all ${
        active ? "bg-gradient-to-r from-electric to-purple text-primary-foreground" : "bg-white/5 text-muted-foreground hover:text-foreground"
      }`}
    >
      {children}
    </button>
  );
}

function groupByDay(txs: any[]): Array<[string, any[]]> {
  const map = new Map<string, any[]>();
  for (const t of txs) {
    const key = relativeDay(t.occurred_at);
    if (!map.has(key)) map.set(key, []);
    map.get(key)!.push(t);
  }
  return Array.from(map.entries());
}
