"use client"

import { useCallback, useEffect, useState } from "react"
import { useRouter } from "next/navigation"
import { ChevronRight, PlayCircle, RotateCcw, Search } from "lucide-react"

import { cn } from "@/lib/utils"
import { productionRunsApi } from "@/lib/api/production-runs"
import { productionTemplatesApi } from "@/lib/api/production-templates"
import { warehousesApi } from "@/lib/api/warehouses"
import { errorMessage } from "@/lib/error-map"
import { ProductionRunStatus, ProductionRunSummary, ProductionTemplateSummary } from "@/types/production"
import { Bin, Warehouse } from "@/types/master-data"
import { PaginationMeta } from "@/types/common"
import { STAGE_STATUS_COLOR, STAGE_STATUS_LABEL, STAGE_STATUS_ORDER } from "@/lib/production-status-colors"

import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"
import { Field, FieldError, FieldGroup, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Skeleton } from "@/components/ui/skeleton"
import { toast } from "@/components/ui/toast"
import { StageProgressStrip, StageStatusLegend } from "@/components/production/stage-progress-strip"

const PAGE_SIZE = 25

type StatusFilter = ProductionRunStatus | "All"

function runStatusBadgeClass(status: ProductionRunStatus) {
  if (status === "Completed") return "bg-success/10 text-success"
  if (status === "Cancelled") return "bg-destructive/10 text-destructive"
  return "bg-info/10 text-info"
}

const SUMMARY_KEYS = {
  Waiting: "waiting",
  Ready: "ready",
  InProgress: "inProgress",
  Done: "done",
  Approved: "approved",
} as const

