"use client"

import { useEffect, useMemo, useState } from "react"
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Textarea } from "@/components/ui/textarea"
import { Gift, Loader2, Minus, Percent, Plus, Scissors, ShieldCheck } from "lucide-react"
import { toast } from "@/hooks/use-toast"
import { useAuthStore } from "@/lib/auth-store"
import { hasPermission } from "@/lib/permissions"
import {
  MOTIVOS_DE_AJUSTE,
  TIPOS_DE_AJUSTE,
  cantidadCobrable,
  totalLinea,
  validarAjuste,
  type TipoDeAjuste,
} from "@/lib/line-adjustments"
import { cn } from "@/lib/utils"

/** Lo que una fila del panel sabe de la línea. Los contadores vienen del servidor. */
export type LineaDelPanel = {
  id: string
  name: string
  quantity: number
  price: number
  voidedQuantity?: number
  compedQuantity?: number
  discountPct?: number
  billableQuantity?: number
  lineTotal?: number
}

type Props = {
  open: boolean
  onOpenChange: (open: boolean) => void
  item: LineaDelPanel | null
  tableName: string
  /** El servidor ya escribió el ajuste: quien abre el diálogo recarga la cuenta. */
  onAjustado: (r: { valorUSD: number; repartoReiniciado: boolean }) => void
}

const ICONO: Record<TipoDeAjuste, typeof Scissors> = { VOID: Scissors, COMP: Gift, DISCOUNT: Percent }

/**
 * Anular, cortesía o descuento sobre UNA línea de la cuenta (v1.81.0).
 *
 * Siempre es de gerencia. Si quien está entrado no tiene `order.void`, el
 * diálogo pide el PIN de un gerente y lo cambia por un vale de dos minutos
 * (`POST /api/auth/autorizar`); la bitácora registra a los dos. Lo que se
 * muestra como «se quitan $X» lo calcula la misma librería que usa el
 * servidor, así que no hay sorpresa al confirmar. Se puede cerrar siempre.
 */
