import { auth } from '@/lib/auth'
import { prisma } from '@/lib/prisma'
import { monthBounds, monthLabel } from '@/lib/utils/dates'
import { NetWorthCard } from '@/components/dashboard/NetWorthCard'
import { CashFlowCard } from '@/components/dashboard/CashFlowCard'
import { RecentTransactions } from '@/components/dashboard/RecentTransactions'
import { BudgetSummary } from '@/components/dashboard/BudgetSummary'
import { MonthYearPicker } from '@/components/dashboard/MonthYearPicker'

type SearchParams = Promise<Record<string, string | string[] | undefined>>

export default async function DashboardPage({ searchParams }: { searchParams: SearchParams }) {
  const session = await auth()
  if (!session?.user?.id) return null

  const userId = session.user.id
  const sp = await searchParams
  const get = (k: string) => (Array.isArray(sp[k]) ? sp[k][0] : sp[k]) ?? ''

  const now = new Date()
  const month = Number(get('month')) || (now.getMonth() + 1)
  const year = Number(get('year')) || now.getFullYear()
  const isCurrentMonth = month === (now.getMonth() + 1) && year === now.getFullYear()

  const selectedDate = new Date(year, month - 1, 1)
  const { start, end } = monthBounds(selectedDate)

  const [cashFlowRows, budgets, spendRows, recentTx] = await Promise.all([
    prisma.$queryRaw<{ type: string; total: bigint }[]>`
      SELECT t.type, COALESCE(SUM(t."amountCents"), 0)::bigint AS total
      FROM "Transaction" t
      JOIN "Account" a ON t."accountId" = a.id
      WHERE a."userId" = ${userId}
        AND a.type = 'BANK'
        AND t.type != 'TRANSFER'
        AND t.date >= ${start}
        AND t.date <= ${end}
      GROUP BY t.type
    `,
    prisma.budget.findMany({
      where: { userId, isActive: true },
      orderBy: { name: 'asc' },
    }),
    prisma.$queryRaw<{ budgetId: string; total: bigint }[]>`
      SELECT t."budgetId",
        COALESCE(SUM(CASE WHEN t.type = 'DEBIT' THEN t."amountCents" WHEN t.type = 'CREDIT' THEN -t."amountCents" ELSE 0 END), 0)::bigint AS total
      FROM "Transaction" t
      JOIN "Account" a ON t."accountId" = a.id
      WHERE a."userId" = ${userId}
        AND t."budgetId" IS NOT NULL
        AND t.date >= ${start}
        AND t.date <= ${end}
      GROUP BY t."budgetId"
    `,
    prisma.transaction.findMany({
      where: {
        account: { userId },
        date: { gte: start, lte: end },
      },
      include: { account: { select: { name: true } } },
      orderBy: { date: 'desc' },
      take: 5,
    }),
  ])

  // Net worth: live balances for current month, snapshots for past months
  let netWorthCents: number
  let netWorthAccounts: { id: string; name: string; balanceCents: number }[]

  if (isCurrentMonth) {
    const accounts = await prisma.account.findMany({
      where: { userId, isActive: true, type: { in: ['BANK', 'INVESTMENT'] } },
      select: { id: true, name: true, currentBalanceCents: true },
      orderBy: { name: 'asc' },
    })
    netWorthAccounts = accounts.map((a) => ({ id: a.id, name: a.name, balanceCents: a.currentBalanceCents }))
    netWorthCents = netWorthAccounts.reduce((s, a) => s + a.balanceCents, 0)
  } else {
    const snapshots = await prisma.$queryRaw<{ accountId: string; name: string; balanceCents: bigint }[]>`
      SELECT bs."accountId", a.name, bs."balanceCents"
      FROM "BalanceSnapshot" bs
      JOIN "Account" a ON bs."accountId" = a.id
      WHERE a."userId" = ${userId}
        AND a.type IN ('BANK', 'INVESTMENT')
        AND bs.year = ${year}
        AND bs.month = ${month}
    `
    netWorthAccounts = snapshots.map((s) => ({
      id: s.accountId,
      name: s.name,
      balanceCents: Number(s.balanceCents),
    }))
    netWorthCents = netWorthAccounts.reduce((s, a) => s + a.balanceCents, 0)
  }

  const cfMap = Object.fromEntries(cashFlowRows.map((r) => [r.type, Number(r.total)]))
  const creditsCents = cfMap['CREDIT'] ?? 0
  const debitsCents = cfMap['DEBIT'] ?? 0

  const spendMap = new Map(spendRows.map((r) => [r.budgetId, Number(r.total)]))

  const recentTransactions = recentTx.map((t) => ({
    id: t.id,
    date: t.date.toISOString(),
    description: t.description,
    amountCents: t.amountCents,
    type: t.type,
    accountName: t.account.name,
  }))

  const budgetsWithSpend = budgets.map((b) => ({
    id: b.id,
    name: b.name,
    limitCents: b.limitCents,
    color: b.color,
    spendCents: spendMap.get(b.id) ?? 0,
  }))

  return (
    <div className="p-6 space-y-6">
      <div className="flex items-center justify-between">
        <h1 className="text-2xl font-bold">Dashboard</h1>
        <MonthYearPicker />
      </div>

      <div className="grid gap-4 sm:grid-cols-2">
        <NetWorthCard netWorthCents={netWorthCents} bankAccounts={netWorthAccounts} />
        <CashFlowCard
          monthLabel={monthLabel(selectedDate)}
          creditsCents={creditsCents}
          debitsCents={debitsCents}
          netCents={creditsCents - debitsCents}
        />
      </div>

      <div className="grid gap-4 lg:grid-cols-2">
        <RecentTransactions transactions={recentTransactions} />
        <BudgetSummary budgets={budgetsWithSpend} />
      </div>
    </div>
  )
}
