import { db } from "@/db";
import { bankAccounts, transactions, recurringRules, budgets, categories } from "@/db/schema";
import { eq, and, gte, lte } from "drizzle-orm";
import { requireHousehold } from "@/lib/session";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Progress } from "@/components/ui/progress";
import { AnimatedMoney } from "@/components/animated-number";
import { formatMoney } from "@/lib/utils";
import { loadLedger } from "@/lib/ledger-service";
import { addDays, startOfMonth, endOfMonth } from "date-fns";
import { ArrowDownRight, ArrowUpRight, Calendar, Wallet } from "lucide-react";

export default async function DashboardPage() {
  const { householdId } = await requireHousehold();
  const today = new Date();
  const monthStart = startOfMonth(today);
  const monthEnd = endOfMonth(today);

  const accts = await db
    .select()
    .from(bankAccounts)
    .where(and(eq(bankAccounts.householdId, householdId), eq(bankAccounts.isArchived, false)));

  // current balances (opening + all posted)
  const currentByAccount: Record<string, number> = {};
  for (const a of accts) {
    const txs = await db
      .select()
      .from(transactions)
      .where(
        and(
          eq(transactions.bankAccountId, a.id),
          eq(transactions.householdId, householdId),
        ),
      );
    const sum = txs
      .filter((t) => t.status === "posted")
      .reduce((s, t) => s + t.amountMinor, 0);
    currentByAccount[a.id] = a.openingBalanceMinor + sum;
  }
  const totalBalance = Object.values(currentByAccount).reduce((s, v) => s + v, 0);

  // upcoming projected over next 14 days
  const { rows: upcomingRows } = await loadLedger({
    householdId,
    from: addDays(today, 1),
    to: addDays(today, 14),
  });
  const upcoming = upcomingRows.filter((r) => r.status === "projected").slice(0, 8);

  // forecast end-of-month spendable
  const { rows: monthRows } = await loadLedger({
    householdId,
    from: today,
    to: monthEnd,
  });
  const projectedEoM = monthRows.length > 0 ? monthRows[monthRows.length - 1].runningBalanceMinor : totalBalance;

  // current month spending vs budgets
  const monthStartIso = monthStart.toISOString().slice(0, 10);
  const monthEndIso = monthEnd.toISOString().slice(0, 10);
  const monthTxs = await db
    .select()
    .from(transactions)
    .where(
      and(
        eq(transactions.householdId, householdId),
        eq(transactions.status, "posted"),
        gte(transactions.date, monthStartIso),
        lte(transactions.date, monthEndIso),
      ),
    );
  const allBudgets = await db.select().from(budgets).where(eq(budgets.householdId, householdId));
  const cats = await db.select().from(categories).where(eq(categories.householdId, householdId));
  const catMap = new Map(cats.map((c) => [c.id, c]));

  const spentByCat: Record<string, number> = {};
  for (const t of monthTxs) {
    if (!t.categoryId || t.amountMinor >= 0) continue;
    spentByCat[t.categoryId] = (spentByCat[t.categoryId] ?? 0) + Math.abs(t.amountMinor);
  }

  const incomeMonth = monthTxs.filter((t) => t.amountMinor > 0).reduce((s, t) => s + t.amountMinor, 0);
  const expenseMonth = monthTxs.filter((t) => t.amountMinor < 0).reduce((s, t) => s + Math.abs(t.amountMinor), 0);

  return (
    <div className="space-y-6 max-w-7xl mx-auto">
      <div className="flex items-end justify-between">
        <div>
          <p className="text-sm text-muted-foreground">Spendable across all accounts</p>
          <h1 className="text-5xl font-bold tracking-tight tabular text-foreground">
            <AnimatedMoney amountMinor={totalBalance} />
          </h1>
          <p className="text-sm text-muted-foreground mt-1">
            Projected end-of-month: <span className="text-foreground tabular">{formatMoney(projectedEoM)}</span>
          </p>
        </div>
      </div>

      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
        <Card>
          <CardHeader>
            <CardDescription className="flex items-center gap-2">
              <ArrowUpRight className="size-4 text-success" />
              Income this month
            </CardDescription>
            <CardTitle className="text-2xl tabular text-success">{formatMoney(incomeMonth)}</CardTitle>
          </CardHeader>
        </Card>
        <Card>
          <CardHeader>
            <CardDescription className="flex items-center gap-2">
              <ArrowDownRight className="size-4 text-destructive" />
              Spent this month
            </CardDescription>
            <CardTitle className="text-2xl tabular text-destructive">{formatMoney(expenseMonth)}</CardTitle>
          </CardHeader>
        </Card>
        <Card>
          <CardHeader>
            <CardDescription className="flex items-center gap-2">
              <Wallet className="size-4 text-primary" />
              Accounts
            </CardDescription>
            <CardTitle className="text-2xl tabular">{accts.length}</CardTitle>
          </CardHeader>
        </Card>
        <Card>
          <CardHeader>
            <CardDescription className="flex items-center gap-2">
              <Calendar className="size-4 text-warning" />
              Upcoming (14d)
            </CardDescription>
            <CardTitle className="text-2xl tabular">{upcoming.length}</CardTitle>
          </CardHeader>
        </Card>
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
        <Card className="lg:col-span-2">
          <CardHeader>
            <CardTitle>Accounts</CardTitle>
            <CardDescription>Current balance per account</CardDescription>
          </CardHeader>
          <CardContent className="space-y-2">
            {accts.map((a) => (
              <div key={a.id} className="flex items-center justify-between rounded-md bg-card/40 border px-4 py-3">
                <div>
                  <div className="font-medium">{a.name}</div>
                  <div className="text-xs text-muted-foreground capitalize">{a.type}</div>
                </div>
                <div className="font-mono tabular text-lg">{formatMoney(currentByAccount[a.id] ?? 0, a.currency)}</div>
              </div>
            ))}
          </CardContent>
        </Card>

        <Card>
          <CardHeader>
            <CardTitle>Upcoming bills</CardTitle>
            <CardDescription>Next 14 days</CardDescription>
          </CardHeader>
          <CardContent className="space-y-2">
            {upcoming.length === 0 ? (
              <p className="text-sm text-muted-foreground">Nothing scheduled.</p>
            ) : (
              upcoming.map((u) => (
                <div key={u.id} className="flex items-center justify-between text-sm">
                  <div>
                    <div className="font-medium">{u.description}</div>
                    <div className="text-xs text-muted-foreground">{u.date}</div>
                  </div>
                  <span
                    className={`font-mono tabular ${u.amountMinor < 0 ? "text-destructive" : "text-success"}`}
                  >
                    {formatMoney(u.amountMinor)}
                  </span>
                </div>
              ))
            )}
          </CardContent>
        </Card>
      </div>

      {allBudgets.length > 0 && (
        <Card>
          <CardHeader>
            <CardTitle>Budgets</CardTitle>
            <CardDescription>This month, by category</CardDescription>
          </CardHeader>
          <CardContent className="space-y-3">
            {allBudgets.map((b) => {
              const cat = catMap.get(b.categoryId);
              const spent = spentByCat[b.categoryId] ?? 0;
              const pct = Math.round((spent / b.amountMinor) * 100);
              const over = spent > b.amountMinor;
              return (
                <div key={b.id} className="space-y-1.5">
                  <div className="flex items-center justify-between text-sm">
                    <div className="font-medium">{cat?.name ?? "Category"}</div>
                    <div className="font-mono tabular">
                      <span className={over ? "text-destructive" : ""}>{formatMoney(spent)}</span>
                      <span className="text-muted-foreground"> / {formatMoney(b.amountMinor)}</span>
                    </div>
                  </div>
                  <Progress value={pct} className={over ? "[&>div]:bg-destructive" : ""} />
                </div>
              );
            })}
          </CardContent>
        </Card>
      )}
    </div>
  );
}
