"use client"

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

import { salesReturnsApi } from "@/lib/api/sales-returns"
import { salesApi } from "@/lib/api/sales"
import { reasonCodesApi } from "@/lib/api/reason-codes"
import { itemsApi } from "@/lib/api/items"
import { errorMessage } from "@/lib/error-map"
import { validateSalesReturnLine } from "@/lib/validations/sales"
import { cn } from "@/lib/utils"
import { CreateSalesReturnLineInput, SalesInvoice, SalesInvoiceLine } from "@/types/sales"
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"

interface LineState {
  selected: boolean
  qty: string
}

function NewSalesReturnContent() {
  const router = useRouter()
  const searchParams = useSearchParams()
  const presetInvoiceId = Number(searchParams.get("invoiceId")) || null
  const presetLineId = Number(searchParams.get("lineId")) || null

  const [invoices, setInvoices] = useState<SalesInvoice[] | null>(null)
  const [items, setItems] = useState<ItemListItem[]>([])
  const [reasonCodes, setReasonCodes] = useState<ReasonCode[]>([])
  const [loadError, setLoadError] = useState<string | null>(null)
  const [remainingByLine, setRemainingByLine] = useState<Record<number, number>>({})
  const [remainingLoading, setRemainingLoading] = useState(false)

  const [invoiceId, setInvoiceId] = useState<number | null>(presetInvoiceId)
  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([salesApi.listInvoices({ status: "Posted", pageSize: 200 }), itemsApi.list({ pageSize: 200 }), reasonCodesApi.list("Return")])
      .then(([invoiceList, it, rc]) => {
        // Only Posted invoices have stock movements to return against.
        Promise.all(invoiceList.items.map((i) => salesApi.getInvoice(i.salesInvoiceId))).then((results) => setInvoices(results.map((r) => r.data)))
        setItems(it.items)
        setReasonCodes(rc.items)
      })
      .catch((err) => setLoadError(errorMessage(err)))
  }, [])

  const selectedInvoice = invoices?.find((i) => i.salesInvoiceId === invoiceId) ?? null

  useEffect(() => {
    if (!selectedInvoice) {
      setLineState({})
      setRemainingByLine({})
      return
    }
    const next: Record<number, LineState> = {}
    for (const line of selectedInvoice.lines) {
      next[line.salesInvoiceLineId] = { selected: false, qty: "" }
    }
    setLineState(next)
    setRemainingLoading(true)
    salesReturnsApi
      .getRemaining(selectedInvoice.salesInvoiceId)
      .then((rows) => {
        const map: Record<number, number> = {}
        for (const row of rows) map[row.salesInvoiceLineId] = row.remainingQty
        setRemainingByLine(map)
        if (presetLineId) {
          const remaining = map[presetLineId] ?? 0
          setLineState((prev) => ({ ...prev, [presetLineId]: { selected: remaining > 0, qty: remaining > 0 ? String(remaining) : "" } }))
        }
      })
      .catch((err) => setLoadError(errorMessage(err)))
      .finally(() => setRemainingLoading(false))
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selectedInvoice?.salesInvoiceId])

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

  function remainingFor(lineId: number, fallback: number) {
    return remainingByLine[lineId] ?? fallback
  }

  function toggleLine(line: SalesInvoiceLine) {
    const remaining = remainingFor(line.salesInvoiceLineId, line.qty)
    setLineState((prev) => ({
      ...prev,
      [line.salesInvoiceLineId]: { selected: !prev[line.salesInvoiceLineId]?.selected, qty: prev[line.salesInvoiceLineId]?.qty || String(remaining) },
    }))
  }

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

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

    if (!selectedInvoice) {
      setHeaderError("Select an invoice to return against.")
      return
    }
    if (!reasonCodeId) {
      setHeaderError("Select a reason code.")
      return
    }

    const selectedLines = selectedInvoice.lines.filter((l) => lineState[l.salesInvoiceLineId]?.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 = validateSalesReturnLine({
        salesInvoiceLineId: line.salesInvoiceLineId,
        qty: lineState[line.salesInvoiceLineId].qty,
        maxQty: remainingFor(line.salesInvoiceLineId, line.qty),
      })
      if (Object.keys(errors).length > 0) nextErrors[line.salesInvoiceLineId] = errors
    }
    setLineErrors(nextErrors)
    if (Object.keys(nextErrors).length > 0) {
      setSubmitError("Fix the highlighted lines before submitting.")
      return
    }

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

    setSubmitting(true)
    try {
      const salesReturn = await salesReturnsApi.create({
        customerId: selectedInvoice.customerId,
        warehouseId: selectedInvoice.warehouseId,
        reasonCodeId,
        lines: payloadLines,
      })
      toast.success("Sales return posted", `${salesReturn.docNo} — ${salesReturn.ledgerRefs.length} ledger entr${salesReturn.ledgerRefs.length === 1 ? "y" : "ies"} posted.`)
      router.push("/dashboard/sales/sales-returns")
    } catch (err) {
      setSubmitError(errorMessage(err))
      toast.error("Could not post sales return", errorMessage(err))
    } finally {
      setSubmitting(false)
    }
  }

  const loading = !invoices

  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 Sales Return</h1>
          <p className="text-base text-muted-foreground">Return sold goods from a customer; posts an inbound ledger entry immediately.</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">Sales Invoice</Label>
              <Select<number | null> value={invoiceId} onValueChange={setInvoiceId} disabled={!!presetInvoiceId}>
                <SelectTrigger className="h-12! w-full text-base">
                  <SelectValue placeholder="Select a posted invoice" />
                </SelectTrigger>
                <SelectContent>
                  {(invoices ?? []).map((inv) => (
                    <SelectItem key={inv.salesInvoiceId} value={inv.salesInvoiceId} className="text-base">
                      {inv.invoiceNo} — {inv.customerSnapshotName}
                    </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>
          )}

          {selectedInvoice && (
            <div className="flex flex-col gap-3">
              <h2 className="text-base font-semibold text-foreground">Lines invoiced on {selectedInvoice.invoiceNo}</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">Invoiced qty</TableHead>
                    <TableHead className="h-12 px-3 text-sm">Remaining qty</TableHead>
                    <TableHead className="h-12 px-3 text-sm">Unit price</TableHead>
                    <TableHead className="h-12 w-36 px-3 text-sm">Return qty</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {selectedInvoice.lines.map((line) => {
                    const item = itemFor(line.itemId)
                    const state = lineState[line.salesInvoiceLineId] ?? { selected: false, qty: "" }
                    const errors = lineErrors[line.salesInvoiceLineId] ?? {}
                    const remaining = remainingFor(line.salesInvoiceLineId, line.qty)
                    const fullyReturned = !remainingLoading && remaining <= 0
                    return (
                      <TableRow key={line.salesInvoiceLineId}>
                        <TableCell className="px-3 py-3.5">
                          <Checkbox checked={state.selected} disabled={fullyReturned} onCheckedChange={() => toggleLine(line)} />
                        </TableCell>
                        <TableCell className="px-3 py-3.5">{item ? `${item.sku} — ${item.name}` : line.description}</TableCell>
                        <TableCell className="px-3 py-3.5">{line.qty}</TableCell>
                        <TableCell className="px-3 py-3.5">
                          {remainingLoading ? "…" : fullyReturned ? <span className="text-muted-foreground">Fully returned</span> : remaining}
                        </TableCell>
                        <TableCell className="px-3 py-3.5">{line.unitPrice.toFixed(2)}</TableCell>
                        <TableCell className="px-3 py-3 align-top">
                          <Input
                            type="number"
                            min="0"
                            step="any"
                            value={state.qty}
                            disabled={!state.selected || fullyReturned}
                            aria-invalid={!!errors.qty}
                            onChange={(e) => setQty(line.salesInvoiceLineId, 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/sales/sales-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 NewSalesReturnPage() {
  return (
    <Suspense fallback={<Skeleton className="h-48 w-full" />}>
      <NewSalesReturnContent />
    </Suspense>
  )
}
