"use client"

import { use, useEffect, useMemo, useState } from "react"
import Link from "next/link"
import { ArrowLeft, ExternalLink, Minus, Plus, Printer, Save, Send, X } from "lucide-react"

import { salesApi } from "@/lib/api/sales"
import { customersApi } from "@/lib/api/customers"
import { itemsApi } from "@/lib/api/items"
import { uomsApi } from "@/lib/api/uoms"
import { baseUomLabel } from "@/lib/uom-label"
import { warehousesApi } from "@/lib/api/warehouses"
import { usersApi } from "@/lib/api/users"
import { errorMessage } from "@/lib/error-map"
import { Button, buttonVariants } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Skeleton } from "@/components/ui/skeleton"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { cn } from "@/lib/utils"
import { getSuggestedUnitPrice } from "@/lib/sales-line-utils"
import { FreeIssuePromotionSuggestions } from "@/components/sales/FreeIssuePromotionSuggestions"
import { Customer } from "@/types/customers"
import { ItemListItem, Uom, Warehouse } from "@/types/master-data"
import { ManagedUser } from "@/types/users"
import { CreateSalesSlipLineRequest, SalesFreeIssueSuggestion, SalesSlip, SalesSlipPostingCheck } from "@/types/sales"
import { toast } from "@/components/ui/toast"

type Line = CreateSalesSlipLineRequest & { key: string }

const money = new Intl.NumberFormat("en-LK", {
  style: "currency",
  currency: "LKR",
  minimumFractionDigits: 2,
})

const blankLine = (key: string): Line => ({
  key,
  itemId: 0,
  warehouseId: 0,
  qty: 1,
  freeQty: 0,
  unitPrice: null,
  allowManualPriceOverride: true,
  discountMode: "Percentage",
  discountPct: 0,
  discountAmount: 0,
  discountValue: 0,
  taxPct: 0,
  isFreeIssue: false,
  parentLineId: null,
})

