"use client"

import { useEffect, useState } from "react"
import { useParams, useRouter } from "next/navigation"
import Link from "next/link"
import { AlertTriangle, Save } from "lucide-react"

import { itemsApi } from "@/lib/api/items"
import { categoriesApi } from "@/lib/api/categories"
import { uomsApi } from "@/lib/api/uoms"
import { warehousesApi } from "@/lib/api/warehouses"
import { errorMessage, fieldErrors } from "@/lib/error-map"
import { validateItemForm } from "@/lib/validations/master-data"
import { cn } from "@/lib/utils"
import { Item, MeasureUnit, StockNature, TrackingMode, Warranty, WarrantyPeriodMonths } from "@/types/master-data"

/** Entry units. Only ml/g are stored — the server normalises L and Kg ×1000 on write. */
const CONTENT_UNITS: MeasureUnit[] = ["Ml", "L", "G", "Kg"]

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 { Skeleton } from "@/components/ui/skeleton"
import { toast } from "@/components/ui/toast"

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

  const [item, setItem] = useState<Item | null>(null)
  const [etag, setEtag] = useState<string | null>(null)
  const [categories, setCategories] = useState<{ categoryId: number; name: string }[]>([])
  const [uoms, setUoms] = useState<{ uomId: number; name: string }[]>([])
  const [warehouses, setWarehouses] = useState<{ warehouseId: number; code: string; name: string }[]>([])
  const [loadError, setLoadError] = useState<string | null>(null)

  // Basic info form
  const [sku, setSku] = useState("")
  const [name, setName] = useState("")
  // No longer editable here — carried through unchanged so a save doesn't silently clear it.
  const [description, setDescription] = useState("")
  const [categoryId, setCategoryId] = useState<number | null>(null)
  // Carried through edits so a save doesn't silently drop the item's subcategory/brand.
  // Not editable here — they are chosen on the create screen's builder.
  const [subCategoryId, setSubCategoryId] = useState<number | null>(null)
  const [brandId, setBrandId] = useState<number | null>(null)
  const [baseUomId, setBaseUomId] = useState<number | null>(null)
  const [stockNature, setStockNature] = useState<StockNature>("Stocked")
  // Default vendor, tax class, and tracking mode are no longer editable on this page —
  // carried through unchanged (from the loaded item) so a save doesn't silently clear them.
  const [defaultVendorId, setDefaultVendorId] = useState<number | null>(null)
  const [trackingMode, setTrackingMode] = useState<TrackingMode>("None")
  // Not editable here — carried through unchanged so a save doesn't silently reset it.
  const [warranty, setWarranty] = useState<Warranty>("NonWarranty")
  const [warrantyPeriodMonths, setWarrantyPeriodMonths] = useState<WarrantyPeriodMonths | null>(null)
  const [taxClass, setTaxClass] = useState("")
  // Raw string: an empty box means "no content size", which is not the same as 0.
  const [contentQty, setContentQty] = useState("")
  const [contentUnit, setContentUnit] = useState<MeasureUnit | null>(null)
  // Frontend-only: there's no warehouse field anywhere on the Item contract, so this
  // isn't sent on save — nothing to wire it to server-side.
  const [warehouseId, setWarehouseId] = useState<number | null>(null)

  const [errors, setErrors] = useState<Record<string, string>>({})
  const [conflict, setConflict] = useState(false)
  const [saveError, setSaveError] = useState<string | null>(null)
  const [saving, setSaving] = useState(false)
  const [togglingStatus, setTogglingStatus] = useState(false)

  function applyItem(data: Item) {
    setItem(data)
    setSku(data.sku)
    setName(data.name)
    setDescription(data.description ?? "")
    setCategoryId(data.categoryId)
    setSubCategoryId(data.subCategoryId)
    setBrandId(data.brandId)
    setBaseUomId(data.baseUomId)
    setDefaultVendorId(data.defaultVendorId)
    setStockNature(data.stockNature)
    setTrackingMode(data.trackingMode)
    setWarranty(data.warranty)
    setWarrantyPeriodMonths(data.warrantyPeriodMonths)
    setTaxClass(data.taxClass ?? "")
    setContentQty(data.contentQty === null ? "" : String(data.contentQty))
    setContentUnit(data.contentUnit)
  }

  function load() {
    setLoadError(null)
    itemsApi
      .get(itemId)
      .then(({ data, etag: tag }) => {
        applyItem(data)
        setEtag(tag)
        setConflict(false)
      })
      .catch((err) => setLoadError(errorMessage(err)))
  }

  useEffect(() => {
    if (!Number.isFinite(itemId)) return
    load()
    Promise.all([categoriesApi.list(), uomsApi.list(), warehousesApi.list({ pageSize: 200 })])
      .then(([cat, uo, wh]) => {
        setCategories(cat.items)
        setUoms(uo.items)
        setWarehouses(wh.items)
      })
      .catch(() => {})
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [itemId])

  async function handleSave() {
    if (!item || !etag) return
    setSaveError(null)
    const nextErrors = validateItemForm({ sku, name, categoryId, baseUomId, contentQty, contentUnit })
    setErrors(nextErrors)
    if (Object.keys(nextErrors).length > 0) return

    setSaving(true)
    try {
      const result = await itemsApi.update(
        item.itemId,
        {
          sku, name, description: description || null, categoryId: categoryId as number, subCategoryId, brandId,
          baseUomId: baseUomId as number, defaultVendorId, stockNature, trackingMode, warranty, warrantyPeriodMonths,
          taxClass: taxClass || null,
          contentQty: contentQty.trim() ? Number(contentQty) : null,
          contentUnit: contentQty.trim() ? contentUnit : null,
        },
        etag
      )
      applyItem(result.data)
      setEtag(result.etag)
      toast.success("Item saved", `${result.data.sku} — ${result.data.name}`)
    } catch (err) {
      const code = (err as { code?: string })?.code
      if (code === "CONCURRENCY_CONFLICT") {
        setConflict(true)
        setSaveError(errorMessage(err))
        setSaving(false)
        return
      }
      const fe = fieldErrors(err)
      if (fe?.sku) setErrors((prev) => ({ ...prev, sku: fe.sku }))
      setSaveError(errorMessage(err))
      toast.error("Could not save item", errorMessage(err))
    } finally {
      setSaving(false)
    }
  }

  async function handleToggleStatus() {
    if (!item) return
    const next = item.status === "Active" ? "Inactive" : "Active"
    setTogglingStatus(true)
    try {
      await itemsApi.updateStatus(item.itemId, next)
      toast.success(next === "Active" ? "Item activated" : "Item deactivated")
      load()
    } catch (err) {
      toast.error("Could not update status", errorMessage(err))
    } finally {
      setTogglingStatus(false)
    }
  }

  function uomName(uomId: number) {
    return uoms.find((u) => u.uomId === uomId)?.name ?? `#${uomId}`
  }

  if (loadError && !item) {
    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/products" className={cn(buttonVariants({ variant: "outline" }))}>
          Back to items
        </Link>
      </div>
    )
  }

  if (!item) {
    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">{item.sku}</h1>
              <Badge
                variant="outline"
                className={cn("h-6 w-fit justify-center border-transparent px-2.5 text-sm", item.status === "Active" ? "bg-success/10 text-success" : "bg-destructive/10 text-destructive")}
              >
                {item.status}
              </Badge>
            </div>
            <p className="text-base text-muted-foreground">{item.name}</p>
          </div>
        </div>

        <Button size="lg" variant={item.status === "Active" ? "destructive" : "success"} onClick={handleToggleStatus} disabled={togglingStatus}>
          {togglingStatus ? "Updating…" : item.status === "Active" ? "Deactivate" : "Activate"}
        </Button>
      </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 item 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-4 rounded-xl border p-5">
        <h2 className="text-base font-semibold text-foreground">Basic info</h2>
        <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
          <div className="flex flex-col gap-2">
            <Label className="text-base">SKU</Label>
            <Input value={sku} onChange={(e) => setSku(e.target.value)} aria-invalid={!!errors.sku} className="h-12 text-base" disabled={conflict} />
            <FieldError errors={[errors.sku ? { message: errors.sku } : undefined]} />
          </div>
          <div className="flex flex-col gap-2">
            <Label className="text-base">Name</Label>
            <Input value={name} onChange={(e) => setName(e.target.value)} aria-invalid={!!errors.name} className="h-12 text-base" disabled={conflict} />
            <FieldError errors={[errors.name ? { message: errors.name } : undefined]} />
          </div>
          <div className="flex flex-col gap-2">
            <Label className="text-base">Category</Label>
            <Select<number | null>
              value={categoryId}
              onValueChange={setCategoryId}
              disabled={conflict}
              items={categories.map((c) => ({ label: c.name, value: c.categoryId }))}
            >
              <SelectTrigger className="h-12! w-full text-base" aria-invalid={!!errors.categoryId}>
                <SelectValue placeholder="Select category" />
              </SelectTrigger>
              <SelectContent>
                {categories.map((c) => (
                  <SelectItem key={c.categoryId} value={c.categoryId} className="text-base">
                    {c.name}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            <FieldError errors={[errors.categoryId ? { message: errors.categoryId } : undefined]} />
          </div>
          <div className="flex flex-col gap-2">
            <Label className="text-base">Base UOM</Label>
            <Select<number | null>
              value={baseUomId}
              onValueChange={setBaseUomId}
              disabled={conflict}
              items={uoms.map((u) => ({ label: u.name, value: u.uomId }))}
            >
              <SelectTrigger className="h-12! w-full text-base" aria-invalid={!!errors.baseUomId}>
                <SelectValue placeholder="Select base UOM" />
              </SelectTrigger>
              <SelectContent>
                {uoms.map((u) => (
                  <SelectItem key={u.uomId} value={u.uomId} className="text-base">
                    {u.name}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            <FieldError errors={[errors.baseUomId ? { message: errors.baseUomId } : undefined]} />
          </div>
          {/* Content size (FR-MD-02): how much one pack holds. Optional, and independent of the
              base UOM above — stock is counted in packs either way. */}
          <div className="flex flex-col gap-2">
            <Label className="text-base">Content size</Label>
            <div className="flex gap-2">
              <Input
                type="number"
                min="0"
                step="any"
                value={contentQty}
                disabled={conflict}
                onChange={(e) => setContentQty(e.target.value)}
                placeholder="e.g. 500"
                aria-invalid={!!errors.contentQty}
                className="h-12! text-base"
              />
              <Select<MeasureUnit | null>
                value={contentUnit}
                onValueChange={setContentUnit}
                disabled={conflict}
                items={CONTENT_UNITS.map((u) => ({ label: u, value: u }))}
              >
                <SelectTrigger className="h-12! w-28 shrink-0 text-base" aria-invalid={!!errors.contentUnit}>
                  <SelectValue placeholder="Unit" />
                </SelectTrigger>
                <SelectContent>
                  {CONTENT_UNITS.map((u) => (
                    <SelectItem key={u} value={u} className="text-base">
                      {u.toLowerCase()}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <FieldError
              errors={[
                errors.contentQty ? { message: errors.contentQty } : undefined,
                errors.contentUnit ? { message: errors.contentUnit } : undefined,
              ]}
            />
            {/* The stored value, so the ×1000 normalisation is never a surprise. */}
            <p className="text-sm text-muted-foreground">
              {item.contentBaseQty !== null && item.contentBaseUnit
                ? `Stored as ${item.contentBaseQty} ${item.contentBaseUnit.toLowerCase()} per ${uomName(item.baseUomId)}.`
                : "No content size — leave blank for items with nothing measurable to hold."}
            </p>
          </div>
          <div className="flex flex-col gap-2">
            {/* "Item type" now means a Color/Size dimension master — this field is the
                stock-nature one it used to be confused with (docs/11 §8). */}
            <Label className="text-base">Stock nature</Label>
            <Select<StockNature> value={stockNature} onValueChange={(v) => v && setStockNature(v)} disabled={conflict}>
              <SelectTrigger className="h-12! w-full text-base">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="Stocked" className="text-base">Stocked</SelectItem>
                <SelectItem value="NonStocked" className="text-base">Non-stocked</SelectItem>
                <SelectItem value="Service" className="text-base">Service</SelectItem>
              </SelectContent>
            </Select>
          </div>
          <div className="flex flex-col gap-2">
            <Label className="text-base">Warehouse (optional)</Label>
            <Select<number | null>
              value={warehouseId}
              onValueChange={setWarehouseId}
              disabled={conflict}
              items={warehouses.map((w) => ({ label: `${w.code} — ${w.name}`, value: w.warehouseId }))}
            >
              <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>
        <div className="flex justify-end gap-3">
          <Button variant="outline" size="lg" onClick={() => router.push("/dashboard/products")}>
            Back
          </Button>
          <Button size="lg" onClick={handleSave} disabled={saving || conflict}>
            <Save className="size-5" />
            {saving ? "Saving…" : "Save changes"}
          </Button>
        </div>
      </div>

      <p className="text-sm text-muted-foreground">
        {uomName(item.baseUomId)} is the base UOM — every transaction records quantities as a count of it (FR-MD-03).
        There are no conversions: a differently sized pack is a different item.
      </p>
    </div>
  )
}