export function AjustarLineaDialog({ open, onOpenChange, item, tableName, onAjustado }: Props) {
  const user = useAuthStore((s) => s.user)
  const necesitaPin = !(user?.role && hasPermission(user.role, "order.void"))

  const [tipo, setTipo] = useState<TipoDeAjuste>("VOID")
  const [cantidad, setCantidad] = useState(1)
  const [pct, setPct] = useState("10")
  const [motivo, setMotivo] = useState("")
  const [nota, setNota] = useState("")
  const [pin, setPin] = useState("")
  const [enviando, setEnviando] = useState(false)

  // Cada línea empieza limpia: un motivo elegido para otra no se hereda.
  useEffect(() => {
    if (!open) return
    setTipo("VOID")
    setCantidad(1)
    setPct("10")
    setMotivo("")
    setNota("")
    setPin("")
    setEnviando(false)
  }, [open, item?.id])

  const cobrable = item ? cantidadCobrable(item) : 0
  const motivos = useMemo(() => MOTIVOS_DE_AJUSTE.filter((m) => m.aplicaA.includes(tipo)), [tipo])
  useEffect(() => {
    if (motivo && !motivos.some((m) => m.codigo === motivo)) setMotivo("")
  }, [motivos, motivo])

  const ajuste = { tipo, cantidad, pct: Number(pct), motivo, nota }
  const validacion = item ? validarAjuste(item, ajuste) : null
  const listo = validacion?.ok === true && (!necesitaPin || pin.length === 6)

  const confirmar = async () => {
    if (!item || !validacion?.ok) return
    setEnviando(true)
    try {
      let autorizacion: string | undefined
      if (necesitaPin) {
        const r = await fetch("/api/auth/autorizar", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ pin, permiso: "order.void" }),
        })
        const d = await r.json().catch(() => ({}))
        if (!r.ok) {
          setPin("")
          toast({ title: "No se pudo autorizar", description: d.error ?? "Revisa el PIN", variant: "destructive" })
          return
        }
        autorizacion = d.token
      }

      const r = await fetch(`/api/table-sessions/items/${item.id}/ajustar`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ ...ajuste, autorizacion }),
      })
      const d = await r.json().catch(() => ({}))
      if (!r.ok) {
        toast({ title: "No se pudo ajustar", description: d.error ?? "Intenta de nuevo", variant: "destructive" })
        return
      }
      toast({
        title: `${TIPOS_DE_AJUSTE[tipo].etiqueta} registrada`,
        description: [
          `${tableName}: se quitan $${Number(d.valorUSD).toFixed(2)} de la cuenta.`,
          d.autorizadoPor ? `Autorizó ${d.autorizadoPor}.` : null,
          d.repartoReiniciado ? "El reparto de esa línea vuelve a la mesa." : null,
        ]
          .filter(Boolean)
          .join(" "),
      })
      onAjustado({ valorUSD: Number(d.valorUSD), repartoReiniciado: Boolean(d.repartoReiniciado) })
      onOpenChange(false)
    } catch (e) {
      console.error(e)
      toast({ title: "No se pudo ajustar", description: "Revisa la conexión e intenta de nuevo", variant: "destructive" })
    } finally {
      setEnviando(false)
    }
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="w-[calc(100vw-1rem)] max-w-md max-h-[94vh] overflow-y-auto p-4 sm:p-6">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            <Scissors className="h-5 w-5 text-primary" />
            Ajustar {item?.name ?? "línea"}
          </DialogTitle>
          <DialogDescription>
            {tableName} · {cobrable} por cobrar de {item?.quantity ?? 0} · queda en bitácora con motivo
          </DialogDescription>
        </DialogHeader>

        {item && (
          <div className="space-y-4">
            <div className="grid grid-cols-3 gap-1.5">
              {(Object.keys(TIPOS_DE_AJUSTE) as TipoDeAjuste[]).map((t) => {
                const Icono = ICONO[t]
                return (
                  <Button
                    key={t}
                    type="button"
                    variant={tipo === t ? "default" : "outline"}
                    className="h-11"
                    onClick={() => setTipo(t)}
                  >
                    <Icono className="h-4 w-4 mr-1.5" />
                    {TIPOS_DE_AJUSTE[t].etiqueta}
                  </Button>
                )
              })}
            </div>
            <p className="text-xs text-muted-foreground -mt-2">
              {tipo === "VOID"
                ? "No se cobra y se le quita a cocina. Si ya estaba hecho, cuenta como merma."
                : tipo === "COMP"
                  ? "El cliente lo recibió y no lo paga. Cocina no se entera."
                  : "Rebaja un porcentaje al precio de esta línea. Un solo descuento por línea."}
            </p>

            {tipo === "DISCOUNT" ? (
              <div>
                <Label htmlFor="pct">Porcentaje</Label>
                <div className="flex items-center gap-2 mt-1">
                  {[10, 15, 20, 50, 100].map((p) => (
                    <Button key={p} type="button" size="sm" variant={pct === String(p) ? "default" : "outline"} onClick={() => setPct(String(p))}>
                      {p}%
                    </Button>
                  ))}
                  <Input
                    id="pct"
                    inputMode="numeric"
                    className="w-20 text-center"
                    value={pct}
                    onChange={(e) => setPct(e.target.value.replace(/[^\d.]/g, "").slice(0, 5))}
                  />
                </div>
                {(item.discountPct ?? 0) > 0 && (
                  <p className="text-xs text-muted-foreground mt-1">Hoy tiene −{item.discountPct}%. El nuevo lo reemplaza.</p>
                )}
              </div>
            ) : (
              <div>
                <Label>Unidades</Label>
                <div className="flex items-center gap-3 mt-1">
                  <Button type="button" variant="outline" size="icon" disabled={cantidad <= 1} onClick={() => setCantidad((c) => Math.max(1, c - 1))} aria-label="Una unidad menos">
                    <Minus className="h-4 w-4" />
                  </Button>
                  <span className="text-2xl font-bold w-10 text-center tabular-nums">{cantidad}</span>
                  <Button type="button" variant="outline" size="icon" disabled={cantidad >= cobrable} onClick={() => setCantidad((c) => Math.min(cobrable, c + 1))} aria-label="Una unidad más">
                    <Plus className="h-4 w-4" />
                  </Button>
                  <span className="text-sm text-muted-foreground">de {cobrable}</span>
                </div>
              </div>
            )}

            <div>
              <Label>Motivo</Label>
              <div className="grid grid-cols-2 gap-1.5 mt-1">
                {motivos.map((m) => (
                  <Button
                    key={m.codigo}
                    type="button"
                    size="sm"
                    variant={motivo === m.codigo ? "default" : "outline"}
                    className="h-auto min-h-9 py-1.5 whitespace-normal text-left justify-start text-xs"
                    onClick={() => setMotivo(m.codigo)}
                  >
                    {m.etiqueta}
                  </Button>
                ))}
              </div>
            </div>

            <div>
              <Label htmlFor="nota">Nota {motivo === "OTRO" ? "(obligatoria)" : "(opcional)"}</Label>
              <Textarea id="nota" rows={2} maxLength={190} value={nota} onChange={(e) => setNota(e.target.value)} placeholder="Qué pasó, en una línea" />
            </div>

            <div className={cn("rounded-md px-3 py-2 text-sm", validacion?.ok ? "bg-amber-50 text-amber-900" : "bg-muted text-muted-foreground")}>
              {validacion?.ok
                ? `Se quitan $${validacion.valorUSD.toFixed(2)}. La línea queda en $${(totalLinea(item) - validacion.valorUSD).toFixed(2)}.`
                : validacion?.error ?? "Elige qué y por qué"}
            </div>

            {necesitaPin && (
              <div className="rounded-md border border-primary/30 p-3 space-y-1.5">
                <Label htmlFor="pin-gerencia" className="flex items-center gap-1.5">
                  <ShieldCheck className="h-4 w-4 text-primary" />
                  PIN de gerencia
                </Label>
                <Input
                  id="pin-gerencia"
                  type="password"
                  inputMode="numeric"
                  autoComplete="off"
                  maxLength={6}
                  placeholder="••••••"
                  value={pin}
                  onChange={(e) => setPin(e.target.value.replace(/\D/g, "").slice(0, 6))}
                  className="text-center text-2xl tracking-[0.4em] font-mono h-12"
                />
                <p className="text-xs text-muted-foreground">Esta acción la autoriza un gerente. Su nombre queda junto al tuyo en la bitácora.</p>
              </div>
            )}
          </div>
        )}

        <DialogFooter className="gap-2 sm:gap-0">
          <Button type="button" variant="outline" onClick={() => onOpenChange(false)} disabled={enviando}>
            Cancelar
          </Button>
          <Button type="button" onClick={confirmar} disabled={!listo || enviando} className="bg-naranja-vip hover:bg-naranja-vip/90 text-white">
            {enviando ? <Loader2 className="h-4 w-4 animate-spin mr-2" /> : null}
            Confirmar {TIPOS_DE_AJUSTE[tipo].etiqueta.toLowerCase()}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}

/** Fila de una línea con sus ajustes a la vista (tachado, cortesía, %). */
export function LineaAjustada({ item, className }: { item: LineaDelPanel; className?: string }) {
  const cobrable = item.billableQuantity ?? cantidadCobrable(item)
  const anuladas = item.voidedQuantity ?? 0
  const cortesia = item.compedQuantity ?? 0
  const pct = item.discountPct ?? 0
  return (
    <span className={cn("flex flex-wrap items-center gap-x-1.5 gap-y-0.5 min-w-0", className)}>
      <span className={cn("truncate", cobrable === 0 && "line-through text-muted-foreground")}>
        {cobrable}x {item.name}
      </span>
      {anuladas > 0 && (
        <span className="text-[11px] rounded bg-red-100 text-red-800 px-1.5 py-0.5">{anuladas} anulada{anuladas === 1 ? "" : "s"}</span>
      )}
      {cortesia > 0 && (
        <span className="text-[11px] rounded bg-emerald-100 text-emerald-800 px-1.5 py-0.5">{cortesia} cortesía</span>
      )}
      {pct > 0 && <span className="text-[11px] rounded bg-amber-100 text-amber-900 px-1.5 py-0.5">−{pct}%</span>}
    </span>
  )
}
