"use client"

import * as React from "react"
import {
  flexRender,
  getCoreRowModel,
  getFilteredRowModel,
  getPaginationRowModel,
  useReactTable,
  type ColumnDef,
  type ColumnFiltersState,
  type FilterFn,
  type PaginationState,
} from "@tanstack/react-table"
import { GitCompareArrows } from "lucide-react"

import { FormPageHeader } from "@/app/dashboard/_components/form"
import { ErrorBanner } from "@/components/shared/error-banner"
import { StatusBadgeFromTone, type StatusPillTone } from "@/components/shared/status-pill"
import { XmlApiTablePagination } from "@/components/xml-apis/shared/xml-api-table-pagination"
import type {
  PosReconciliationItem,
  PosReconciliationRunDetail,
  PosReconciliationSummaryRow,
} from "@/components/xml-apis/pos-reconciliation/types"
import { Badge } from "@/components/ui/badge"
import {
  Collapsible,
  CollapsibleContent,
  CollapsibleTrigger,
} from "@/components/ui/collapsible"
import { Input } from "@/components/ui/input"
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { SETTINGS_INPUT_CLASS } from "@/components/settings/constants"
import { cn } from "@/lib/utils"

const listHref = "/dashboard/xml-apis/pos-reconciliation"
const filterInputClass = cn(SETTINGS_INPUT_CLASS, "h-8")

const includesFilter: FilterFn<PosReconciliationItem> = (row, columnId, value) => {
  if (!value) return true
  return String(row.getValue(columnId) ?? "")
    .toLowerCase()
    .includes(String(value).toLowerCase())
}

function reconStatusTone(status: string): StatusPillTone {
  if (status === "matched") return "success"
  if (status === "mismatch") return "danger"
  if (status === "missing_in_oxy" || status === "missing_in_pos") return "warning"
  return "muted"
}

const itemColumns: ColumnDef<PosReconciliationItem>[] = [
  { accessorKey: "id", header: "ID", filterFn: includesFilter },
  {
    accessorKey: "status",
    header: "Status",
    filterFn: includesFilter,
    cell: ({ row }) => (
      <StatusBadgeFromTone
        label={row.original.status.replace(/_/g, " ")}
        tone={reconStatusTone(row.original.status)}
      />
    ),
  },
  { accessorKey: "ruleType", header: "Rule Type", filterFn: includesFilter },
  { accessorKey: "userRef", header: "User Ref", filterFn: includesFilter },
  { accessorKey: "accountNumber", header: "Account Number", filterFn: includesFilter },
  { accessorKey: "currencyCode", header: "Currency", filterFn: includesFilter },
  { accessorKey: "isin", header: "ISIN", filterFn: includesFilter },
  { accessorKey: "assetClass", header: "Asset Class", filterFn: includesFilter },
  { accessorKey: "apiValue", header: "API Value", enableColumnFilter: false },
  { accessorKey: "oxyValue", header: "Oxy Value", enableColumnFilter: false },
  {
    accessorKey: "delta",
    header: "Delta",
    enableColumnFilter: false,
    cell: ({ row }) => {
      const delta = parseFloat(row.original.delta)
      const tone: StatusPillTone =
        Math.abs(delta) > 0.00000001 ? "warning" : "success"
      return <StatusBadgeFromTone label={row.original.delta} tone={tone} />
    },
  },
  { accessorKey: "reason", header: "Reason", filterFn: includesFilter },
]