export default function SalesSlipDetailPage({ params }: { params: Promise<{ id: string }> }) {
  const resolvedParams = use(params)
  const slipId = Number(resolvedParams.id)
  const [slip, setSlip] = useState<SalesSlip | null>(null)
  const [etag, setEtag] = useState<string | null>(null)
  const [customers, setCustomers] = useState<Customer[]>([])
  const [items, setItems] = useState<ItemListItem[]>([])
  const [uoms, setUoms] = useState<Uom[]>([])
  const [warehouses, setWarehouses] = useState<Warehouse[]>([])
  const [users, setUsers] = useState<ManagedUser[]>([])
  const [promotionSuggestion, setPromotionSuggestion] = useState<SalesFreeIssueSuggestion | null>(null)
  const [postingCheck, setPostingCheck] = useState<SalesSlipPostingCheck | null>(null)
  const [customerId, setCustomerId] = useState<number | null>(null)
  const [warehouseId, setWarehouseId] = useState<number | null>(null)
  const [cashierUserId, setCashierUserId] = useState<number | null>(null)
  const [lines, setLines] = useState<Line[]>([blankLine("line-1")])
  const [error, setError] = useState<string | null>(null)
  const [saving, setSaving] = useState(false)
  const [actionBusy, setActionBusy] = useState<"post" | "cancel" | null>(null)

  useEffect(() => {
    if (!Number.isFinite(slipId)) {
      setError(`Invalid slip id '${resolvedParams.id}'.`)
      return
    }
    Promise.all([
      customersApi.list({ pageSize: 200 }),
      itemsApi.list({ pageSize: 200 }),
      uomsApi.list({ pageSize: 200 }),
      warehousesApi.list({ pageSize: 200 }),
      usersApi.list({ pageSize: 200 }),
      salesApi.getSlip(slipId),
    ])
      .then(([cust, itemRes, uomRes, whRes, userRes, doc]) => {
        setCustomers(cust.items)
        setItems(itemRes.items)
        setUoms(uomRes.items)
        setWarehouses(whRes.items)
        setUsers(userRes.items)
        setSlip(doc.data)
        setEtag(doc.etag)
        setCustomerId(doc.data.customerId)
        setWarehouseId(doc.data.warehouseId)
        setCashierUserId(doc.data.cashierUserId)
        setPromotionSuggestion(null)
        setLines(
          doc.data.lines.map((line) => ({
            key: String(line.salesSlipLineId),
            itemId: line.itemId,
            warehouseId: line.warehouseId,
            qty: line.qty,
            freeQty: line.freeQty,
            unitPrice: line.unitPrice,
            allowManualPriceOverride: true,
            discountMode: line.discountMode,
            discountPct: line.discountPct,
            discountAmount: line.discountAmount,
            discountValue: 0,
            taxPct: line.taxPct,
            isFreeIssue: line.isFreeIssue,
            parentLineId: line.parentLineId,
          }))
        )
      })
      .then(async () => {
        try {
          const suggestions = await salesApi.getFreeIssueSuggestions(slipId)
          setPromotionSuggestion(suggestions)
        } catch {
          setPromotionSuggestion(null)
        }
      })
      .catch((err) => setError(errorMessage(err)))
  }, [resolvedParams.id, slipId])

  useEffect(() => {
    if (!slip || slip.status !== "Draft") {
      setPostingCheck(null)
      return
    }
    salesApi
      .checkSlipPosting(slipId)
      .then((result) => setPostingCheck(result))
      .catch(() => setPostingCheck(null))
  }, [slip, slipId])

  const subtotal = useMemo(
    () => lines.reduce((sum, line) => sum + Number(line.qty || 0) * Number(line.unitPrice ?? 0), 0),
    [lines]
  )

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

  function selectItem(key: string, itemId: number) {
    updateLine(key, {
      itemId,
      unitPrice: getSuggestedUnitPrice(items, itemId),
    })
  }

  function resolveLineUnitPrice(line: Line): number | null {
    if (line.unitPrice !== null && line.unitPrice !== undefined) return Number(line.unitPrice)
    return getSuggestedUnitPrice(items, line.itemId)
  }

  function addLine() {
    setLines((prev) => [...prev, blankLine(`line-${Date.now()}`)])
  }

  function removeLine(key: string) {
    setLines((prev) => (prev.length === 1 ? prev : prev.filter((line) => line.key !== key)))
  }

  async function save() {
    if (!customerId || !warehouseId || !cashierUserId || !etag) return
    setSaving(true)
    setError(null)
    try {
      const payload = {
        customerId,
        warehouseId,
        cashierUserId,
          lines: lines.map((line) => ({
            itemId: Number(line.itemId),
            warehouseId: Number(line.warehouseId),
            qty: Number(line.qty),
            freeQty: Number(line.freeQty),
            unitPrice: resolveLineUnitPrice(line),
            allowManualPriceOverride: line.allowManualPriceOverride,
          discountMode: line.discountMode,
          discountPct: Number(line.discountPct),
          discountAmount: Number(line.discountAmount),
          discountValue: Number(line.discountValue),
          taxPct: Number(line.taxPct),
          isFreeIssue: line.isFreeIssue,
          parentLineId: line.parentLineId || null,
        })),
      }
      const updated = await salesApi.updateSlip(slipId, payload, etag)
      setSlip(updated.data)
      setEtag(updated.etag)
      toast.success("Slip saved", updated.data.slipNo)
    } catch (err) {
      setError(errorMessage(err))
    } finally {
      setSaving(false)
    }
  }

  async function post() {
    if (!postingCheck?.canPost) {
      setError("Resolve stock shortages before posting this slip.")
      return
    }
    setActionBusy("post")
    setError(null)
    try {
      const posted = await salesApi.postSlip(slipId)
      setSlip(posted)
      toast.success("Slip posted", posted.slipNo)
    } catch (err) {
      setError(errorMessage(err))
    } finally {
      setActionBusy(null)
    }
  }

  async function cancel() {
    setActionBusy("cancel")
    setError(null)
    try {
      const cancelled = await salesApi.cancelSlip(slipId)
      setSlip(cancelled)
      toast.success("Slip cancelled", cancelled.slipNo)
    } catch (err) {
      setError(errorMessage(err))
    } finally {
      setActionBusy(null)
    }
  }

  if (error && !slip) return <div className="rounded-lg border border-destructive/30 bg-destructive/5 p-5 text-base text-destructive">{error}</div>
  if (!slip) return <div className="rounded-2xl border border-dashed p-8 text-muted-foreground">{error ?? "Slip data is loading or unavailable."}</div>

  const locked = slip.status !== "Draft"
  const canPost = slip.status === "Draft" && (postingCheck?.canPost ?? true) && actionBusy === null

  return (
    <div className="flex flex-col gap-6">
      <div className="flex items-center justify-between gap-3">
        <div className="flex items-center gap-3">
          <Link href="/dashboard/sales/slips" className={cn(buttonVariants({ variant: "outline", size: "icon" }))}>
            <ArrowLeft className="size-4" />
          </Link>
          <div>
            <h1 className="text-2xl font-bold text-foreground">Sales Slip</h1>
            <p className="text-base text-muted-foreground">{slip.slipNo} · {slip.status}</p>
          </div>
        </div>
        <div className="flex flex-wrap gap-2">
          <Link
            href={`/print/sales/slips/${slip.salesSlipId}`}
            target="_blank"
            rel="noopener noreferrer"
            className={cn(buttonVariants({ variant: "outline", size: "default" }))}
          >
            <Printer className="size-4" />
            Print
          </Link>
          <Button variant="outline" onClick={save} disabled={saving || locked}><Save className="size-4" />{saving ? "Saving..." : "Save"}</Button>
          <Button variant="outline" onClick={post} disabled={!canPost}><Send className="size-4" />{postingCheck && !postingCheck.canPost ? "Resolve shortages first" : actionBusy === "post" ? "Posting..." : "Post"}</Button>
          <Button variant="destructive" onClick={cancel} disabled={actionBusy !== null || locked}><X className="size-4" />{actionBusy === "cancel" ? "Cancelling..." : "Cancel"}</Button>
        </div>
      </div>

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

      <section className="bg-white">
        <div className="border-b pb-4">
          <div className="flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
            <div>
              <div className="text-xs font-semibold uppercase tracking-[0.35em] text-muted-foreground">Sales Slip</div>
              <h2 className="mt-2 text-3xl font-semibold text-foreground">{slip.slipNo}</h2>
              <div className="mt-1 flex flex-wrap items-center gap-2 text-sm text-muted-foreground">
                <span>Status:</span>
                <span className={cn("inline-flex rounded-full border px-2 py-0.5 text-xs font-medium", slip.status === "Draft" ? "border-amber-200 bg-amber-50 text-amber-800" : slip.status === "Posted" ? "border-emerald-200 bg-emerald-50 text-emerald-800" : "border-rose-200 bg-rose-50 text-rose-800")}>
                  {slip.status}
                </span>
                <span>Date: {new Date(slip.slipDate).toLocaleDateString()}</span>
                <span>Cashier: {users.find((u) => u.userId === slip.cashierUserId)?.displayName ?? `#${slip.cashierUserId}`}</span>
              </div>
            </div>
            <div className="text-sm md:text-right">
              <div className="font-semibold text-foreground">{customers.find((c) => c.customerId === slip.customerId)?.displayName ?? customers.find((c) => c.customerId === slip.customerId)?.name ?? slip.customerSnapshotName}</div>
              <div className="text-muted-foreground">Warehouse: {warehouses.find((w) => w.warehouseId === slip.warehouseId)?.name ?? `#${slip.warehouseId}`}</div>
              <div className="text-muted-foreground">Code: {warehouses.find((w) => w.warehouseId === slip.warehouseId)?.code ?? slip.warehouseId}</div>
            </div>
          </div>
        </div>

        <div className="grid gap-6 py-5 md:grid-cols-3">
          <div>
            <div className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Customer</div>
            <div className="mt-2 font-semibold text-foreground">{slip.customerSnapshotName}</div>
            <div className="text-sm text-muted-foreground">Customer ID: {slip.customerId}</div>
          </div>
          <div>
            <div className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Warehouse</div>
            <div className="mt-2 font-semibold text-foreground">{warehouses.find((w) => w.warehouseId === slip.warehouseId)?.name ?? `#${slip.warehouseId}`}</div>
            <div className="text-sm text-muted-foreground">Code: {warehouses.find((w) => w.warehouseId === slip.warehouseId)?.code ?? slip.warehouseId}</div>
          </div>
          <div>
            <div className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Totals</div>
            <div className="mt-2 grid grid-cols-2 gap-2 text-sm">
              <div className="text-muted-foreground">Subtotal</div>
              <div className="text-right font-medium">{money.format(slip.totals.subtotal)}</div>
              <div className="text-muted-foreground">Discount</div>
              <div className="text-right font-medium">{money.format(slip.totals.discountTotal)}</div>
              <div className="text-muted-foreground">Free qty</div>
              <div className="text-right font-medium">{slip.totals.freeQtyTotal.toFixed(0)}</div>
              <div className="text-muted-foreground">Grand total</div>
              <div className="text-right font-semibold">{money.format(slip.totals.grandTotal)}</div>
            </div>
          </div>
        </div>

        <div className="overflow-x-auto border-y">
          <Table className="text-sm">
            <TableHeader>
              <TableRow>
                <TableHead className="h-12 px-4 text-sm">Item</TableHead>
                <TableHead className="h-12 px-4 text-sm">UOM</TableHead>
                <TableHead className="h-12 px-4 text-sm text-right">Qty</TableHead>
                <TableHead className="h-12 px-4 text-sm text-right">Free</TableHead>
                <TableHead className="h-12 px-4 text-sm text-right">Unit price</TableHead>
                <TableHead className="h-12 px-4 text-sm text-right">Line total</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {slip.lines.map((line) => (
                <TableRow key={line.salesSlipLineId}>
                  <TableCell className="px-4 py-3">
                    <div className="font-medium text-foreground">{line.description}</div>
                    <div className="text-xs text-muted-foreground">SKU {items.find((i) => i.itemId === line.itemId)?.sku ?? `#${line.itemId}`}</div>
                    <div className="mt-1 text-[11px] text-muted-foreground">
                      {getSuggestedUnitPrice(items, line.itemId) !== null
                        ? `Suggested: ${money.format(getSuggestedUnitPrice(items, line.itemId) ?? 0)}`
                        : "No price suggestion available"}
                    </div>
                  </TableCell>
                  <TableCell className="px-4 py-3">{baseUomLabel(items, uoms, line.itemId)}</TableCell>
                  <TableCell className="px-4 py-3 text-right">{line.qty.toFixed(0)}</TableCell>
                  <TableCell className="px-4 py-3 text-right">{line.freeQty > 0 ? line.freeQty.toFixed(0) : "-"}</TableCell>
                  <TableCell className="px-4 py-3 text-right">{money.format(line.unitPrice)}</TableCell>
                  <TableCell className="px-4 py-3 text-right font-medium">{money.format(line.lineTotal)}</TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </div>
      </section>

      {slip.status === "Draft" && postingCheck && !postingCheck.canPost ? (
        <div className="rounded-lg border border-amber-200 bg-amber-50 p-4 text-sm text-amber-900">
          <div className="flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
            <div>
              <div className="font-semibold">Stock shortage detected before posting</div>
              <div className="mt-1">This slip cannot be posted until every line has enough available stock in the selected warehouse.</div>
            </div>
            <Link
              href="/dashboard/receiving/grn/new"
              className="inline-flex h-9 items-center gap-2 self-start rounded-full border border-amber-300 bg-white px-4 text-sm font-medium text-amber-950 shadow-sm hover:bg-amber-100"
            >
              <ExternalLink className="size-4" />
              Create GRN
            </Link>
          </div>
          <div className="mt-3 overflow-x-auto">
            <table className="w-full text-sm">
              <thead className="text-left text-xs uppercase tracking-wide text-amber-900/70">
                <tr>
                  <th className="py-1 pr-3">Item</th>
                  <th className="py-1 pr-3">Warehouse</th>
                  <th className="py-1 pr-3 text-right">Requested</th>
                  <th className="py-1 pr-3 text-right">Available</th>
                  <th className="py-1 text-right">Short</th>
                </tr>
              </thead>
              <tbody>
                {postingCheck.issues.map((issue) => (
                  <tr key={issue.salesSlipLineId} className="border-t border-amber-200/60">
                    <td className="py-2 pr-3">
                      <div className="font-medium">{issue.itemSku}</div>
                      <div className="text-xs text-amber-900/70">{issue.itemName}{issue.isFreeIssue ? " · free issue" : ""}</div>
                    </td>
                    <td className="py-2 pr-3">{issue.warehouseId}</td>
                    <td className="py-2 pr-3 text-right font-mono tabular-nums">{issue.requestedQty.toFixed(0)}</td>
                    <td className="py-2 pr-3 text-right font-mono tabular-nums">{issue.availableQty.toFixed(0)}</td>
                    <td className="py-2 text-right font-mono tabular-nums">{issue.shortQty.toFixed(0)}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      ) : null}

      {slip.status === "Draft" ? (
        <>
          <div className="grid gap-4 md:grid-cols-3">
            <div className="flex flex-col gap-2">
              <Label>Customer</Label>
              <Select value={customerId ? String(customerId) : ""} onValueChange={(v) => setCustomerId(v ? Number(v) : null)} disabled={locked}>
                <SelectTrigger className="h-12!"><SelectValue /></SelectTrigger>
                <SelectContent>{customers.map((c) => <SelectItem key={c.customerId} value={String(c.customerId)}>{c.customerCode} - {c.displayName ?? c.name}</SelectItem>)}</SelectContent>
              </Select>
            </div>
            <div className="flex flex-col gap-2">
              <Label>Warehouse</Label>
              <Select value={warehouseId ? String(warehouseId) : ""} onValueChange={(v) => setWarehouseId(v ? Number(v) : null)} disabled={locked}>
                <SelectTrigger className="h-12!"><SelectValue /></SelectTrigger>
                <SelectContent>{warehouses.map((w) => <SelectItem key={w.warehouseId} value={String(w.warehouseId)}>{w.code} - {w.name}</SelectItem>)}</SelectContent>
              </Select>
            </div>
            <div className="flex flex-col gap-2">
              <Label>Cashier</Label>
              <Select value={cashierUserId ? String(cashierUserId) : ""} onValueChange={(v) => setCashierUserId(v ? Number(v) : null)} disabled={locked}>
                <SelectTrigger className="h-12!"><SelectValue /></SelectTrigger>
                <SelectContent>{users.map((u) => <SelectItem key={u.userId} value={String(u.userId)}>{u.displayName}</SelectItem>)}</SelectContent>
              </Select>
            </div>
          </div>

          <div className="rounded-2xl border p-4">
            <div className="mb-3 flex items-center justify-between">
              <h2 className="text-lg font-semibold">Lines</h2>
              <Button type="button" variant="outline" onClick={addLine} disabled={locked}><Plus className="size-4" /> Add line</Button>
            </div>
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>Item</TableHead>
                  <TableHead>UOM</TableHead>
                  <TableHead>Qty</TableHead>
                  <TableHead>Free</TableHead>
                  <TableHead>Unit price</TableHead>
                  <TableHead />
                </TableRow>
              </TableHeader>
              <TableBody>
                {lines.map((line) => (
                  <TableRow key={line.key}>
                    <TableCell>
                      <Select value={line.itemId ? String(line.itemId) : ""} onValueChange={(v) => selectItem(line.key, Number(v))} disabled={locked}>
                        <SelectTrigger className="h-11!"><SelectValue placeholder="Item" /></SelectTrigger>
                        <SelectContent>{items.map((i) => <SelectItem key={i.itemId} value={String(i.itemId)}>{i.sku} - {i.name}</SelectItem>)}</SelectContent>
                      </Select>
                    </TableCell>
                    <TableCell className="text-sm text-muted-foreground">{baseUomLabel(items, uoms, line.itemId)}</TableCell>
                    <TableCell><Input type="number" min="0" step="0.01" value={line.qty} onChange={(e) => updateLine(line.key, { qty: Number(e.target.value) })} disabled={locked} /></TableCell>
                    <TableCell><Input type="number" min="0" step="0.01" value={line.freeQty} onChange={(e) => updateLine(line.key, { freeQty: Number(e.target.value) })} disabled={locked} /></TableCell>
                    <TableCell><Input type="number" min="0" step="0.01" value={line.unitPrice ?? ""} onChange={(e) => updateLine(line.key, { unitPrice: e.target.value === "" ? null : Number(e.target.value) })} disabled={locked} /></TableCell>
                    <TableCell><Button type="button" variant="ghost" size="icon" onClick={() => removeLine(line.key)} disabled={locked}><Minus className="size-4" /></Button></TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
            <div className="mt-4 text-sm text-muted-foreground">Subtotal: {subtotal.toFixed(2)}</div>
          </div>

          <FreeIssuePromotionSuggestions suggestion={promotionSuggestion} />

          <div className="flex justify-end gap-3">
            <Link href="/dashboard/sales/slips" className={cn(buttonVariants({ variant: "outline", size: "lg" }))}>Back</Link>
            <Button variant="outline" onClick={save} disabled={saving || locked}>Save</Button>
            <Button onClick={post} disabled={!canPost}>Post</Button>
          </div>
        </>
      ) : null}
    </div>
  )
}

