"use client"

import { useEffect, useMemo, useState } from "react"
import Link from "next/link"
import { ArrowLeft, BadgeDollarSign } from "lucide-react"

import { glBudgetsApi, reportsApi } from "@/lib/api/general-ledger"
import { errorMessage } from "@/lib/error-map"
import { formatAmount } from "@/lib/format"
import { cn } from "@/lib/utils"
import { BudgetVsActualRow, GlBudget, ReportType } from "@/types/general-ledger"

import { buttonVariants } from "@/components/ui/button"
import { Label } from "@/components/ui/label"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Skeleton } from "@/components/ui/skeleton"
import { Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { DownloadCsvButton } from "@/components/reports/DownloadCsvButton"
import { DownloadPdfButton } from "@/components/reports/DownloadPdfButton"
import { ReportHeader } from "@/components/reports/ReportHeader"

export default function BudgetVsActualPage() {
  const [budgets, setBudgets] = useState<GlBudget[] | null>(null)
  const [budgetsError, setBudgetsError] = useState<string | null>(null)
  const [budgetId, setBudgetId] = useState<number | "">("")

  const [rows, setRows] = useState<BudgetVsActualRow[] | null>(null)
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    glBudgetsApi
      .list()
      .then((res) => setBudgets(res))
      .catch((err) => setBudgetsError(errorMessage(err)))
  }, [])

  // Clears stale results the instant budgetId changes, during the render that reacts to it —
  // not inside the effect below, which would be a synchronous setState-in-effect
  // (react-hooks/set-state-in-effect); this is React's own sanctioned "adjust state during
  // render" pattern instead.
  const [loadedFor, setLoadedFor] = useState<number | "">("")
  if (loadedFor !== budgetId) {
    setLoadedFor(budgetId)
    setRows(null)
    setError(null)
  }

  useEffect(() => {
    if (!budgetId) return
    let cancelled = false
    reportsApi
      .budgetVsActual(budgetId)
      .then((res) => {
        if (!cancelled) setRows(res)
      })
      .catch((err) => {
        if (!cancelled) setError(errorMessage(err))
      })
    return () => {
      cancelled = true
    }
  }, [budgetId])

  const selectedBudget = useMemo(() => (budgets ?? []).find((b) => b.budgetId === budgetId) ?? null, [budgets, budgetId])

  const totalBudgeted = (rows ?? []).reduce((sum, r) => sum + r.budgetedAmount, 0)
  const totalActual = (rows ?? []).reduce((sum, r) => sum + r.actualAmount, 0)
  const totalVariance = (rows ?? []).reduce((sum, r) => sum + r.variance, 0)

  return (
    <div className="flex flex-col gap-6">
      <div className="flex items-center gap-3">
        <Link href="/dashboard/ledgers" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
          <ArrowLeft className="size-5" />
        </Link>
        <div>
          <h1 className="text-2xl font-bold text-foreground">Budget vs Actual</h1>
          <p className="text-base text-muted-foreground">Budgeted amounts against real postings per account/period.</p>
        </div>
      </div>

      {budgetsError && (
        <div className="rounded-lg border border-destructive/30 bg-destructive/5 p-5 text-base text-destructive">{budgetsError}</div>
      )}

      <div className="flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between">
        <div className="flex flex-col gap-1.5 sm:w-96">
          <Label className="text-base">Budget</Label>
          <Select<number | ""> value={budgetId} onValueChange={(v) => setBudgetId(v ?? "")}>
            <SelectTrigger className="h-11! w-full text-base">
              <SelectValue placeholder={budgets === null ? "Loading…" : "Select a budget"} />
            </SelectTrigger>
            <SelectContent>
              {(budgets ?? []).map((b) => (
                <SelectItem key={b.budgetId} value={b.budgetId} label={b.name} className="text-base">
                  {b.name}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>
        <div className="flex gap-2">
          <DownloadPdfButton reportType={ReportType.BudgetVsActual} params={{ budgetId: budgetId || undefined }} disabled={!rows} />
          <DownloadCsvButton reportType={ReportType.BudgetVsActual} params={{ budgetId: budgetId || undefined }} disabled={!rows} />
        </div>
      </div>

      {error && (
        <div className="rounded-lg border border-destructive/30 bg-destructive/5 p-5 text-base text-destructive">{error}</div>
      )}

      {!error && !budgetId && (
        <div className="flex flex-col items-center gap-4 rounded-xl border border-dashed py-20 text-center">
          <BadgeDollarSign className="size-12 text-muted-foreground" />
          <p className="text-base text-muted-foreground">Select a budget to compare against actuals.</p>
        </div>
      )}

      {!error && budgetId && rows === null && (
        <div className="flex flex-col gap-3">
          {Array.from({ length: 5 }).map((_, i) => (
            <Skeleton key={i} className="h-12 w-full" />
          ))}
        </div>
      )}

      {!error && budgetId && rows !== null && rows.length === 0 && (
        <div className="flex flex-col items-center gap-4 rounded-xl border border-dashed py-20 text-center">
          <BadgeDollarSign className="size-12 text-muted-foreground" />
          <p className="text-base text-muted-foreground">This budget has no lines yet.</p>
        </div>
      )}

      {!error && budgetId && rows !== null && rows.length > 0 && (
        <div className="rounded-2xl bg-white p-6 shadow-sm ring-1 ring-black/5">
          <ReportHeader title="Budget vs Actual" subtitle={selectedBudget?.name ?? ""} />
          <Table className="mt-4 text-base">
            <TableHeader>
              <TableRow>
                <TableHead className="h-11 px-3 text-sm">Account</TableHead>
                <TableHead className="h-11 px-3 text-right text-sm">Budgeted</TableHead>
                <TableHead className="h-11 px-3 text-right text-sm">Actual</TableHead>
                <TableHead className="h-11 px-3 text-right text-sm">Variance</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {rows.map((row) => (
                <TableRow key={row.budgetLineId}>
                  <TableCell className="px-3 py-2.5">
                    <span className="text-muted-foreground">{row.accountCode}</span>{" "}
                    <span>{row.accountName}</span>
                  </TableCell>
                  <TableCell className="px-3 py-2.5 text-right tabular-nums">{formatAmount(row.budgetedAmount)}</TableCell>
                  <TableCell className="px-3 py-2.5 text-right tabular-nums">{formatAmount(row.actualAmount)}</TableCell>
                  <TableCell
                    className={cn(
                      "px-3 py-2.5 text-right font-medium tabular-nums",
                      row.variance < 0 ? "text-destructive" : "text-success"
                    )}
                  >
                    {formatAmount(row.variance)}
                  </TableCell>
                </TableRow>
              ))}
            </TableBody>
            <TableFooter className="border-t-2 border-foreground/70 bg-transparent">
              <TableRow className="hover:bg-transparent">
                <TableCell className="px-3 py-3 font-bold">Total</TableCell>
                <TableCell className="px-3 py-3 text-right font-bold tabular-nums">{formatAmount(totalBudgeted)}</TableCell>
                <TableCell className="px-3 py-3 text-right font-bold tabular-nums">{formatAmount(totalActual)}</TableCell>
                <TableCell className="px-3 py-3 text-right font-bold tabular-nums">{formatAmount(totalVariance)}</TableCell>
              </TableRow>
            </TableFooter>
          </Table>
        </div>
      )}
    </div>
  )
}
