"use client"

import { useEffect, useRef, useState } from "react"
import { useParams } from "next/navigation"
import Link from "next/link"
import { BookOpen, CheckCircle2, CircleDollarSign, PackageCheck, PackageX, ShieldAlert, XCircle } from "lucide-react"

import { grnsApi } from "@/lib/api/grns"
import { warehousesApi } from "@/lib/api/warehouses"
import { itemsApi } from "@/lib/api/items"
import { uomsApi } from "@/lib/api/uoms"
import { baseUomLabel } from "@/lib/uom-label"
import { errorMessage } from "@/lib/error-map"
import { formatAmount } from "@/lib/format"
import { cn } from "@/lib/utils"
import { ConfirmGrnResponse, Grn, GrnPayment } from "@/types/grn"
import { Bin, ItemListItem, Uom } from "@/types/master-data"

import { Badge } from "@/components/ui/badge"
import { Button, buttonVariants } from "@/components/ui/button"
import { Skeleton } from "@/components/ui/skeleton"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { toast } from "@/components/ui/toast"
import { GrnPaymentStatusBadge, GrnStatusBadge, HoldStatusBadge } from "@/components/receiving/status-badges"
import { GrnPaymentDialog } from "@/components/receiving/GrnPaymentDialog"

export default function GrnDetailPage() {
  const params = useParams<{ id: string }>()
  const grnId = Number(params.id)

  const [grn, setGrn] = useState<Grn | null>(null)
  const [items, setItems] = useState<ItemListItem[]>([])
  const [uoms, setUoms] = useState<Uom[]>([])
  const [bins, setBins] = useState<Bin[]>([])
  const [error, setError] = useState<string | null>(null)

  const [confirming, setConfirming] = useState(false)
  const [confirmResult, setConfirmResult] = useState<ConfirmGrnResponse | null>(null)
  const [releasingLineId, setReleasingLineId] = useState<number | null>(null)

  const [payments, setPayments] = useState<GrnPayment[]>([])
  const [payDialogOpen, setPayDialogOpen] = useState(false)

  // Stable per detail-page-session key so a retried confirm click doesn't double-post.
  const idempotencyKey = useRef(crypto.randomUUID())

  useEffect(() => {
    if (!Number.isFinite(grnId)) return
    grnsApi.get(grnId).then(setGrn).catch((err) => setError(errorMessage(err)))
    Promise.all([itemsApi.list({ pageSize: 200 }), uomsApi.list()])
      .then(([it, uo]) => {
        setItems(it.items)
        setUoms(uo.items)
      })
      .catch(() => {})
  }, [grnId])

  useEffect(() => {
    if (!grn) return
    warehousesApi.listBins(grn.warehouseId).then(setBins).catch(() => setBins([]))
  }, [grn?.warehouseId])

  useEffect(() => {
    if (!grn || grn.status === "Draft") return
    grnsApi.listPayments(grn.grnId).then(setPayments).catch(() => setPayments([]))
  }, [grn?.grnId, grn?.status])

  function handlePaid(_updated: Grn, payment: GrnPayment) {
    setGrn((prev) =>
      prev ? { ...prev, paidAmount: prev.paidAmount + payment.amount, balanceAmount: prev.balanceAmount - payment.amount } : prev
    )
    setPayments((prev) => [payment, ...prev])
  }

  function itemFor(itemId: number) {
    return items.find((i) => i.itemId === itemId)
  }
  function binFor(binId: number | null) {
    if (!binId) return "—"
    return bins.find((b) => b.binId === binId)?.code ?? `#${binId}`
  }

  async function handleConfirm() {
    if (!grn) return
    setError(null)
    setConfirming(true)
    try {
      const result = await grnsApi.confirm(grn.grnId, idempotencyKey.current)
      setConfirmResult(result)
      setGrn((prev) =>
        prev ? { ...prev, status: result.status, glJournalNo: result.glJournalNo, balanceAmount: result.balanceAmount } : prev
      )
      toast.success("GRN confirmed", `${result.createdLayers.length} layer(s) posted to stock. Journal ${result.glJournalNo}.`)
    } catch (err) {
      setError(errorMessage(err))
      toast.error("Could not confirm GRN", errorMessage(err))
    } finally {
      setConfirming(false)
    }
  }

  async function handleRelease(grnLineId: number, action: "Release" | "Reject") {
    if (!grn) return
    setError(null)
    setReleasingLineId(grnLineId)
    try {
      const result = await grnsApi.releaseLine(grn.grnId, grnLineId, action)
      setGrn((prev) =>
        prev
          ? { ...prev, lines: prev.lines.map((l) => (l.grnLineId === grnLineId ? { ...l, holdStatus: result.holdStatus } : l)) }
          : prev
      )
      toast.success(action === "Release" ? "Line released" : "Line rejected", `Hold status is now ${result.holdStatus}.`)
    } catch (err) {
      setError(errorMessage(err))
      toast.error("Could not update line", errorMessage(err))
    } finally {
      setReleasingLineId(null)
    }
  }

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

  if (!grn) {
    return (
      <div className="flex flex-col gap-3">
        <Skeleton className="h-10 w-72" />
        <Skeleton className="h-48 w-full" />
      </div>
    )
  }

  return (
    <div className="flex flex-col gap-6">
      <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
        <div className="flex items-center gap-3">
          <div>
            <div className="flex items-center gap-3">
              <h1 className="text-2xl font-bold text-foreground">{grn.docNo}</h1>
              <GrnStatusBadge status={grn.status} />
              {grn.status !== "Draft" && <GrnPaymentStatusBadge paidAmount={grn.paidAmount} balanceAmount={grn.balanceAmount} />}
            </div>
            <p className="text-base text-muted-foreground">
              {grn.poId ? `Against PO #${grn.poId}` : "Direct receipt"} — Vendor #{grn.vendorId} — Warehouse #{grn.warehouseId}
            </p>
          </div>
        </div>

        <div className="flex items-center gap-2">
          {grn.status !== "Draft" && (
            <>
              <Link
                href="/dashboard/ledgers/general-ledger"
                className={cn(buttonVariants({ variant: "outline", size: "lg" }))}
                title="View this GRN's postings in the General Ledger report"
              >
                <BookOpen className="size-5" />
                View in Ledger
              </Link>
              {grn.balanceAmount > 0 && (
                <Button size="lg" onClick={() => setPayDialogOpen(true)}>
                  <CircleDollarSign className="size-5" />
                  Pay
                </Button>
              )}
            </>
          )}
          {grn.status === "Draft" && (
            <Button size="lg" onClick={handleConfirm} disabled={confirming}>
              <PackageCheck className="size-5" />
              {confirming ? "Confirming…" : "Confirm GRN"}
            </Button>
          )}
        </div>
      </div>

      <GrnPaymentDialog grn={grn} open={payDialogOpen} onOpenChange={setPayDialogOpen} onPaid={handlePaid} />

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

      {confirmResult && (
        <div className="flex flex-col gap-2 rounded-xl border border-success/30 bg-success/5 p-5">
          <div className="flex items-center gap-2 text-success">
            <CheckCircle2 className="size-6" />
            <p className="text-base font-semibold">Confirmed — stock layers created (FR-GRN-06)</p>
          </div>
          <div className="text-sm text-muted-foreground">
            Layers: {confirmResult.createdLayers.map((l) => `#${l.layerId} (${l.qtyReceived} @ ${l.unitCost})`).join(", ")}
          </div>
          <div className="text-sm text-muted-foreground">Ledger refs: {confirmResult.ledgerRefs.join(", ")}</div>
          <div className="text-sm text-muted-foreground">GL journal entry: {confirmResult.glJournalNo}</div>
          {confirmResult.poStatus && <div className="text-sm text-muted-foreground">PO status: {confirmResult.poStatus}</div>}
        </div>
      )}

      <div className="overflow-x-auto">
      <Table className="text-base">
        <TableHeader>
          <TableRow>
            <TableHead className="h-12 px-3 text-sm">Item</TableHead>
            <TableHead className="h-12 px-3 text-sm">UOM</TableHead>
            <TableHead className="h-12 px-3 text-sm">Bin</TableHead>
            <TableHead className="h-12 px-3 text-sm">Qty</TableHead>
            <TableHead className="h-12 px-3 text-sm text-right">Unit cost</TableHead>
            <TableHead className="h-12 px-3 text-sm text-right">Disc %</TableHead>
            <TableHead className="h-12 px-3 text-sm text-right">Net cost</TableHead>
            <TableHead className="h-12 px-3 text-sm text-right">Received value</TableHead>
            <TableHead className="h-12 px-3 text-sm text-right">VAT</TableHead>
            <TableHead className="h-12 px-3 text-sm text-right">Line total</TableHead>
            <TableHead className="h-12 px-3 text-sm">Hold status</TableHead>
            {grn.status === "Confirmed" && <TableHead className="h-12 px-3 text-sm">Actions</TableHead>}
          </TableRow>
        </TableHeader>
        <TableBody>
          {grn.lines.map((line) => {
            const item = itemFor(line.itemId)
            return (
              <TableRow key={line.grnLineId}>
                <TableCell className="px-3 py-3.5">
                  <div className="flex items-center gap-2">
                    {item ? `${item.sku} — ${item.name}` : `Item #${line.itemId}`}
                    {item?.warranty === "Warranty" && <Badge variant="outline" className="text-xs">Warranty</Badge>}
                  </div>
                  {line.warrantyNumbers.length > 0 && (
                    <p
                      className="mt-1 text-xs text-muted-foreground"
                      title={line.warrantyNumbers.map((w) => `${w.warrantyNo} (${w.warrantyPeriodMonths}mo)`).join(", ")}
                    >
                      {line.warrantyNumbers.length} warranty number{line.warrantyNumbers.length === 1 ? "" : "s"} captured
                    </p>
                  )}
                </TableCell>
                <TableCell className="px-3 py-3.5">{baseUomLabel(items, uoms, line.itemId)}</TableCell>
                <TableCell className="px-3 py-3.5">{binFor(line.binId)}</TableCell>
                <TableCell className="px-3 py-3.5">{line.qty}</TableCell>
                <TableCell className="px-3 py-3.5 text-right tabular-nums">
                  {line.unitCost.toFixed(2)}
                  {line.poUnitPrice !== null && line.priceVariance !== 0 && (
                    <span className="block text-xs text-warning">
                      PO {line.poUnitPrice.toFixed(2)} · var {line.priceVariance > 0 ? "+" : ""}{line.priceVariance.toFixed(2)}
                    </span>
                  )}
                </TableCell>
                <TableCell className="px-3 py-3.5 text-right tabular-nums">{line.discountPct.toFixed(2)}</TableCell>
                <TableCell className="px-3 py-3.5 text-right tabular-nums">{line.netUnitCost.toFixed(2)}</TableCell>
                <TableCell className="px-3 py-3.5 text-right tabular-nums">{line.receivedValue.toFixed(2)}</TableCell>
                <TableCell className="px-3 py-3.5 text-right tabular-nums">
                  {line.vatAmount.toFixed(2)}
                  <span className="block text-xs text-muted-foreground">{line.vatPct.toFixed(2)}%</span>
                </TableCell>
                <TableCell className="px-3 py-3.5 text-right tabular-nums font-medium">{line.lineTotal.toFixed(2)}</TableCell>
                <TableCell className="px-3 py-3.5">
                  <HoldStatusBadge status={line.holdStatus} />
                </TableCell>
                {grn.status === "Confirmed" && (
                  <TableCell className="px-3 py-3.5">
                    {line.holdStatus === "OnHold" ? (
                      <div className="flex items-center gap-1">
                        <Button
                          type="button"
                          variant="success"
                          size="sm"
                          disabled={releasingLineId === line.grnLineId}
                          onClick={() => handleRelease(line.grnLineId, "Release")}
                        >
                          <ShieldAlert className="size-4" />
                          Release
                        </Button>
                        <Button
                          type="button"
                          variant="destructive"
                          size="sm"
                          disabled={releasingLineId === line.grnLineId}
                          onClick={() => handleRelease(line.grnLineId, "Reject")}
                        >
                          <XCircle className="size-4" />
                          Reject
                        </Button>
                      </div>
                    ) : line.holdStatus === "Rejected" ? (
                      <Link
                        href={`/dashboard/procurement/purchase-returns/new?grnId=${grn.grnId}&grnLineId=${line.grnLineId}`}
                        className={cn(buttonVariants({ variant: "outline", size: "sm" }))}
                      >
                        <PackageX className="size-4" />
                        Create Return
                      </Link>
                    ) : (
                      <span className="text-sm text-muted-foreground">—</span>
                    )}
                  </TableCell>
                )}
              </TableRow>
            )
          })}
        </TableBody>
      </Table>
      </div>

      <div className="flex flex-wrap justify-end gap-8 border-t border-border pt-4 text-base">
        <div className="flex gap-3">
          <span className="text-muted-foreground">Stock value (excl. VAT)</span>
          <span className="tabular-nums">{grn.lines.reduce((s, l) => s + l.receivedValue, 0).toFixed(2)}</span>
        </div>
        <div className="flex gap-3">
          <span className="text-muted-foreground">VAT</span>
          <span className="tabular-nums">{grn.lines.reduce((s, l) => s + l.vatAmount, 0).toFixed(2)}</span>
        </div>
        <div className="flex gap-3">
          <span className="text-muted-foreground">Document total</span>
          <span className="font-semibold tabular-nums">{grn.lines.reduce((s, l) => s + l.lineTotal, 0).toFixed(2)}</span>
        </div>
        {grn.status !== "Draft" && (
          <>
            <div className="flex gap-3">
              <span className="text-muted-foreground">Amount paid</span>
              <span className="tabular-nums">{formatAmount(grn.paidAmount)}</span>
            </div>
            <div className="flex gap-3">
              <span className="text-muted-foreground">Balance due</span>
              <span className="font-semibold tabular-nums">{formatAmount(grn.balanceAmount)}</span>
            </div>
          </>
        )}
      </div>

      {grn.status !== "Draft" && payments.length > 0 && (
        <div className="flex flex-col gap-3">
          <h2 className="text-lg font-semibold text-foreground">Payment History</h2>
          <div className="overflow-x-auto">
            <Table className="text-base">
              <TableHeader>
                <TableRow>
                  <TableHead className="h-12 px-3 text-sm">Date</TableHead>
                  <TableHead className="h-12 px-3 text-sm text-right">Amount</TableHead>
                  <TableHead className="h-12 px-3 text-sm">Account</TableHead>
                  <TableHead className="h-12 px-3 text-sm">Reference</TableHead>
                  <TableHead className="h-12 px-3 text-sm">GL Journal</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {payments.map((p) => (
                  <TableRow key={p.grnPaymentId}>
                    <TableCell className="px-3 py-3.5">{new Date(p.paymentDate).toLocaleString()}</TableCell>
                    <TableCell className="px-3 py-3.5 text-right tabular-nums">{formatAmount(p.amount)}</TableCell>
                    <TableCell className="px-3 py-3.5">{p.bankAccountName}</TableCell>
                    <TableCell className="px-3 py-3.5">{p.reference ?? "—"}</TableCell>
                    <TableCell className="px-3 py-3.5">{p.glJournalNo ?? "—"}</TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </div>
        </div>
      )}
    </div>
  )
}