export default function ProductionRunsPage() {
  const router = useRouter()

  // null = still loading (the codebase convention for "no data yet" vs "empty result").
  const [runs, setRuns] = useState<ProductionRunSummary[] | null>(null)
  const [pagination, setPagination] = useState<PaginationMeta | null>(null)
  const [loadError, setLoadError] = useState<string | null>(null)

  const [searchInput, setSearchInput] = useState("")
  const [query, setQuery] = useState("")
  const [status, setStatus] = useState<StatusFilter>("All")
  const [templateId, setTemplateId] = useState<number | null>(null)
  const [warehouseId, setWarehouseId] = useState<number | null>(null)
  const [page, setPage] = useState(1)

  const [templates, setTemplates] = useState<ProductionTemplateSummary[]>([])
  const [warehouses, setWarehouses] = useState<Warehouse[]>([])

  const [open, setOpen] = useState(false)
  const [startTemplateId, setStartTemplateId] = useState<number | null>(null)
  const [targetQty, setTargetQty] = useState("")
  const [startWarehouseId, setStartWarehouseId] = useState<number | null>(null)
  const [bins, setBins] = useState<Bin[]>([])
  const [outputBinId, setOutputBinId] = useState<number | null>(null)
  const [formError, setFormError] = useState("")
  const [submitting, setSubmitting] = useState(false)

  // 300ms debounce, matching app/dashboard/receiving/grn/page.tsx. Resets to page 1 with the
  // query so a narrower search can't leave you stranded past the last page.
  useEffect(() => {
    const timer = setTimeout(() => {
      setQuery(searchInput.trim())
      setPage(1)
    }, 300)
    return () => clearTimeout(timer)
  }, [searchInput])

  const load = useCallback(() => {
    setLoadError(null)
    productionRunsApi
      .list({
        page,
        pageSize: PAGE_SIZE,
        q: query || undefined,
        status: status === "All" ? undefined : status,
        templateId: templateId ?? undefined,
        warehouseId: warehouseId ?? undefined,
      })
      .then((res) => {
        setRuns(res.items)
        setPagination(res.pagination)
      })
      .catch((err) => {
        setRuns([])
        setLoadError(errorMessage(err))
      })
  }, [page, query, status, templateId, warehouseId])

  useEffect(load, [load])

  // Filter and picker fills. Templates are fetched unfiltered so the *filter* can name an
  // Inactive template that still has historical runs; the start dialog narrows to Active
  // itself, because FR-MFG-01 only blocks starting new runs (docs/21 §4).
  useEffect(() => {
    Promise.all([productionTemplatesApi.list({ pageSize: 200 }), warehousesApi.list({ pageSize: 200 })])
      .then(([templateRes, warehouseRes]) => {
        setTemplates(templateRes.items)
        setWarehouses(warehouseRes.items)
      })
      .catch((err) => toast.error("Could not load filters", errorMessage(err)))
  }, [])

  // Bins belong to a warehouse, so the list is only meaningful once one is picked.
  useEffect(() => {
    if (startWarehouseId === null) {
      setBins([])
      return
    }
    warehousesApi
      .listBins(startWarehouseId)
      .then(setBins)
      .catch(() => setBins([]))
  }, [startWarehouseId])

  const startableTemplates = templates.filter((t) => t.status === "Active")
  const startTemplate = startableTemplates.find((t) => t.templateId === startTemplateId) ?? null
  const targetQtyNum = Number(targetQty)

  function openStartDialog() {
    setStartTemplateId(null)
    setTargetQty("")
    setStartWarehouseId(null)
    setOutputBinId(null)
    setFormError("")
    setOpen(true)
  }

  async function handleStartRun() {
    if (!startTemplate) return setFormError("Pick a template.")
    if (!(targetQtyNum > 0)) return setFormError("Target quantity must be greater than 0.")
    if (startWarehouseId === null) return setFormError("Pick a warehouse.")

    setFormError("")
    setSubmitting(true)
    try {
      const { data } = await productionRunsApi.create({
        templateId: startTemplate.templateId,
        targetQty: targetQtyNum,
        warehouseId: startWarehouseId,
        outputBinId,
      })
      toast.success("Run started", `${data.docNo} — ${data.templateName}`)
      setOpen(false)
      // Straight to the run: the per-stage quantities the operator may want to adjust before
      // starting stage one only exist there (docs/30 §4).
      router.push(`/dashboard/production/runs/${data.runId}`)
    } catch (err) {
      setFormError(errorMessage(err))
    } finally {
      setSubmitting(false)
    }
  }

  const hasFilters = query.length > 0 || status !== "All" || templateId !== null || warehouseId !== null

  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>
          <h1 className="text-2xl font-bold text-foreground">Production Runs</h1>
          <p className="text-base text-muted-foreground">All manufacturing runs with per-stage progress at a glance.</p>
        </div>
        <Dialog open={open} onOpenChange={setOpen}>
          <DialogTrigger render={<Button size="lg" onClick={openStartDialog}><PlayCircle className="size-5" />Start Run</Button>} />
          <DialogContent className="sm:max-w-md">
            <DialogHeader className="items-center text-center">
              <DialogTitle>Start a run</DialogTitle>
              <DialogDescription>Fine-tune per-stage quantities afterward on the run itself.</DialogDescription>
            </DialogHeader>
            <FieldGroup>
              <Field data-invalid={!!formError && !startTemplate}>
                <FieldLabel>Template</FieldLabel>
                <Select<number> value={startTemplateId} onValueChange={setStartTemplateId}>
                  <SelectTrigger className="h-11! w-full text-base">
                    <SelectValue placeholder={startableTemplates.length === 0 ? "No active templates" : "Pick a template"} />
                  </SelectTrigger>
                  <SelectContent>
                    {startableTemplates.map((t) => (
                      <SelectItem key={t.templateId} value={t.templateId} className="text-base">
                        {t.name} · {t.code}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </Field>

              <Field data-invalid={!!formError && !(targetQtyNum > 0)}>
                <FieldLabel htmlFor="target-qty">Target quantity</FieldLabel>
                <Input
                  id="target-qty"
                  type="number"
                  min={0}
                  step="any"
                  value={targetQty}
                  onChange={(e) => setTargetQty(e.target.value)}
                  placeholder="e.g. 200"
                />
              </Field>

              <Field data-invalid={!!formError && startWarehouseId === null}>
                <FieldLabel>Warehouse</FieldLabel>
                <Select<number> value={startWarehouseId} onValueChange={(v) => { setStartWarehouseId(v); setOutputBinId(null) }}>
                  <SelectTrigger className="h-11! w-full text-base">
                    <SelectValue placeholder="Pick a warehouse" />
                  </SelectTrigger>
                  <SelectContent>
                    {warehouses.map((w) => (
                      <SelectItem key={w.warehouseId} value={w.warehouseId} className="text-base">
                        {w.name} · {w.code}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </Field>

              <Field>
                <FieldLabel>Output bin (optional)</FieldLabel>
                <Select<number> value={outputBinId} onValueChange={setOutputBinId}>
                  <SelectTrigger className="h-11! w-full text-base" disabled={bins.length === 0}>
                    <SelectValue placeholder={startWarehouseId === null ? "Pick a warehouse first" : bins.length === 0 ? "No bins in this warehouse" : "No specific bin"} />
                  </SelectTrigger>
                  <SelectContent>
                    {bins.map((b) => (
                      <SelectItem key={b.binId} value={b.binId} className="text-base">
                        {b.code}
                        {b.binType ? ` · ${b.binType}` : ""}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </Field>

              {startTemplate && targetQtyNum > 0 && (
                <div className="rounded-lg border border-border bg-muted/40 p-3 text-sm text-muted-foreground">
                  Every stage&apos;s planned inputs and outputs are scaled from the template&apos;s per-batch figures against
                  this target. The authoritative numbers come back with the run and stay editable until each stage starts.
                </div>
              )}

              <FieldError errors={[formError ? { message: formError } : undefined]} />
            </FieldGroup>
            <div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
              <Button variant="outline" className="w-full sm:w-auto sm:min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
                Cancel
              </Button>
              <Button className="w-full sm:w-auto sm:min-w-36" onClick={handleStartRun} disabled={submitting}>
                {submitting ? "Starting…" : "Start run"}
              </Button>
            </div>
          </DialogContent>
        </Dialog>
      </div>

      <div className="flex flex-col gap-3 sm:flex-row sm:items-center">
        <div className="relative flex-1 basis-0">
          <Search className="pointer-events-none absolute top-1/2 left-4 size-5 -translate-y-1/2 text-muted-foreground" />
          <Input
            value={searchInput}
            onChange={(e) => setSearchInput(e.target.value)}
            placeholder="Search doc no…"
            className="h-14 w-full pl-11 text-base"
            aria-label="Search runs"
          />
        </div>
        <Select<number | null>
          value={templateId}
          onValueChange={(v) => { setTemplateId(v); setPage(1) }}
        >
          <SelectTrigger className="h-14! w-full flex-1 basis-0 text-base">
            <SelectValue placeholder="All templates" />
          </SelectTrigger>
          <SelectContent>
            {templates.map((t) => (
              <SelectItem key={t.templateId} value={t.templateId} className="text-base">{t.name}</SelectItem>
            ))}
          </SelectContent>
        </Select>
        <Select<number | null>
          value={warehouseId}
          onValueChange={(v) => { setWarehouseId(v); setPage(1) }}
        >
          <SelectTrigger className="h-14! w-full flex-1 basis-0 text-base">
            <SelectValue placeholder="All warehouses" />
          </SelectTrigger>
          <SelectContent>
            {warehouses.map((w) => (
              <SelectItem key={w.warehouseId} value={w.warehouseId} className="text-base">{w.name}</SelectItem>
            ))}
          </SelectContent>
        </Select>
        <Select<StatusFilter> value={status} onValueChange={(v) => { setStatus(v ?? "All"); setPage(1) }}>
          <SelectTrigger className="h-14! w-full sm:w-48 text-base">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="All" className="text-base">All statuses</SelectItem>
            <SelectItem value="InProgress" className="text-base">In Progress</SelectItem>
            <SelectItem value="Completed" className="text-base">Completed</SelectItem>
            <SelectItem value="Cancelled" className="text-base">Cancelled</SelectItem>
          </SelectContent>
        </Select>
      </div>

      {hasFilters && (
        <Button
          variant="ghost"
          size="sm"
          className="w-fit"
          onClick={() => {
            setSearchInput("")
            setStatus("All")
            setTemplateId(null)
            setWarehouseId(null)
            setPage(1)
          }}
        >
          Clear filters
        </Button>
      )}

      <div className="rounded-2xl bg-card p-4 shadow-sm ring-1 ring-foreground/10">
        <StageStatusLegend />
      </div>

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

      {runs === null ? (
        <div className="flex flex-col gap-3">
          <Skeleton className="h-32 w-full rounded-2xl" />
          <Skeleton className="h-32 w-full rounded-2xl" />
          <Skeleton className="h-32 w-full rounded-2xl" />
        </div>
      ) : runs.length === 0 ? (
        <div className="flex flex-col items-center gap-4 rounded-xl border border-dashed py-20 text-center">
          <PlayCircle className="size-12 text-muted-foreground" />
          <p className="text-base text-muted-foreground">
            {hasFilters ? "No runs match your search/filter." : "No runs yet."}
          </p>
        </div>
      ) : (
        <>
          <div className="flex flex-col gap-3">
            {runs.map((r) => {
              const warehouse = warehouses.find((w) => w.warehouseId === r.warehouseId)
              return (
                <button
                  key={r.runId}
                  type="button"
                  onClick={() => router.push(`/dashboard/production/runs/${r.runId}`)}
                  className="w-full rounded-2xl bg-card p-4 text-left shadow-sm ring-1 ring-foreground/10 transition-colors hover:ring-primary/40 sm:p-5"
                >
                  <div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
                    <div className="flex min-w-0 flex-col gap-1">
                      <div className="flex flex-wrap items-center gap-2">
                        <span className="font-semibold text-foreground">{r.docNo}</span>
                        <Badge variant="outline" className={cn("h-6 w-fit justify-center border-transparent px-2.5 text-sm", runStatusBadgeClass(r.status))}>
                          {r.status === "InProgress" ? "In Progress" : r.status}
                        </Badge>
                        {r.reworkCount > 0 && (
                          <Badge
                            variant="outline"
                            className="h-6 w-fit justify-center gap-1 border-transparent bg-warning/10 px-2.5 text-sm text-warning"
                          >
                            <RotateCcw className="size-3.5" />
                            Rework #{r.reworkCount}
                          </Badge>
                        )}
                      </div>
                      <p className="text-sm text-muted-foreground">
                        {r.templateName}
                        {warehouse && ` · ${warehouse.name}`}
                      </p>
                    </div>
                    <div className="flex shrink-0 items-start gap-2 sm:items-center">
                      <div className="flex flex-col text-left sm:text-right">
                        <span className="text-sm font-medium text-foreground">
                          {r.targetQty.toLocaleString()}
                          {r.finishedItemName && ` · ${r.finishedItemName}`}
                        </span>
                        <span className="text-sm text-muted-foreground">
                          Created {new Date(r.createdAt).toLocaleDateString()}
                          {r.completedAt && <> · Completed {new Date(r.completedAt).toLocaleDateString()}</>}
                        </span>
                      </div>
                      <ChevronRight className="hidden size-5 shrink-0 text-muted-foreground sm:block" />
                    </div>
                  </div>

                  <StageProgressStrip status={r.status} summary={r.stageSummary} className="mt-4" />

                  {/*
                    Counts per status, not named stages. The list projection carries `stageSummary`
                    only — which stage is in which state is on the run detail — so naming them here
                    would mean guessing an allocation, which is what the mock used to do.
                  */}
                  <div className="mt-3 flex flex-wrap gap-2">
                    {STAGE_STATUS_ORDER.filter((key) => r.stageSummary[SUMMARY_KEYS[key]] > 0).map((key) => (
                      <span
                        key={key}
                        className="inline-flex items-center gap-1.5 rounded-full bg-muted/50 px-2.5 py-1 text-xs font-medium text-foreground"
                      >
                        <span className="size-2 shrink-0 rounded-full" style={{ backgroundColor: STAGE_STATUS_COLOR[key] }} />
                        {r.stageSummary[SUMMARY_KEYS[key]]} {STAGE_STATUS_LABEL[key]}
                      </span>
                    ))}
                  </div>
                </button>
              )
            })}
          </div>

          {pagination && pagination.totalPages > 1 && (
            <div className="flex items-center justify-between">
              <p className="text-base text-muted-foreground">
                Showing {(pagination.page - 1) * pagination.pageSize + 1}–
                {Math.min(pagination.page * pagination.pageSize, pagination.totalItems)} of {pagination.totalItems}
              </p>
              <div className="flex gap-2">
                <Button variant="outline" onClick={() => setPage((p) => p - 1)} disabled={pagination.page <= 1}>
                  Previous
                </Button>
                <Button variant="outline" onClick={() => setPage((p) => p + 1)} disabled={pagination.page >= pagination.totalPages}>
                  Next
                </Button>
              </div>
            </div>
          )}
        </>
      )}
    </div>
  )
}
