"use client"

import { useEffect, useMemo, useState } from "react"
import Link from "next/link"
import { ArrowLeft, Pencil, Plus, Search, Wallet } from "lucide-react"

import { bankAccountsApi, glAccountsApi } from "@/lib/api/general-ledger"
import { errorMessage } from "@/lib/error-map"
import { formatReportDate } from "@/lib/format"
import { cn } from "@/lib/utils"
import { CashAndBankAccountDto, CashBankAccountType, GlAccount } from "@/types/general-ledger"

import { Badge } from "@/components/ui/badge"
import { Button, buttonVariants } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Skeleton } from "@/components/ui/skeleton"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"

type AccountTypeFilter = CashBankAccountType | "Both"

export default function BankAccountsPage() {
  const [accounts, setAccounts] = useState<CashAndBankAccountDto[] | null>(null)
  const [glAccounts, setGlAccounts] = useState<GlAccount[] | null>(null)
  const [error, setError] = useState<string | null>(null)
  const [search, setSearch] = useState("")
  const [accountType, setAccountType] = useState<AccountTypeFilter>("Both")

  // GL's own server-side accountType filter (2026-07-22 rework — was client-only over one table
  // before) — re-fetches whenever the filter changes, unlike the plain client-side search below.
  useEffect(() => {
    let cancelled = false
    Promise.all([bankAccountsApi.list(accountType), glAccountsApi.list()])
      .then(([banks, gl]) => {
        if (cancelled) return
        setAccounts(banks)
        setGlAccounts(gl.items)
      })
      .catch((err) => {
        if (!cancelled) setError(errorMessage(err))
      })
    return () => {
      cancelled = true
    }
  }, [accountType])

  const glAccountsById = useMemo(() => new Map((glAccounts ?? []).map((a) => [a.accountId, a])), [glAccounts])

  const filtered = useMemo(() => {
    if (!accounts) return null
    const q = search.trim().toLowerCase()
    if (!q) return accounts
    return accounts.filter((a) => {
      const gl = glAccountsById.get(a.glAccountId)
      return (
        a.accountName.toLowerCase().includes(q) ||
        (a.bankName ?? "").toLowerCase().includes(q) ||
        (a.cashAccountTypeName ?? "").toLowerCase().includes(q) ||
        (a.accountNumber ?? "").toLowerCase().includes(q) ||
        a.currencyCode.toLowerCase().includes(q) ||
        (gl?.accountCode ?? "").toLowerCase().includes(q)
      )
    })
  }, [accounts, search, glAccountsById])

  return (
    <div className="flex flex-col gap-6">
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-3">
          <Link href="/dashboard/accounts" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
            <ArrowLeft className="size-5" />
          </Link>
          <div>
            <h1 className="text-2xl font-bold text-foreground">Cash / Bank Accounts</h1>
            <p className="text-base text-muted-foreground">Cash and Bank accounts linked to a GL account, for reconciliation.</p>
          </div>
        </div>
        <Link href="/dashboard/accounts/bank-accounts/new" className={cn(buttonVariants({ size: "lg" }))}>
          <Plus className="size-5" />
          New Account
        </Link>
      </div>

      <div className="flex flex-col gap-3 sm:flex-row sm:items-center">
        <div className="relative flex-1">
          <Search className="pointer-events-none absolute top-1/2 left-4 size-5 -translate-y-1/2 text-muted-foreground" />
          <Input
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            placeholder="Search name, bank/type, account no. or currency…"
            className="h-14 w-full pl-11 text-base"
            aria-label="Search cash/bank accounts"
          />
        </div>
        <Select<AccountTypeFilter> value={accountType} onValueChange={(v) => setAccountType(v ?? "Both")}>
          <SelectTrigger className="h-14! w-full text-base sm:w-48">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="Both" label="All types" className="text-base">All types</SelectItem>
            <SelectItem value={CashBankAccountType.Bank} label="Bank" className="text-base">Bank</SelectItem>
            <SelectItem value={CashBankAccountType.Cash} label="Cash" className="text-base">Cash</SelectItem>
          </SelectContent>
        </Select>
      </div>

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

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

      {!error && filtered !== null && filtered.length === 0 && (
        <div className="flex flex-col items-center gap-4 rounded-xl border border-dashed py-20 text-center">
          <Wallet className="size-12 text-muted-foreground" />
          <p className="text-base text-muted-foreground">
            {search ? "No accounts match your search." : "No cash/bank accounts yet."}
          </p>
        </div>
      )}

      {!error && filtered !== null && filtered.length > 0 && (
        <Table className="text-base">
          <TableHeader>
            <TableRow>
              <TableHead className="h-12 px-3 text-sm">Type</TableHead>
              <TableHead className="h-12 px-3 text-sm">Account name</TableHead>
              <TableHead className="h-12 px-3 text-sm">Bank / Cash type</TableHead>
              <TableHead className="h-12 px-3 text-sm">Account no.</TableHead>
              <TableHead className="h-12 px-3 text-sm">GL account</TableHead>
              <TableHead className="h-12 px-3 text-sm">Currency</TableHead>
              <TableHead className="h-12 px-3 text-sm">Created</TableHead>
              <TableHead className="h-12 px-3 text-sm">Actions</TableHead>
            </TableRow>
          </TableHeader>
          <TableBody>
            {filtered.map((a) => {
              const gl = glAccountsById.get(a.glAccountId)
              return (
                <TableRow key={`${a.accountType}-${a.accountId}`}>
                  <TableCell className="px-3 py-3.5">
                    <Badge
                      variant="outline"
                      className={cn(
                        "h-6 w-16 justify-center border-transparent text-sm",
                        a.accountType === CashBankAccountType.Cash
                          ? "bg-success/10 text-success"
                          : "bg-primary/10 text-primary"
                      )}
                    >
                      {a.accountType}
                    </Badge>
                  </TableCell>
                  <TableCell className="px-3 py-3.5 font-medium">{a.accountName}</TableCell>
                  <TableCell className="px-3 py-3.5">{a.bankName ?? a.cashAccountTypeName ?? "—"}</TableCell>
                  <TableCell className="px-3 py-3.5">{a.accountNumber ?? "—"}</TableCell>
                  <TableCell className="px-3 py-3.5 text-muted-foreground">
                    {gl ? `${gl.accountCode} — ${gl.accountName}` : `#${a.glAccountId}`}
                  </TableCell>
                  <TableCell className="px-3 py-3.5">{a.currencyCode}</TableCell>
                  <TableCell className="px-3 py-3.5 text-muted-foreground">{formatReportDate(a.createdAt)}</TableCell>
                  <TableCell className="px-3 py-3.5">
                    <Tooltip>
                      <TooltipTrigger
                        render={
                          <Button variant="ghost" size="icon-sm" disabled aria-label={`Edit ${a.accountName}`} />
                        }
                      >
                        <Pencil className="size-4" />
                      </TooltipTrigger>
                      <TooltipContent>
                        Editing isn&apos;t available yet — the General Ledger service has no update endpoint for
                        {a.accountType === CashBankAccountType.Cash ? " cash" : " bank"} accounts.
                      </TooltipContent>
                    </Tooltip>
                  </TableCell>
                </TableRow>
              )
            })}
          </TableBody>
        </Table>
      )}
    </div>
  )
}
