"use client"

import { useEffect, useState } from "react"
import { useRouter } from "next/navigation"
import Link from "next/link"
import { ArrowLeft, ExternalLink, Plus, RefreshCw, ShieldCheck, Trash2 } from "lucide-react"

import { grnsApi } from "@/lib/api/grns"
import { purchaseOrdersApi } from "@/lib/api/purchase-orders"
import { vendorsApi } from "@/lib/api/vendors"
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 { validateLine, grnHeaderSchema } from "@/lib/validations/grn"
import { cn } from "@/lib/utils"
import { CreateGrnLineInput, HoldStatus } from "@/types/grn"
import { PurchaseOrder, PurchaseOrderSummary } from "@/types/procurement"
import { Bin, ItemListItem, Uom, Vendor, Warehouse } from "@/types/master-data"

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

type Mode = "po" | "direct"
type LineTab = "lines" | "warranty"

/** Whole units a line's qty represents — one warranty number is captured per unit. */
function unitCount(qty: string): number {
  const n = Math.floor(Number(qty))
  return Number.isFinite(n) && n > 0 ? n : 0
}

/** One-shot hint next to the warranty button — shows on mount, then fades out on its own. */
function WarrantyHintBubble() {
  const [visible, setVisible] = useState(true)

  useEffect(() => {
    const timer = setTimeout(() => setVisible(false), 3000)
    return () => clearTimeout(timer)
  }, [])

  return (
    <div
      role="status"
      className={cn(
        "absolute bottom-full right-0 z-10 mb-2 flex w-max max-w-xs items-center gap-2 rounded-xl border border-info/40 bg-white p-3 shadow-xl transition-opacity duration-700",
        visible ? "opacity-100" : "pointer-events-none opacity-0"
      )}
    >
      <span className="flex size-7 shrink-0 items-center justify-center rounded-full bg-info/15 text-info">
        <ShieldCheck className="size-4" />
      </span>
      <span className="min-w-0 text-sm font-semibold text-info">Add warranty numbers for this item</span>
    </div>
  )
}

interface DraftLine {
  key: string
  poLineId: number | null
  itemId: number | null
  binId: number | null
  qty: string
  unitCost: string
  /** PO line price when prefilled from a PO; drives the variance hint. */
  poUnitPrice: number | null
  discountPct: string
  vatPct: string
  holdStatus: HoldStatus
  /** One entry per received unit, index-aligned; only meaningful when the item is warranty-tracked. */
  warrantyNumbers: string[]
}

/** Mirror of the server's line arithmetic — display only (docs/20 §3, server stays authoritative). */
function computeLine(l: DraftLine) {
  const qty = Number(l.qty) || 0
  const gross = Number(l.unitCost) || 0
  const disc = Number(l.discountPct) || 0
  const vat = Number(l.vatPct) || 0
  const netUnitCost = gross * (1 - disc / 100)
  const receivedValue = qty * netUnitCost
  const vatAmount = receivedValue * (vat / 100)
  return { netUnitCost, receivedValue, vatAmount, lineTotal: receivedValue + vatAmount }
}

let keySeq = 0
function newKey() {
  keySeq += 1
  return `gline-${keySeq}`
}

function emptyLine(): DraftLine {
  return {
    key: newKey(),
    poLineId: null,
    itemId: null,
    binId: null,
    qty: "",
    unitCost: "",
    poUnitPrice: null,
    discountPct: "0",
    vatPct: "0",
    holdStatus: "Available",
    warrantyNumbers: [],
  }
}

