"use client"

import { Suspense, useEffect, useState } from "react"
import { useRouter, useSearchParams } from "next/navigation"
import Link from "next/link"
import {} from "lucide-react"

import { purchaseReturnsApi } from "@/lib/api/purchase-returns"
import { grnsApi } from "@/lib/api/grns"
import { reasonCodesApi } from "@/lib/api/reason-codes"
import { itemsApi } from "@/lib/api/items"
import { errorMessage } from "@/lib/error-map"
import { validateReturnLine } from "@/lib/validations/procurement"
import { cn } from "@/lib/utils"
import { CreatePurchaseReturnLineInput } from "@/types/procurement"
import { Grn, GrnLine } from "@/types/grn"
import { ItemListItem } from "@/types/master-data"
import { ReasonCode } from "@/types/stock"

import { Button, buttonVariants } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Checkbox } from "@/components/ui/checkbox"
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 { HoldStatusBadge } from "@/components/receiving/status-badges"

interface LineState {
  selected: boolean
  qty: string
}

function NewPurchaseReturnContent() {
  const router = useRouter()
  const searchParams = useSearchParams()
  const presetGrnId = Number(searchParams.get("grnId")) || null
  const presetGrnLineId = Number(searchParams.get("grnLineId")) || null

  const [grns, setGrns] = useState<Grn[] | null>(null)
  const [items, setItems] = useState<ItemListItem[]>([])
  const [reasonCodes, setReasonCodes] = useState<ReasonCode[]>([])
  const [loadError, setLoadError] = useState<string | null>(null)

  const [grnId, setGrnId] = useState<number | null>(presetGrnId)
  const [reasonCodeId, setReasonCodeId] = useState<number | null>(null)
  const [lineState, setLineState] = useState<Record<number, LineState>>({})
  const [lineErrors, setLineErrors] = useState<Record<number, Record<string, string>>>({})

  const [headerError, setHeaderError] = useState<string | null>(null)
  const [submitError, setSubmitError] = useState<string | null>(null)
  const [submitting, setSubmitting] = useState(false)

  useEffect(() => {
    Promise.all([grnsApi.list({ pageSize: 200 }), itemsApi.list({ pageSize: 200 }), reasonCodesApi.list("Return")])
      .then(([grnList, it, rc]) => {
        // Only Confirmed/Closed GRNs have posted stock layers to return against.
        Promise.all(grnList.items.filter((g) => g.status === "Confirmed" || g.status === "Closed").map((g) => grnsApi.get(g.grnId))).then(setGrns)
        setItems(it.items)
        setReasonCodes(rc.items)
      })
      .catch((err) => setLoadError(errorMessage(err)))
  }, [])

  const selectedGrn = grns?.find((g) => g.grnId === grnId) ?? null

  useEffect(() => {
    if (!selectedGrn) {
      setLineState({})
      return
    }
    const next: Record<number, LineState> = {}
    for (const line of selectedGrn.lines) {
      next[line.grnLineId] = {
        selected: presetGrnLineId ? line.grnLineId === presetGrnLineId : false,
        qty: presetGrnLineId && line.grnLineId === presetGrnLineId ? String(line.qty) : "",
      }
    }
    setLineState(next)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selectedGrn?.grnId])

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

  function toggleLine(line: GrnLine) {
    setLineState((prev) => ({
      ...prev,
      [line.grnLineId]: { selected: !prev[line.grnLineId]?.selected, qty: prev[line.grnLineId]?.qty || String(line.qty) },
    }))
  }

  function setQty(grnLineId: number, qty: string) {
    setLineState((prev) => ({ ...prev, [grnLineId]: { ...prev[grnLineId], qty } }))
  }

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

    if (!selectedGrn) {
      setHeaderError("Select a GRN to return against.")
      return
    }
    if (!reasonCodeId) {
      setHeaderError("Select a reason code.")
      return
    }

    const selectedLines = selectedGrn.lines.filter((l) => lineState[l.grnLineId]?.selected)
    if (selectedLines.length === 0) {
      setSubmitError("Select at least one line to return.")
      return
    }

    const nextErrors: Record<number, Record<string, string>> = {}
    for (const line of selectedLines) {
      const errors = validateReturnLine({ grnLineId: line.grnLineId, qty: lineState[line.grnLineId].qty, maxQty: line.qty })
      if (Object.keys(errors).length > 0) nextErrors[line.grnLineId] = errors
    }
    setLineErrors(nextErrors)
    if (Object.keys(nextErrors).length > 0) {
      setSubmitError("Fix the highlighted lines before submitting.")
      return
    }

    const payloadLines: CreatePurchaseReturnLineInput[] = selectedLines.map((l) => ({
      grnLineId: l.grnLineId,
      itemId: l.itemId,
      qty: Number(lineState[l.grnLineId].qty),
    }))

    setSubmitting(true)
    try {
      const purchaseReturn = await purchaseReturnsApi.create({
        vendorId: selectedGrn.vendorId,
        warehouseId: selectedGrn.warehouseId,
        reasonCodeId,
        lines: payloadLines,
      })
      toast.success("Purchase return posted", `${purchaseReturn.docNo} — ${purchaseReturn.ledgerRefs.length} ledger entr${purchaseReturn.ledgerRefs.length === 1 ? "y" : "ies"} posted.`)
      router.push("/dashboard/procurement/purchase-returns")
    } catch (err) {
      setSubmitError(errorMessage(err))
      toast.error("Could not post purchase return", errorMessage(err))
    } finally {
      setSubmitting(false)
    }
  }

  const loading = !grns

  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 Purchase Return</h1>
          <p className="text-base text-muted-foreground">Return received goods to the vendor; posts an outbound ledger entry immediately (FR-PROC-08).</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-24 w-full" />}

      {!loading && (
        <>
          <div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
            <div className="flex flex-col gap-2 sm:col-span-2">
              <Label className="text-base">Goods Receipt Note</Label>
              <Select<number | null> value={grnId} onValueChange={setGrnId} disabled={!!presetGrnId}>
                <SelectTrigger className="h-12! w-full text-base">
                  <SelectValue placeholder="Select a confirmed GRN" />
                </SelectTrigger>
                <SelectContent>
                  {(grns ?? []).map((g) => (
                    <SelectItem key={g.grnId} value={g.grnId} className="text-base">
                      {g.docNo} — Vendor #{g.vendorId}, Warehouse #{g.warehouseId}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div className="flex flex-col gap-2">
              <Label className="text-base">Reason</Label>
              <Select<number | null> value={reasonCodeId} onValueChange={setReasonCodeId}>
                <SelectTrigger className="h-12! w-full text-base">
                  <SelectValue placeholder="Select reason" />
                </SelectTrigger>
                <SelectContent>
                  {reasonCodes.map((rc) => (
                    <SelectItem key={rc.reasonCodeId} value={rc.reasonCodeId} className="text-base">
                      {rc.description}
                    </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>
          )}

          {selectedGrn && (
            <div className="flex flex-col gap-3">
              <h2 className="text-base font-semibold text-foreground">Lines received on {selectedGrn.docNo}</h2>
              <Table className="text-base">
                <TableHeader>
                  <TableRow>
                    <TableHead className="h-12 w-10 px-3" />
                    <TableHead className="h-12 px-3 text-sm">Item</TableHead>
                    <TableHead className="h-12 px-3 text-sm">Received qty</TableHead>
                    <TableHead className="h-12 px-3 text-sm">Hold status</TableHead>
                    <TableHead className="h-12 w-36 px-3 text-sm">Return qty</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {selectedGrn.lines.map((line) => {
                    const item = itemFor(line.itemId)
                    const state = lineState[line.grnLineId] ?? { selected: false, qty: "" }
                    const errors = lineErrors[line.grnLineId] ?? {}
                    return (
                      <TableRow key={line.grnLineId}>
                        <TableCell className="px-3 py-3.5">
                          <Checkbox checked={state.selected} onCheckedChange={() => toggleLine(line)} />
                        </TableCell>
                        <TableCell className="px-3 py-3.5">{item ? `${item.sku} — ${item.name}` : `Item #${line.itemId}`}</TableCell>
                        <TableCell className="px-3 py-3.5">{line.qty}</TableCell>
                        <TableCell className="px-3 py-3.5">
                          <HoldStatusBadge status={line.holdStatus} />
                        </TableCell>
                        <TableCell className="px-3 py-3 align-top">
                          <Input
                            type="number"
                            min="0"
                            step="any"
                            value={state.qty}
                            disabled={!state.selected}
                            aria-invalid={!!errors.qty}
                            onChange={(e) => setQty(line.grnLineId, e.target.value)}
                            className="h-11 text-base"
                          />
                          <FieldError errors={[errors.qty ? { message: errors.qty } : undefined]} />
                        </TableCell>
                      </TableRow>
                    )
                  })}
                </TableBody>
              </Table>
            </div>
          )}

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

          <div className="flex justify-end gap-3">
            <Link href="/dashboard/procurement/purchase-returns" className={cn(buttonVariants({ variant: "outline", size: "lg" }))}>
              Cancel
            </Link>
            <Button size="lg" type="button" onClick={handleSubmit} disabled={submitting}>
              {submitting ? "Posting…" : "Post Return"}
            </Button>
          </div>
        </>
      )}
    </div>
  )
}

export default function NewPurchaseReturnPage() {
  return (
    <Suspense fallback={<Skeleton className="h-48 w-full" />}>
      <NewPurchaseReturnContent />
    </Suspense>
  )
}
