"use client"

import { useEffect, useState } from "react"
import { useParams, useRouter } from "next/navigation"
import Link from "next/link"
import { AlertTriangle, ArrowLeft, Ban, Check, Plus, Save, Trash2 } from "lucide-react"
import { isPoEditable, purchaseOrdersApi } from "@/lib/api/purchase-orders"
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 { vendorsApi } from "@/lib/api/vendors"
import { errorMessage } from "@/lib/error-map"
import { validatePoLine } from "@/lib/validations/procurement"
import { cn } from "@/lib/utils"
import { CreatePoLineInput, PurchaseOrder } from "@/types/procurement"
import { ItemListItem, Uom, Vendor, Warehouse } from "@/types/master-data"

import { AlertDialog, AlertDialogContent, AlertDialogTrigger } from "@/components/ui/alert-dialog"
import { Button, buttonVariants } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
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 { PoStatusBadge } from "@/components/procurement/status-badges"

interface DraftLine {
  key: string
  poLineId: number | null
  itemId: number | null
  warehouseId: number | null
  qty: string
  unitPrice: string
  tax: string
  qtyReceived: number
}

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

export default function PurchaseOrderDetailPage() {
  const params = useParams<{ id: string }>()
  const router = useRouter()
  const poId = Number(params.id)

  const [po, setPo] = useState<PurchaseOrder | null>(null)
  const [etag, setEtag] = useState<string | null>(null)
  const [items, setItems] = useState<ItemListItem[]>([])
  const [uoms, setUoms] = useState<Uom[]>([])
  const [warehouses, setWarehouses] = useState<Warehouse[]>([])
  const [vendors, setVendors] = useState<Vendor[]>([])
  const [loadError, setLoadError] = useState<string | null>(null)

  const [lines, setLines] = useState<DraftLine[]>([])
  const [lineErrors, setLineErrors] = useState<Record<string, Record<string, string>>>({})
  const [conflict, setConflict] = useState(false)
  const [saveError, setSaveError] = useState<string | null>(null)
  const [saving, setSaving] = useState(false)

  const [showCancelForm, setShowCancelForm] = useState(false)
  const [cancelReason, setCancelReason] = useState("")
  const [cancelling, setCancelling] = useState(false)
  const [submitting, setSubmitting] = useState(false)
  const [deleting, setDeleting] = useState(false)

  function toDraftLines(order: PurchaseOrder): DraftLine[] {
    return order.lines.map((l) => ({
      key: newKey(),
      poLineId: l.poLineId,
      itemId: l.itemId,
      warehouseId: l.warehouseId,
      qty: String(l.qty),
      unitPrice: String(l.unitPrice),
      tax: String(l.tax),
      qtyReceived: l.qtyReceived,
    }))
  }

  function load() {
    setLoadError(null)
    purchaseOrdersApi
      .getWithETag(poId)
      .then(({ data, etag: tag }) => {
        setPo(data)
        setEtag(tag)
        setLines(toDraftLines(data))
        setConflict(false)
      })
      .catch((err) => setLoadError(errorMessage(err)))
  }

  useEffect(() => {
    if (!Number.isFinite(poId)) return
    load()
    Promise.all([itemsApi.list({ pageSize: 200 }), uomsApi.list(), warehousesApi.list(), vendorsApi.list({ pageSize: 200 })])
      .then(([it, uo, wh, ve]) => {
        setItems(it.items)
        setUoms(uo.items)
        setWarehouses(wh.items)
        setVendors(ve.items)
      })
      .catch(() => {})
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [poId])

  function itemFor(itemId: number | null) {
    return items.find((i) => i.itemId === itemId) ?? null
  }
  function warehouseCode(warehouseId: number) {
    return warehouses.find((w) => w.warehouseId === warehouseId)?.code ?? `#${warehouseId}`
  }
  function vendorCode(vendorId: number) {
    return vendors.find((v) => v.vendorId === vendorId)?.code ?? `#${vendorId}`
  }

  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))
  }

  async function handleSave() {
    if (!po || !etag) return
    setSaveError(null)

    if (lines.length === 0) {
      setSaveError("A purchase order needs at least one line.")
      return
    }
    const nextLineErrors: Record<string, Record<string, string>> = {}
    for (const line of lines) {
      const errors = validatePoLine({
        itemId: line.itemId,
        warehouseId: line.warehouseId,
        qty: line.qty,
        unitPrice: line.unitPrice,
        tax: line.tax,
      })
      if (Object.keys(errors).length > 0) nextLineErrors[line.key] = errors
    }
    setLineErrors(nextLineErrors)
    if (Object.keys(nextLineErrors).length > 0) {
      setSaveError("Fix the highlighted lines before saving.")
      return
    }

    const payloadLines: CreatePoLineInput[] = lines.map((l) => ({
      itemId: l.itemId as number,
      warehouseId: l.warehouseId as number,
      qty: Number(l.qty),
      unitPrice: Number(l.unitPrice),
      tax: Number(l.tax),
    }))

    setSaving(true)
    try {
      const result = await purchaseOrdersApi.update(po.poId, { vendorId: po.vendorId, requisitionId: po.requisitionId, lines: payloadLines }, etag)
      setPo(result.data)
      setEtag(result.etag)
      setLines(toDraftLines(result.data))
      toast.success("Purchase order saved", `${result.data.docNo} updated (FR-PROC-05, edit-while-open).`)
    } catch (err) {
      const code = (err as { code?: string })?.code
      if (code === "CONCURRENCY_CONFLICT") {
        setConflict(true)
        setSaveError(errorMessage(err))
        setSaving(false)
        return
      }
      setSaveError(errorMessage(err))
      toast.error("Could not save purchase order", errorMessage(err))
    } finally {
      setSaving(false)
    }
  }

  async function handleSubmitPo() {
    if (!po) return
    setSaveError(null)
    setSubmitting(true)
    try {
      const updated = await purchaseOrdersApi.submit(po.poId)
      setPo(updated)
      setLines(toDraftLines(updated))
      toast.success("Purchase order approved", `${updated.docNo} — now ${updated.status} and locked for editing.`)
    } catch (err) {
      setSaveError(errorMessage(err))
      toast.error("Could not approve purchase order", errorMessage(err))
    } finally {
      setSubmitting(false)
    }
  }

  async function handleDelete() {
    if (!po) return
    setSaveError(null)
    setDeleting(true)
    try {
      await purchaseOrdersApi.remove(po.poId)
      toast.success("Draft deleted", po.docNo)
      router.push("/dashboard/procurement/purchase-orders")
    } catch (err) {
      setSaveError(errorMessage(err))
      toast.error("Could not delete purchase order", errorMessage(err))
      setDeleting(false)
    }
  }

  async function handleCancel() {
    if (!po) return
    if (!cancelReason.trim()) {
      setSaveError("A cancellation reason is required.")
      return
    }
    setCancelling(true)
    try {
      const updated = await purchaseOrdersApi.cancel(po.poId, { reason: cancelReason.trim() })
      setPo(updated)
      setShowCancelForm(false)
      toast.success("Purchase order cancelled", updated.docNo)
    } catch (err) {
      toast.error("Could not cancel purchase order", errorMessage(err))
    } finally {
      setCancelling(false)
    }
  }

  if (loadError && !po) {
    return (
      <div className="flex flex-col gap-4">
        <div className="rounded-lg border border-destructive/30 bg-destructive/5 p-5 text-base text-destructive">{loadError}</div>
        <Link href="/dashboard/procurement/purchase-orders" className={cn(buttonVariants({ variant: "outline" }))}>
          Back to purchase orders
        </Link>
      </div>
    )
  }

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

  const editable = isPoEditable(po.status) && !conflict
  const hasReceipts = po.lines.some((l) => l.qtyReceived > 0)
  // A submitted-but-still-open PO (issued to the vendor) is cancellable with a reason;
  // a Draft is deleted instead, and closed/cancelled POs are terminal.
  const cancellable = po.status === "Approved" || po.status === "PartiallyReceived"

  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">{po.docNo}</h1>
              <PoStatusBadge status={po.status} />
            </div>
            <p className="text-base text-muted-foreground">
              Vendor {vendorCode(po.vendorId)} {po.requisitionId ? `— from Requisition #${po.requisitionId}` : ""} — {po.totals.currency} {po.totals.grandTotal.toFixed(2)}
            </p>
          </div>
        </div>

        <div className="flex flex-wrap items-center gap-3">
          {po.status === "Draft" && (
            <>
              <Button variant="success" size="lg" onClick={handleSubmitPo} disabled={submitting || deleting}>
                <Check className="size-5" />
                {submitting ? "Approving�" : "Approve"}
              </Button>
              <AlertDialog>
                <AlertDialogTrigger
                  render={<Button variant="destructive" size="lg" disabled={deleting || submitting} />}
                >
                  <Trash2 className="size-5" />
                  {deleting ? "Deleting…" : "Delete draft"}
                </AlertDialogTrigger>
                <AlertDialogContent
                  variant="destructive"
                  title={`Delete draft ${po.docNo}?`}
                  description="This cannot be undone."
                  confirmLabel="Delete"
                  onConfirm={handleDelete}
                />
              </AlertDialog>
            </>
          )}
          {cancellable && !showCancelForm && (
            <Button
              variant="destructive"
              size="lg"
              onClick={() => setShowCancelForm(true)}
              disabled={hasReceipts}
              title={hasReceipts ? "Cannot cancel — this PO already has receipts against it" : undefined}
            >
              <Ban className="size-5" />
              Cancel PO
            </Button>
          )}
        </div>
      </div>

      {showCancelForm && (
        <div className="flex flex-col gap-3 rounded-xl border border-destructive/30 bg-destructive/5 p-5">
          <p className="text-base font-semibold text-destructive">Cancel {po.docNo}</p>
          <Input
            value={cancelReason}
            onChange={(e) => setCancelReason(e.target.value)}
            placeholder="Reason (e.g. Duplicate order)"
            className="h-11 max-w-md text-base"
          />
          <div className="flex gap-3">
            <Button variant="outline" onClick={() => setShowCancelForm(false)} disabled={cancelling}>
              Back
            </Button>
            <Button variant="destructive" onClick={handleCancel} disabled={cancelling}>
              {cancelling ? "Cancelling…" : "Confirm cancellation"}
            </Button>
          </div>
        </div>
      )}

      {conflict && (
        <div className="flex items-start gap-3 rounded-lg border border-warning/30 bg-warning/5 p-5 text-base text-warning">
          <AlertTriangle className="size-5 shrink-0" />
          <div className="flex flex-col gap-2">
            <p>{saveError ?? "This purchase order was changed by someone else."} Reload before retrying.</p>
            <Button size="sm" variant="outline" onClick={load}>
              Reload
            </Button>
          </div>
        </div>
      )}

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

      <div className="flex flex-col gap-3">
        <div className="flex items-center justify-between">
          <h2 className="text-base font-semibold text-foreground">Lines</h2>
          {editable && (
            <Button type="button" variant="outline" onClick={() => setLines((prev) => [...prev, { key: newKey(), poLineId: null, itemId: null, warehouseId: null, qty: "", unitPrice: "", tax: "0.18", qtyReceived: 0 }])}>
              <Plus className="size-5" />
              Add line
            </Button>
          )}
        </div>

        <div className="overflow-x-auto">
          <Table className="text-base">
            <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-36 px-3 text-sm">Warehouse</TableHead>
                <TableHead className="h-12 w-24 px-3 text-sm">Qty</TableHead>
                <TableHead className="h-12 w-24 px-3 text-sm">Received</TableHead>
                <TableHead className="h-12 w-28 px-3 text-sm">Unit price</TableHead>
                <TableHead className="h-12 w-20 px-3 text-sm">Tax</TableHead>
                {editable && <TableHead className="h-12 w-10 px-3" />}
              </TableRow>
            </TableHeader>
            <TableBody>
              {lines.map((line) => {
                const errors = lineErrors[line.key] ?? {}
                const item = itemFor(line.itemId)
                if (!editable) {
                  return (
                    <TableRow key={line.key}>
                      <TableCell className="px-3 py-3.5">{item ? `${item.sku} — ${item.name}` : `Item #${line.itemId}`}</TableCell>
                      <TableCell className="px-3 py-3.5">{baseUomLabel(items, uoms, line.itemId)}</TableCell>
                      <TableCell className="px-3 py-3.5">{line.warehouseId ? warehouseCode(line.warehouseId) : "—"}</TableCell>
                      <TableCell className="px-3 py-3.5">{line.qty}</TableCell>
                      <TableCell className="px-3 py-3.5">{line.qtyReceived}</TableCell>
                      <TableCell className="px-3 py-3.5">{Number(line.unitPrice).toFixed(2)}</TableCell>
                      <TableCell className="px-3 py-3.5">{(Number(line.tax) * 100).toFixed(0)}%</TableCell>
                    </TableRow>
                  )
                }
                return (
                  <TableRow key={line.key}>
                    <TableCell className="px-3 py-3 align-top">
                      <Select<number | null> value={line.itemId} onValueChange={(v) => updateLine(line.key, { itemId: v })}>
                        <SelectTrigger className="h-11! w-full text-base" aria-invalid={!!errors.itemId}>
                          <SelectValue placeholder="Select item" />
                        </SelectTrigger>
                        <SelectContent>
                          {items.map((i) => (
                            <SelectItem key={i.itemId} value={i.itemId} className="text-base">
                              {i.sku} — {i.name}
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                      <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-base text-muted-foreground">
                        {baseUomLabel(items, uoms, line.itemId)}
                      </div>
                    </TableCell>
                    <TableCell className="px-3 py-3 align-top">
                      <Select<number | null> value={line.warehouseId} onValueChange={(v) => updateLine(line.key, { warehouseId: v })}>
                        <SelectTrigger className="h-11! w-full text-base" aria-invalid={!!errors.warehouseId}>
                          <SelectValue placeholder="Warehouse" />
                        </SelectTrigger>
                        <SelectContent>
                          {warehouses.map((w) => (
                            <SelectItem key={w.warehouseId} value={w.warehouseId} className="text-base">
                              {w.code}
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                      <FieldError errors={[errors.warehouseId ? { message: errors.warehouseId } : undefined]} />
                    </TableCell>
                    <TableCell className="px-3 py-3 align-top">
                      <Input
                        type="number"
                        min={line.qtyReceived}
                        step="any"
                        value={line.qty}
                        aria-invalid={!!errors.qty}
                        onChange={(e) => updateLine(line.key, { qty: e.target.value })}
                        className="h-11 text-base"
                      />
                      <FieldError errors={[errors.qty ? { message: errors.qty } : undefined]} />
                    </TableCell>
                    <TableCell className="px-3 py-3.5">{line.qtyReceived}</TableCell>
                    <TableCell className="px-3 py-3 align-top">
                      <Input
                        type="number"
                        min="0"
                        step="any"
                        value={line.unitPrice}
                        aria-invalid={!!errors.unitPrice}
                        onChange={(e) => updateLine(line.key, { unitPrice: e.target.value })}
                        className="h-11 text-base"
                      />
                      <FieldError errors={[errors.unitPrice ? { message: errors.unitPrice } : undefined]} />
                    </TableCell>
                    <TableCell className="px-3 py-3 align-top">
                      <Input
                        type="number"
                        min="0"
                        step="0.01"
                        value={line.tax}
                        aria-invalid={!!errors.tax}
                        onChange={(e) => updateLine(line.key, { tax: e.target.value })}
                        className="h-11 text-base"
                      />
                      <FieldError errors={[errors.tax ? { message: errors.tax } : undefined]} />
                    </TableCell>
                    <TableCell className="px-3 py-3 align-top">
                      <Button
                        type="button"
                        variant="ghost"
                        size="icon"
                        onClick={() => removeLine(line.key)}
                        aria-label="Remove line"
                        disabled={line.qtyReceived > 0}
                        title={line.qtyReceived > 0 ? "Cannot remove a line that already has receipts" : undefined}
                      >
                        <Trash2 className="size-5" />
                      </Button>
                    </TableCell>
                  </TableRow>
                )
              })}
            </TableBody>
          </Table>
        </div>
      </div>

      {editable && (
        <div className="flex justify-end gap-3">
          <Button variant="outline" size="lg" onClick={() => router.push("/dashboard/procurement/purchase-orders")}>
            Back
          </Button>
          <Button size="lg" onClick={handleSave} disabled={saving}>
            <Save className="size-5" />
            {saving ? "Saving…" : "Save changes"}
          </Button>
        </div>
      )}
    </div>
  )
}