export default function NewGrnPage() {
  const router = useRouter()

  const [mode, setMode] = useState<Mode>("po")

  const [warehouses, setWarehouses] = useState<Warehouse[] | null>(null)
  const [items, setItems] = useState<ItemListItem[] | null>(null)
  const [uoms, setUoms] = useState<Uom[] | null>(null)
  const [vendors, setVendors] = useState<Vendor[] | null>(null)
  const [purchaseOrders, setPurchaseOrders] = useState<PurchaseOrderSummary[] | null>(null)
  const [bins, setBins] = useState<Bin[]>([])
  const [loadError, setLoadError] = useState<string | null>(null)

  const [warehouseId, setWarehouseId] = useState<number | null>(null)
  const [vendorId, setVendorId] = useState<number | null>(null)
  const [poId, setPoId] = useState<number | null>(null)
  const [poLoading, setPoLoading] = useState(false)
  const [lines, setLines] = useState<DraftLine[]>([emptyLine()])
  const [lineTab, setLineTab] = useState<LineTab>("lines")

  // Whole-GRN discount/VAT: entering either one here applies that same rate to every
  // line's discountPct/vatPct (clearing whatever was entered per-item), so it flows
  // through the normal per-line NetUnitCost/FIFO-layer costing instead of being a
  // separate header-only adjustment. Independent per field — setting one doesn't
  // touch the other. Cleared back to blank, the per-line fields become editable again.
  const [headerDiscountPct, setHeaderDiscountPct] = useState("")
  const [headerVatPct, setHeaderVatPct] = useState("")

  function applyHeaderDiscountPct(value: string) {
    setHeaderDiscountPct(value)
    const trimmed = value.trim()
    if (trimmed === "") return
    setLines((prev) => prev.map((l) => ({ ...l, discountPct: trimmed })))
  }

  function applyHeaderVatPct(value: string) {
    setHeaderVatPct(value)
    const trimmed = value.trim()
    if (trimmed === "") return
    setLines((prev) => prev.map((l) => ({ ...l, vatPct: trimmed })))
  }

  const [headerError, setHeaderError] = useState<string | null>(null)
  const [lineErrors, setLineErrors] = useState<Record<string, Record<string, string>>>({})
  const [submitError, setSubmitError] = useState<string | null>(null)
  const [submitting, setSubmitting] = useState(false)
  const [refreshingItems, setRefreshingItems] = useState(false)

  useEffect(() => {
    Promise.all([
      warehousesApi.list(),
      itemsApi.list({ pageSize: 200, status: "Active" }),
      uomsApi.list(),
      vendorsApi.list({ pageSize: 200, status: "Active" }),
      purchaseOrdersApi.list({ pageSize: 200 }),
    ])
      .then(([wh, it, uo, ve, po]) => {
        setWarehouses(wh.items)
        setItems(it.items)
        setUoms(uo.items)
        setVendors(ve.items)
        setPurchaseOrders(po.items.filter((p) => p.status === "Approved" || p.status === "PartiallyReceived"))
      })
      .catch((err) => setLoadError(errorMessage(err)))
  }, [])

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

  function switchMode(next: Mode) {
    setMode(next)
    setPoId(null)
    setVendorId(null)
    setLines([emptyLine()])
    setHeaderDiscountPct("")
    setHeaderVatPct("")
    setHeaderError(null)
    setLineErrors({})
  }

  async function handleSelectPo(nextPoId: number | null) {
    setPoId(nextPoId)
    if (!nextPoId) {
      setLines([emptyLine()])
      return
    }

    setPoLoading(true)
    setHeaderError(null)
    try {
      const po: PurchaseOrder = await purchaseOrdersApi.get(nextPoId)
      const openLines = po.lines.filter((l) => l.qtyReceived < l.qty)
      if (openLines.length === 0) {
        setHeaderError("This purchase order has no open (unreceived) lines.")
        setLines([])
        return
      }
      setWarehouseId((prev) => prev ?? openLines[0].warehouseId)
      setLines(
        openLines.map(
          (l): DraftLine => ({
            key: newKey(),
            poLineId: l.poLineId,
            itemId: l.itemId,
            binId: null,
            qty: String(l.qty - l.qtyReceived),
            unitCost: String(l.unitPrice),
            poUnitPrice: l.unitPrice,
            discountPct: headerDiscountPct.trim() || "0",
            vatPct: headerVatPct.trim() || "0",
            holdStatus: "Available",
            warrantyNumbers: [],
          })
        )
      )
    } catch (err) {
      setHeaderError(errorMessage(err))
    } finally {
      setPoLoading(false)
    }
  }

  // Re-pull the active items list so an item created in the other tab (via "New item")
  // becomes selectable without reloading the whole screen and losing the in-progress GRN.
  async function refreshItems() {
    setRefreshingItems(true)
    try {
      const res = await itemsApi.list({ pageSize: 200, status: "Active" })
      setItems(res.items)
      toast.success("Items refreshed", `${res.items.length} active item${res.items.length === 1 ? "" : "s"} loaded.`)
    } catch (err) {
      toast.error("Could not refresh items", errorMessage(err))
    } finally {
      setRefreshingItems(false)
    }
  }

  function updateLine(key: string, patch: Partial<DraftLine>) {
    setLines((prev) => prev.map((l) => (l.key === key ? { ...l, ...patch } : l)))
  }

  function removeLine(key: string) {
    setLines((prev) => prev.filter((l) => l.key !== key))
  }

  function itemFor(itemId: number | null) {
    return items?.find((i) => i.itemId === itemId) ?? null
  }

  function setWarrantyNumberAt(lineKey: string, index: number, value: string) {
    setLines((prev) =>
      prev.map((l) => {
        if (l.key !== lineKey) return l
        const next = [...l.warrantyNumbers]
        while (next.length <= index) next.push("")
        next[index] = value
        return { ...l, warrantyNumbers: next }
      })
    )
  }

  // Lines whose item is warranty-tracked and carry at least one unit — these are the rows
  // the "Warranty numbers" tab needs to capture, one input per unit.
  const warrantyLines = lines
    .map((l) => ({ line: l, item: itemFor(l.itemId), units: unitCount(l.qty) }))
    .filter((w) => w.item?.warranty === "Warranty" && w.units > 0)

  async function handleSubmit() {
    setSubmitError(null)
    setHeaderError(null)

    const header = grnHeaderSchema.safeParse({
      warehouseId: warehouseId ?? 0,
      vendorId: mode === "direct" ? vendorId : null,
      poId: mode === "po" ? poId : null,
    })
    if (!header.success) {
      setHeaderError(header.error.issues[0]?.message ?? "Check the header fields.")
      return
    }
    if (mode === "direct" && !vendorId) {
      setHeaderError("Select a vendor for a direct receipt.")
      return
    }
    if (mode === "po" && !poId) {
      setHeaderError("Select a purchase order.")
      return
    }
    if (lines.length === 0) {
      setSubmitError("Add at least one line.")
      return
    }

    const nextLineErrors: Record<string, Record<string, string>> = {}
    for (const line of lines) {
      const item = itemFor(line.itemId)
      const errors = validateLine({
        itemId: line.itemId,
        qty: line.qty,
        unitCost: line.unitCost,
        discountPct: line.discountPct,
        vatPct: line.vatPct,
        warranty: item?.warranty ?? null,
        warrantyNumbers: line.warrantyNumbers,
      })
      if (Object.keys(errors).length > 0) nextLineErrors[line.key] = errors
    }
    setLineErrors(nextLineErrors)
    if (Object.keys(nextLineErrors).length > 0) {
      // Jump to whichever tab actually shows the offending field(s).
      const onlyWarrantyErrors = Object.values(nextLineErrors).every(
        (errs) => Object.keys(errs).every((k) => k === "warrantyNumbers")
      )
      setLineTab(onlyWarrantyErrors ? "warranty" : "lines")
      setSubmitError("Fix the highlighted lines before submitting.")
      return
    }

    const payloadLines: CreateGrnLineInput[] = lines.map((l) => {
      const item = itemFor(l.itemId)
      return {
        poLineId: l.poLineId,
        itemId: l.itemId as number,
        binId: l.binId,
        qty: Number(l.qty),
        unitCost: Number(l.unitCost),
        discountPct: Number(l.discountPct) || 0,
        vatPct: Number(l.vatPct) || 0,
        holdStatus: l.holdStatus,
        warrantyNumbers:
          item?.warranty === "Warranty"
            ? l.warrantyNumbers.map((s) => s.trim()).filter((s) => s.length > 0)
            : null,
      }
    })

    setSubmitting(true)
    try {
      const grn = await grnsApi.create({
        poId: mode === "po" ? poId : null,
        vendorId: mode === "direct" ? vendorId : null,
        warehouseId: warehouseId as number,
        lines: payloadLines,
      })
      toast.success("GRN created", `${grn.docNo} is ready to confirm.`)
      router.push(`/dashboard/receiving/grn/${grn.grnId}`)
    } catch (err) {
      setSubmitError(errorMessage(err))
      toast.error("Could not create GRN", errorMessage(err))
    } finally {
      setSubmitting(false)
    }
  }

  const loading = !warehouses || !items || !uoms || !vendors || !purchaseOrders

  return (
    <div className="flex flex-col gap-6">
      <div className="flex items-center gap-3">
        <div>
          <h1 className="text-2xl font-bold text-foreground">New GRN</h1>
          <p className="text-base text-muted-foreground">Receive goods against a purchase order, or record a direct receipt (FR-GRN-01/02).</p>
        </div>
      </div>

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

      {loading && !loadError && <Skeleton className="h-12 w-full" />}

      {!loading && (
        <>
          <div className="flex w-fit gap-2 rounded-full border border-input bg-muted/40 p-1">
            <Button
              type="button"
              size="sm"
              variant={mode === "po" ? "default" : "ghost"}
              className="rounded-full"
              onClick={() => switchMode("po")}
            >
              Against PO
            </Button>
            <Button
              type="button"
              size="sm"
              variant={mode === "direct" ? "default" : "ghost"}
              className="rounded-full"
              onClick={() => switchMode("direct")}
            >
              Direct receipt
            </Button>
          </div>

          <div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
            {mode === "po" && (
              <div className="flex flex-col gap-2 sm:col-span-2">
                <Label className="text-base">Purchase order</Label>
                <Select<number | null> value={poId} onValueChange={(v) => handleSelectPo(v)}>
                  <SelectTrigger className="h-12! w-full text-base">
                    <SelectValue placeholder="Select an approved/partially received PO" />
                  </SelectTrigger>
                  <SelectContent>
                    {(purchaseOrders ?? []).map((p) => (
                      <SelectItem key={p.poId} value={p.poId} className="text-base">
                        {p.docNo} — Vendor #{p.vendorId} ({p.status})
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>
            )}

            {mode === "direct" && (
              <div className="flex flex-col gap-2 sm:col-span-2">
                <Label className="text-base">Vendor</Label>
                <Select<number | null> value={vendorId} onValueChange={(v) => setVendorId(v)}>
                  <SelectTrigger className="h-12! w-full text-base">
                    <SelectValue placeholder="Select vendor" />
                  </SelectTrigger>
                  <SelectContent>
                    {(vendors ?? []).map((v) => (
                      <SelectItem key={v.vendorId} value={v.vendorId} className="text-base">
                        {v.code} — {v.name}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>
            )}

            <div className="flex flex-col gap-2">
              <Label className="text-base">Warehouse</Label>
              <Select<number | null> value={warehouseId} onValueChange={(v) => setWarehouseId(v)}>
                <SelectTrigger className="h-12! w-full text-base">
                  <SelectValue placeholder="Select warehouse" />
                </SelectTrigger>
                <SelectContent>
                  {(warehouses ?? []).map((w) => (
                    <SelectItem key={w.warehouseId} value={w.warehouseId} className="text-base">
                      {w.code} — {w.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          </div>

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

          <div className="flex flex-col gap-2 rounded-lg border border-dashed border-input p-4 sm:flex-row sm:items-end sm:gap-4">
            <div className="flex flex-1 flex-col gap-2">
              <Label className="text-base">Whole-GRN discount %</Label>
              <Input
                type="number"
                min="0"
                max="100"
                step="any"
                value={headerDiscountPct}
                onChange={(e) => applyHeaderDiscountPct(e.target.value)}
                placeholder="Applies to every line"
                className="h-11 text-base"
              />
            </div>
            <div className="flex flex-1 flex-col gap-2">
              <Label className="text-base">Whole-GRN VAT %</Label>
              <Input
                type="number"
                min="0"
                max="100"
                step="any"
                value={headerVatPct}
                onChange={(e) => applyHeaderVatPct(e.target.value)}
                placeholder="Applies to every line"
                className="h-11 text-base"
              />
            </div>
            <p className="text-sm text-muted-foreground sm:max-w-64">
              Setting either one applies that rate to every line (replacing any per-item value) and locks the per-item field. Clear it to edit lines individually again.
            </p>
          </div>

          <div className="flex flex-col gap-3">
            <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
              <div>
                <h2 className="text-base font-semibold text-foreground">Lines</h2>
                {mode === "po" && (
                  <p className="text-sm text-muted-foreground">
                    PO lines are prefilled. Use “Add line” to receive an item that isn’t on the PO.
                  </p>
                )}
              </div>
              <div className="flex flex-wrap items-center gap-2">
                {/* Off-PO items are allowed on a PO-based GRN — the server treats a line with
                    no poLineId as a direct receipt (docs/10 FR-GRN-01, revised). */}
                <Button
                  type="button"
                  variant="outline"
                  onClick={() =>
                    setLines((prev) => [
                      ...prev,
                      {
                        ...emptyLine(),
                        discountPct: headerDiscountPct.trim() || "0",
                        vatPct: headerVatPct.trim() || "0",
                      },
                    ])
                  }
                >
                  <Plus className="size-5" />
                  Add line
                </Button>
                {/* Create a brand-new item in a separate tab, then refresh to pick it up. */}
                <Button
                  type="button"
                  variant="outline"
                  onClick={() => window.open("/dashboard/products/new", "_blank", "noopener,noreferrer")}
                >
                  <ExternalLink className="size-5" />
                  New item
                </Button>
                <Button
                  type="button"
                  variant="outline"
                  size="icon"
                  onClick={refreshItems}
                  disabled={refreshingItems}
                  aria-label="Refresh items"
                  title="Refresh items"
                >
                  <RefreshCw className={cn("size-5", refreshingItems && "animate-spin")} />
                </Button>
              </div>
            </div>

            <div className="flex w-fit gap-2 rounded-full border border-input bg-muted/40 p-1">
              <Button
                type="button"
                size="sm"
                variant={lineTab === "lines" ? "default" : "ghost"}
                className="rounded-full"
                onClick={() => setLineTab("lines")}
              >
                Lines
              </Button>
              <Button
                type="button"
                size="sm"
                variant={lineTab === "warranty" ? "default" : "ghost"}
                className="rounded-full"
                onClick={() => setLineTab("warranty")}
              >
                Warranty numbers
                {warrantyLines.length > 0 && (
                  <Badge variant="outline" className="ml-1.5 h-5 px-1.5 text-xs">
                    {warrantyLines.reduce((sum, w) => sum + w.units, 0)}
                  </Badge>
                )}
              </Button>
            </div>

            {poLoading && <Skeleton className="h-24 w-full" />}

            {!poLoading && lineTab === "lines" && lines.length > 0 && (
              <div className="overflow-x-auto">
                <Table className="text-sm">
                  <TableHeader>
                    <TableRow>
                      <TableHead className="h-12 w-56 px-3 text-sm">Item</TableHead>
                      <TableHead className="h-12 w-24 px-3 text-sm">UOM</TableHead>
                      <TableHead className="h-12 w-28 px-3 text-sm">Bin</TableHead>
                      <TableHead className="h-12 w-88 px-3 text-sm">Qty</TableHead>
                      <TableHead className="h-12 w-77 px-3 text-sm">Unit cost</TableHead>
                      <TableHead className="h-12 w-44 px-3 text-sm">Disc %</TableHead>
                      <TableHead className="h-12 w-44 px-3 text-sm">VAT %</TableHead>
                      <TableHead className="h-12 w-28 px-3 text-sm text-right">Line total</TableHead>
                      <TableHead className="h-12 w-56 px-3 text-sm">Hold status</TableHead>
                      <TableHead className="h-12 w-6 px-1 text-sm">Action</TableHead>
                      <TableHead className="h-12 w-10 px-3" />
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {lines.map((line) => {
                      const item = itemFor(line.itemId)
                      const errors = lineErrors[line.key] ?? {}
                      return (
                        <TableRow key={line.key}>
                          <TableCell className="px-3 py-3 align-top">
                            {line.poLineId ? (
                              <div className="flex h-11 items-center gap-2 text-sm">
                                {item ? `${item.sku} — ${item.name}` : `Item #${line.itemId}`}
                                {item?.warranty === "Warranty" && (
                                  <Badge variant="outline" className="text-xs">Warranty</Badge>
                                )}
                              </div>
                            ) : (
                              <>
                                <Select<number | null> value={line.itemId} onValueChange={(v) => updateLine(line.key, { itemId: v })}>
                                  <SelectTrigger className="h-11! w-full text-sm" aria-invalid={!!errors.itemId}>
                                    <SelectValue placeholder="Select item" />
                                  </SelectTrigger>
                                  <SelectContent>
                                    {(items ?? []).map((i) => (
                                      <SelectItem key={i.itemId} value={i.itemId} className="text-sm">
                                        {i.sku} — {i.name}
                                        {i.warranty === "Warranty" ? " (Warranty)" : ""}
                                      </SelectItem>
                                    ))}
                                  </SelectContent>
                                </Select>
                                {item?.warranty === "Warranty" && (
                                  <Badge variant="outline" className="mt-1.5 text-xs">Warranty</Badge>
                                )}
                                <FieldError errors={[errors.itemId ? { message: errors.itemId } : undefined]} />
                              </>
                            )}
                          </TableCell>
                          <TableCell className="px-3 py-3 align-top">
                            <div className="flex h-11 items-center text-sm text-muted-foreground">
                              {baseUomLabel(items ?? [], uoms ?? [], line.itemId)}
                            </div>
                          </TableCell>
                          <TableCell className="px-3 py-3 align-top">
                            <Select<number | null> value={line.binId} onValueChange={(v) => updateLine(line.key, { binId: v })}>
                              <SelectTrigger className="h-11! w-full text-sm">
                                <SelectValue placeholder="None" />
                              </SelectTrigger>
                              <SelectContent>
                                {bins.map((b) => (
                                  <SelectItem key={b.binId} value={b.binId} className="text-sm">
                                    {b.code}
                                  </SelectItem>
                                ))}
                              </SelectContent>
                            </Select>
                          </TableCell>
                          <TableCell className="px-3 py-3 align-top">
                            <Input
                              type="number"
                              min="0"
                              step="any"
                              value={line.qty}
                              aria-invalid={!!errors.qty}
                              onChange={(e) => updateLine(line.key, { qty: e.target.value })}
                              className="h-11 text-sm"
                            />
                            <FieldError errors={[errors.qty ? { message: errors.qty } : undefined]} />
                          </TableCell>
                          <TableCell className="px-3 py-3 align-top">
                            <Input
                              type="number"
                              min="0"
                              step="any"
                              value={line.unitCost}
                              aria-invalid={!!errors.unitCost}
                              onChange={(e) => updateLine(line.key, { unitCost: e.target.value })}
                              className="h-11 text-sm"
                            />
                            <FieldError errors={[errors.unitCost ? { message: errors.unitCost } : undefined]} />
                            {line.poUnitPrice !== null && Number(line.unitCost) !== line.poUnitPrice && (
                              <p className="mt-1 text-xs text-warning">
                                PO price {line.poUnitPrice.toFixed(2)} — variance recorded
                              </p>
                            )}
                          </TableCell>
                          <TableCell className="px-3 py-3 align-top">
                            <Input
                              type="number"
                              min="0"
                              max="100"
                              step="any"
                              value={line.discountPct}
                              aria-invalid={!!errors.discountPct}
                              onChange={(e) => updateLine(line.key, { discountPct: e.target.value })}
                              disabled={headerDiscountPct.trim() !== ""}
                              title={headerDiscountPct.trim() !== "" ? "Driven by the whole-GRN discount % above" : undefined}
                              className="h-11 text-sm"
                            />
                            <FieldError errors={[errors.discountPct ? { message: errors.discountPct } : undefined]} />
                          </TableCell>
                          <TableCell className="px-3 py-3 align-top">
                            <Input
                              type="number"
                              min="0"
                              max="100"
                              step="any"
                              value={line.vatPct}
                              aria-invalid={!!errors.vatPct}
                              onChange={(e) => updateLine(line.key, { vatPct: e.target.value })}
                              disabled={headerVatPct.trim() !== ""}
                              title={headerVatPct.trim() !== "" ? "Driven by the whole-GRN VAT % above" : undefined}
                              className="h-11 text-sm"
                            />
                            <FieldError errors={[errors.vatPct ? { message: errors.vatPct } : undefined]} />
                          </TableCell>
                          <TableCell className="px-3 py-3 align-top text-right tabular-nums">
                            {(() => {
                              const c = computeLine(line)
                              return (
                                <div className="flex h-11 flex-col justify-center">
                                  <span>{c.lineTotal.toFixed(2)}</span>
                                  <span className="text-xs text-muted-foreground">
                                    net {c.receivedValue.toFixed(2)} + VAT {c.vatAmount.toFixed(2)}
                                  </span>
                                </div>
                              )
                            })()}
                          </TableCell>
                          <TableCell className="px-3 py-3 align-top">
                            <Select<HoldStatus>
                              value={line.holdStatus}
                              onValueChange={(v) => v && updateLine(line.key, { holdStatus: v })}
                            >
                              <SelectTrigger className="h-11! w-full text-sm">
                                <SelectValue />
                              </SelectTrigger>
                              <SelectContent>
                                <SelectItem value="Available" className="text-sm">Available</SelectItem>
                                <SelectItem value="OnHold" className="text-sm">On hold (inspection)</SelectItem>
                              </SelectContent>
                            </Select>
                          </TableCell>
                          <TableCell className="py-3 pr-0 pl-1 align-top">
                            {item?.warranty === "Warranty" ? (
                              <div className="relative flex flex-col gap-1">
                                <Tooltip>
                                  <TooltipTrigger
                                    render={
                                      <Button
                                        type="button"
                                        variant="outline"
                                        size="icon"
                                        onClick={() => setLineTab("warranty")}
                                        aria-label="Add warranty numbers"
                                      />
                                    }
                                  >
                                    <ShieldCheck className="size-4" />
                                  </TooltipTrigger>
                                  <TooltipContent>Add warranty numbers</TooltipContent>
                                </Tooltip>
                                {errors.warrantyNumbers && (
                                  <FieldError errors={[{ message: errors.warrantyNumbers }]} />
                                )}
                                <WarrantyHintBubble />
                              </div>
                            ) : (
                              <span className="text-sm text-muted-foreground">—</span>
                            )}
                          </TableCell>
                          <TableCell className="py-3 pr-3 pl-0 align-top">
                            <Button type="button" variant="ghost" size="icon" onClick={() => removeLine(line.key)} aria-label="Remove line">
                              <Trash2 className="size-5" />
                            </Button>
                          </TableCell>
                        </TableRow>
                      )
                    })}
                  </TableBody>
                </Table>
              </div>
            )}

            {!poLoading && lineTab === "warranty" && (
              <div className="flex flex-col gap-3">
                <Button
                  type="button"
                  variant="outline"
                  size="sm"
                  className="w-fit self-end rounded-full"
                  onClick={() => setLineTab("lines")}
                >
                  <ArrowLeft className="size-4" />
                  Back to lines
                </Button>

                {warrantyLines.length === 0 ? (
                  <p className="rounded-lg border border-dashed p-5 text-base text-muted-foreground">
                    No warranty-tracked items on this GRN yet — add a line for an item marked
                    “Warranty” to capture its numbers here.
                  </p>
                ) : (
                  <div className="flex flex-col gap-6">
                    {warrantyLines.map(({ line, item, units }) => {
                      const errors = lineErrors[line.key] ?? {}
                      return (
                        <div key={line.key} className="flex flex-col gap-2">
                          <div className="text-sm font-semibold text-foreground">
                            {item ? `${item.sku} — ${item.name}` : `Item #${line.itemId}`}
                          </div>
                          <div className="overflow-x-auto">
                            <Table className="text-sm">
                              <TableHeader>
                                <TableRow>
                                  <TableHead className="h-10 w-20 px-3 text-sm">Unit</TableHead>
                                  <TableHead className="h-10 px-3 text-sm">Warranty number</TableHead>
                                </TableRow>
                              </TableHeader>
                              <TableBody>
                                {Array.from({ length: units }, (_, i) => (
                                  <TableRow key={`${line.key}-${i}`}>
                                    <TableCell className="px-3 py-3 align-top text-sm text-muted-foreground">
                                      {i + 1} of {units}
                                    </TableCell>
                                    <TableCell className="px-3 py-3 align-top">
                                      <Input
                                        value={line.warrantyNumbers[i] ?? ""}
                                        aria-invalid={!!errors.warrantyNumbers}
                                        onChange={(e) => setWarrantyNumberAt(line.key, i, e.target.value)}
                                        placeholder="e.g. WTY-000123"
                                        className="h-10 max-w-xs text-sm"
                                      />
                                      {i === units - 1 && (
                                        <FieldError
                                          errors={[errors.warrantyNumbers ? { message: errors.warrantyNumbers } : undefined]}
                                        />
                                      )}
                                    </TableCell>
                                  </TableRow>
                                ))}
                              </TableBody>
                            </Table>
                          </div>
                        </div>
                      )
                    })}
                  </div>
                )}

                <Button
                  type="button"
                  variant="outline"
                  size="sm"
                  className="w-fit self-end rounded-full"
                  onClick={() => setLineTab("lines")}
                >
                  <ArrowLeft className="size-4" />
                  Back to lines
                </Button>
              </div>
            )}

            {!poLoading && lineTab === "lines" && lines.length > 0 && (
              <div className="flex justify-end gap-3 border-t border-border pt-4 text-base">
                <span className="text-muted-foreground">Document total (incl. VAT)</span>
                <span className="font-semibold tabular-nums">
                  {lines.reduce((sum, l) => sum + computeLine(l).lineTotal, 0).toFixed(2)}
                </span>
              </div>
            )}
          </div>

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

          {lineTab === "lines" && (
            <div className="flex justify-end gap-3">
              <Link href="/dashboard/receiving/grn" className={cn(buttonVariants({ variant: "outline", size: "lg" }))}>
                Cancel
              </Link>
              <Button size="lg" type="button" onClick={handleSubmit} disabled={submitting}>
                {submitting ? "Creating…" : "Create GRN"}
              </Button>
            </div>
          )}
        </>
      )}
    </div>
  )
}