function SummaryUserGroup({
  label,
  rows,
}: {
  label: string
  rows: PosReconciliationSummaryRow[]
}) {
  const [filters, setFilters] = React.useState<string[]>([])
  const matched = rows.reduce((s, r) => s + r.matchedCount, 0)
  const mismatch = rows.reduce((s, r) => s + r.mismatchCount, 0)
  const missing = rows.reduce((s, r) => s + r.missingOxyCount, 0)
  const delta = rows.reduce((s, r) => s + parseFloat(r.deltaTotal), 0)

  const filtered = rows.filter((row) => {
    const cells = [
      label,
      row.accountNumber,
      row.isin,
      row.assetClass,
      String(row.rowCount),
      row.apiTotal,
      row.oxyTotal,
      row.deltaTotal,
      String(row.matchedCount),
      String(row.mismatchCount),
      String(row.missingOxyCount),
    ]
    return filters.every((f, i) => {
      if (!f) return true
      return cells[i]?.toLowerCase().includes(f.toLowerCase())
    })
  })

  return (
    <Collapsible defaultOpen className="rounded-lg border">
      <CollapsibleTrigger className="flex w-full flex-wrap items-center justify-between gap-2 bg-muted/30 px-4 py-3 text-left hover:bg-muted/50">
        <span className="font-semibold">{label}</span>
        <div className="flex flex-wrap gap-2 text-xs">
          <Badge variant="outline">Rows: {rows.length}</Badge>
          <StatusBadgeFromTone label={`Matched: ${matched}`} tone="success" />
          <StatusBadgeFromTone
            label={`Mismatch: ${mismatch}`}
            tone={mismatch > 0 ? "danger" : "muted"}
          />
          <StatusBadgeFromTone
            label={`Missing In Oxy: ${missing}`}
            tone={missing > 0 ? "warning" : "muted"}
          />
          <StatusBadgeFromTone
            label={`Delta: ${delta.toFixed(8)}`}
            tone={Math.abs(delta) > 0.00000001 ? "warning" : "success"}
          />
        </div>
      </CollapsibleTrigger>
      <CollapsibleContent className="px-2 pb-2">
        <div className="overflow-x-auto">
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>User / Customer</TableHead>
                <TableHead>Account Number</TableHead>
                <TableHead>ISIN</TableHead>
                <TableHead>Asset Class</TableHead>
                <TableHead>Rows</TableHead>
                <TableHead>API Total</TableHead>
                <TableHead>Oxy Total</TableHead>
                <TableHead>Delta Total</TableHead>
                <TableHead>Matched</TableHead>
                <TableHead>Mismatch</TableHead>
                <TableHead>Missing In Oxy</TableHead>
              </TableRow>
              <TableRow>
                {Array.from({ length: 11 }).map((_, i) => (
                  <TableHead key={i} className="px-2 py-1">
                    <Input
                      className={filterInputClass}
                      placeholder="Filter"
                      value={filters[i] ?? ""}
                      onChange={(e) => {
                        const next = [...filters]
                        next[i] = e.target.value
                        setFilters(next)
                      }}
                    />
                  </TableHead>
                ))}
              </TableRow>
            </TableHeader>
            <TableBody>
              {filtered.map((row, idx) => (
                <TableRow key={`${row.accountNumber}-${row.isin}-${idx}`}>
                  <TableCell>{label}</TableCell>
                  <TableCell>{row.accountNumber}</TableCell>
                  <TableCell>{row.isin}</TableCell>
                  <TableCell>{row.assetClass}</TableCell>
                  <TableCell>{row.rowCount}</TableCell>
                  <TableCell className="font-mono text-xs">{row.apiTotal}</TableCell>
                  <TableCell className="font-mono text-xs">{row.oxyTotal}</TableCell>
                  <TableCell className="font-mono text-xs">{row.deltaTotal}</TableCell>
                  <TableCell>{row.matchedCount}</TableCell>
                  <TableCell>{row.mismatchCount}</TableCell>
                  <TableCell>{row.missingOxyCount}</TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </div>
      </CollapsibleContent>
    </Collapsible>
  )
}

function RowDetailsTable({ items }: { items: PosReconciliationItem[] }) {
  const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([])
  const [pagination, setPagination] = React.useState<PaginationState>({
    pageIndex: 0,
    pageSize: 20,
  })

  const table = useReactTable({
    data: items,
    columns: itemColumns,
    state: { columnFilters, pagination },
    getRowId: (r) => r.id,
    onColumnFiltersChange: setColumnFilters,
    onPaginationChange: setPagination,
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
  })

  const setFilter = (columnId: string, value: string) => {
    table.getColumn(columnId)?.setFilterValue(value || undefined)
    table.setPageIndex(0)
  }

  const headers = table.getHeaderGroups()[0]?.headers ?? []
  const filterable = [
    "id",
    "status",
    "ruleType",
    "userRef",
    "accountNumber",
    "currencyCode",
    "isin",
    "assetClass",
    "reason",
  ]

  return (
    <div className="space-y-4">
      <div className="overflow-x-auto rounded-lg border">
        <Table>
          <TableHeader>
            <TableRow className="bg-muted/40">
              {headers.map((h) => (
                <TableHead key={h.id} className="px-3 whitespace-nowrap">
                  {flexRender(h.column.columnDef.header, h.getContext())}
                </TableHead>
              ))}
            </TableRow>
            <TableRow className="bg-muted/20">
              {headers.map((h) => {
                const id = h.column.id
                return (
                  <TableHead key={h.id} className="px-2 py-1">
                    {filterable.includes(id) ? (
                      <Input
                        className={filterInputClass}
                        placeholder="Filter"
                        value={
                          (table.getColumn(id)?.getFilterValue() as string) ?? ""
                        }
                        onChange={(e) => setFilter(id, e.target.value)}
                      />
                    ) : null}
                  </TableHead>
                )
              })}
            </TableRow>
          </TableHeader>
          <TableBody>
            {table.getRowModel().rows.map((row) => (
              <TableRow key={row.id}>
                {row.getVisibleCells().map((cell) => (
                  <TableCell key={cell.id} className="px-3 py-2 whitespace-nowrap">
                    {flexRender(cell.column.columnDef.cell, cell.getContext())}
                  </TableCell>
                ))}
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </div>
      <XmlApiTablePagination table={table} />
    </div>
  )
}

type PosReconciliationDetailPageProps = {
  initialDetail?: PosReconciliationRunDetail | null
  initialErrorMessage?: string | null
}

export function PosReconciliationDetailPage({
  initialDetail = null,
  initialErrorMessage = null,
}: PosReconciliationDetailPageProps) {
  const detail = initialDetail

  if (!detail) {
    return (
      <div className="space-y-3">
        <ErrorBanner message={initialErrorMessage} />
        <p className="text-muted-foreground">Reconciliation run not found.</p>
      </div>
    )
  }

  const { run, items, summary } = detail
  const summaryByUser = summary.reduce<Record<string, typeof summary>>(
    (acc, row) => {
      const key = row.userCustomer
      if (!acc[key]) acc[key] = []
      acc[key].push(row)
      return acc
    },
    {}
  )

  return (
    <div className="pb-4">
      <FormPageHeader
        backHref={listHref}
        breadcrumb={[
          { label: "XML API" },
          { label: "POS Reconciliation", href: listHref },
          { label: `Run #${run.id}` },
        ]}
        titleIcon={<GitCompareArrows className="size-5 text-primary" />}
        title={`Run #${run.id} details`}
        description={
          <>
            Date: <strong>{run.runDate}</strong> · Bank API:{" "}
            <strong>
              {run.bankApiId}
              {run.bankApiName ? ` (${run.bankApiName})` : ""}
            </strong>{" "}
            · Upload: <strong>{run.uploadId}</strong>
          </>
        }
      />

      <Tabs defaultValue="rows" className="mt-6">
        <TabsList>
          <TabsTrigger value="rows">Row Details</TabsTrigger>
          <TabsTrigger value="summary">Summary (Account + ISIN)</TabsTrigger>
        </TabsList>
        <TabsContent value="rows" className="mt-4">
          <RowDetailsTable items={items} />
        </TabsContent>
        <TabsContent value="summary" className="mt-4 space-y-3">
          {Object.keys(summaryByUser).length ? (
            Object.entries(summaryByUser).map(([label, rows]) => (
              <SummaryUserGroup key={label} label={label} rows={rows} />
            ))
          ) : (
            <p className="text-sm text-muted-foreground">No summary records found.</p>
          )}
        </TabsContent>
      </Tabs>
    </div>
  )
}
