"use client"

import { useState } from "react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Badge } from "@/components/ui/badge"
import { Progress } from "@/components/ui/progress"
import { ArrowLeft, CheckCircle2, Loader2, Pencil, Receipt } from "lucide-react"
import { toast } from "@/hooks/use-toast"
import { DualCurrencyDisplay } from "@/components/dual-currency-display"
import { cn } from "@/lib/utils"
import { CobroControles, nombreDeMetodo, type Moneda, type PaymentMethod } from "@/components/admin/cobro-controles"
import type { DivisionData } from "@/components/admin/dividir-cuenta"
import { MotivoDialog } from "@/components/admin/motivo-dialog"
import { MOTIVOS_DE_ANULACION_PAGO } from "@/lib/line-adjustments"
import { Ban } from "lucide-react"

interface CobroPorPersonaProps {
  sessionId: string
  division: DivisionData
  /** Después de cada pago registrado, con la división fresca del servidor. */
  onPagoRegistrado: (r: { division: DivisionData; cuentaCerrada: boolean }) => void
  onEditarReparto: () => void
  /** «Cobrar el resto» pasa a la cuenta completa (el PATCH ya descuenta lo cobrado). */
  onCobrarElResto: () => void
}

type Cobrando = { dinerId: string | null; nombre: string; saldo: number }

const fmt = (n: number) => `$${n.toFixed(2)}`

/**
 * Tablero de cobro de una cuenta dividida: una tarjeta por persona con su
 * saldo, «Cobrar a X», un pago libre sin persona y «Cobrar el resto». Cada
 * pago va a `POST /api/table-sessions/payments`; cuando la suma cubre el
 * consumo, el servidor cierra la cuenta solo y acá se avisa.
 */
export function CobroPorPersona({ sessionId, division, onPagoRegistrado, onEditarReparto, onCobrarElResto }: CobroPorPersonaProps) {
  const { resumen } = division
  const [cobrando, setCobrando] = useState<Cobrando | null>(null)
  const [monto, setMonto] = useState("")
  const [method, setMethod] = useState<PaymentMethod>("cash")
  const [currency, setCurrency] = useState<Moneda>("USD")
  const [tip, setTip] = useState(0)
  const [reference, setReference] = useState("")
  const [isProcessing, setIsProcessing] = useState(false)
  // Pago que gerencia está anulando (v1.84.0)
  const [anulando, setAnulando] = useState<DivisionData["pagos"][number] | null>(null)
  const pagosVigentes = division.pagos.filter((p) => !p.anulado)
  const nombreDeComensal = (dinerId: string | null) => division.diners.find((d) => d.id === dinerId)?.name ?? null

  const abrirCobro = (c: Cobrando) => {
    setCobrando(c)
    setMonto(c.saldo.toFixed(2))
    setTip(0)
    setReference("")
  }

  const montoNumero = Math.max(0, Number.parseFloat(monto) || 0)
  const tope = cobrando?.saldo ?? 0
  const excede = montoNumero > tope + 0.01
  const totalACobrar = Math.round((montoNumero + tip) * 100) / 100

  const confirmar = async () => {
    if (!cobrando || montoNumero <= 0 || excede) return
    setIsProcessing(true)
    try {
      const res = await fetch("/api/table-sessions/payments", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          sessionId,
          dinerId: cobrando.dinerId,
          amount: montoNumero,
          tip,
          method: method.toUpperCase(),
          currency,
          reference: reference.trim() || null,
        }),
      })
      const data = await res.json().catch(() => ({}))
      if (!res.ok) {
        if (res.status === 409) {
          // Alguien cerró la cuenta mientras tanto: se recarga y se sale.
          onPagoRegistrado({ division: { ...division, session: { ...division.session, status: "PAID" } }, cuentaCerrada: true })
        }
        throw new Error(data.error || "No se pudo registrar el pago")
      }
      const nueva: DivisionData = {
        session: data.session ?? division.session,
        diners: division.diners,
        items: division.items,
        pagos: data.payments ?? division.pagos,
        resumen: data.resumen,
      }
      if (data.cuentaCerrada) {
        toast({ title: "Cuenta saldada", description: "La mesa quedó libre." })
      } else {
        toast({
          title: cobrando.nombre ? `Pago de ${cobrando.nombre} registrado` : "Pago registrado",
          description: `${fmt(montoNumero)} en ${nombreDeMetodo(method)}. Faltan ${fmt(data.resumen.saldoPendiente)}.`,
        })
      }
      setCobrando(null)
      onPagoRegistrado({ division: nueva, cuentaCerrada: Boolean(data.cuentaCerrada) })
    } catch (e) {
      toast({
        title: "Error",
        description: e instanceof Error ? e.message : "No se pudo registrar el pago",
        variant: "destructive",
      })
    } finally {
      setIsProcessing(false)
    }
  }

  if (cobrando) {
    return (
      <div className="space-y-4">
        <div className="flex items-center gap-2">
          <Button type="button" variant="ghost" size="icon" className="h-8 w-8" onClick={() => setCobrando(null)} aria-label="Volver">
            <ArrowLeft className="h-4 w-4" />
          </Button>
          <h3 className="font-semibold">{cobrando.dinerId ? `Cobrar a ${cobrando.nombre}` : "Pago libre"}</h3>
        </div>

        <div>
          <Label className="text-primary mb-2 block">Monto (USD)</Label>
          <Input
            type="number"
            inputMode="decimal"
            min={0.01}
            step="0.01"
            value={monto}
            onChange={(e) => setMonto(e.target.value)}
            onBlur={() => {
              if (montoNumero > tope) setMonto(tope.toFixed(2))
            }}
            className={cn("text-lg font-semibold", excede && "border-destructive")}
          />
          <p className={cn("text-xs mt-1", excede ? "text-destructive" : "text-muted-foreground")}>
            {excede
              ? `El máximo es ${fmt(tope)}, lo que ${cobrando.dinerId ? `le falta a ${cobrando.nombre}` : "falta cobrar"}.`
              : cobrando.dinerId
                ? `Le falta ${fmt(tope)}. Si deja más, va como propina.`
                : `Falta cobrar ${fmt(tope)} en total.`}
          </p>
        </div>

        <CobroControles
          compact
          base={montoNumero}
          method={method}
          onMethod={setMethod}
          currency={currency}
          onCurrency={setCurrency}
          tip={tip}
          onTip={setTip}
        />

        {method !== "cash" && (
          <Input
            value={reference}
            onChange={(e) => setReference(e.target.value)}
            placeholder="Referencia (opcional)"
            maxLength={120}
            className="h-9"
          />
        )}

        <div className="p-3 bg-muted/50 rounded-lg space-y-1">
          <div className="flex justify-between text-sm">
            <span>Consumo</span>
            <span>{fmt(montoNumero)}</span>
          </div>
          {tip > 0 && (
            <div className="flex justify-between text-sm">
              <span>Propina</span>
              <span>{fmt(tip)}</span>
            </div>
          )}
          <div className="flex justify-between items-center font-bold border-t pt-1">
            <span>Cobra</span>
            <DualCurrencyDisplay amountUSD={totalACobrar} size="sm" showBothAlways primaryCurrency="USD" />
          </div>
        </div>

        <Button
          type="button"
          className="w-full h-11 bg-green-600 hover:bg-green-700 text-white"
          disabled={isProcessing || montoNumero <= 0 || excede}
          onClick={confirmar}
        >
          {isProcessing ? <Loader2 className="h-4 w-4 animate-spin mr-2" /> : <CheckCircle2 className="h-4 w-4 mr-2" />}
          Confirmar {fmt(totalACobrar)}
        </Button>
      </div>
    )
  }

  const avance = resumen.totalCuenta > 0 ? Math.min(100, (resumen.totalPagado / resumen.totalCuenta) * 100) : 0

  return (
    <div className="space-y-4">
      <div className="space-y-1">
        <Progress value={avance} className="h-2" />
        <div className="flex justify-between text-xs text-muted-foreground">
          <span>
            Pagado {fmt(resumen.totalPagado)} de {fmt(resumen.totalCuenta)}
          </span>
          <span className="font-medium text-foreground">Falta {fmt(resumen.saldoPendiente)}</span>
        </div>
        {resumen.propinaTotal > 0 && <p className="text-xs text-muted-foreground">Propinas: {fmt(resumen.propinaTotal)}</p>}
      </div>

      <div className="flex items-center justify-between">
        <span className="text-sm font-medium">
          {resumen.comensales.length} {resumen.comensales.length === 1 ? "persona" : "personas"}
        </span>
        <Button type="button" variant="ghost" size="sm" onClick={onEditarReparto}>
          <Pencil className="h-3.5 w-3.5 mr-1" />
          Editar reparto
        </Button>
      </div>

      <div className="space-y-2">
        {resumen.comensales.map((c) => (
          <div key={c.dinerId} className={cn("border rounded-lg p-3 space-y-2", c.estaSaldado && "bg-green-50 border-green-200")}>
            <div className="flex items-center justify-between gap-2">
              <div className="min-w-0">
                <p className={cn("font-medium truncate", c.estaSaldado && "text-green-800")}>{c.name}</p>
                <p className="text-xs text-muted-foreground">
                  Propio {fmt(c.propio)} · Compartido {fmt(c.compartido)}
                  {c.pagado > 0 && ` · Pagado ${fmt(c.pagado)}`}
                </p>
                {c.lineas.length > 0 && (
                  <p className="text-[11px] text-muted-foreground break-words line-clamp-2">
                    {c.lineas.map((l) => `${l.quantity}x ${l.name}`).join(", ")}
                  </p>
                )}
              </div>
              {c.estaSaldado ? (
                <Badge className="bg-green-600 text-white shrink-0">PAGADO</Badge>
              ) : (
                <span className="font-bold shrink-0">{fmt(c.saldo)}</span>
              )}
            </div>
            {!c.estaSaldado && (
              <Button
                type="button"
                className="w-full h-11"
                onClick={() => abrirCobro({ dinerId: c.dinerId, nombre: c.name, saldo: c.saldo })}
              >
                <Receipt className="h-4 w-4 mr-2" />
                Cobrar a {c.name} {fmt(c.saldo)}
              </Button>
            )}
          </div>
        ))}
      </div>

      {pagosVigentes.length > 0 && (
        <div className="border rounded-lg overflow-hidden">
          <div className="bg-muted/50 px-3 py-1.5 text-xs font-medium border-b">Pagos registrados</div>
          {pagosVigentes.map((p) => (
            <div key={p.id} className="flex items-center justify-between gap-2 px-3 py-2 border-b last:border-0 text-sm">
              <div className="min-w-0">
                <span className="font-medium">{fmt(p.amount)}</span>
                {p.tip > 0 && <span className="text-muted-foreground"> + {fmt(p.tip)} propina</span>}
                <span className="text-xs text-muted-foreground block truncate">
                  {p.method}{p.enLinea ? " · en línea" : ""}{nombreDeComensal(p.dinerId) ? ` · ${nombreDeComensal(p.dinerId)}` : ""}
                </span>
              </div>
              {/* Siempre de gerencia; si no tienes el permiso, el diálogo pide el PIN de un gerente. */}
              <Button type="button" variant="ghost" size="sm" className="text-destructive shrink-0" onClick={() => setAnulando(p)} title="Anular este pago (gerencia)">
                <Ban className="h-3.5 w-3.5 mr-1" />
                Anular
              </Button>
            </div>
          ))}
        </div>
      )}

      <MotivoDialog
        open={Boolean(anulando)}
        onOpenChange={(abierto) => !abierto && setAnulando(null)}
        title={`Anular el pago de ${anulando ? fmt(anulando.amount) : ""}`}
        description={
          anulando?.enLinea
            ? "Es un pago en línea: se anula en la cuenta y en caja, pero el dinero hay que devolverlo por transferencia."
            : "El pago queda anulado en la cuenta y caja lo ve como una anulación en rojo. Queda en bitácora con motivo."
        }
        motivos={MOTIVOS_DE_ANULACION_PAGO}
        permisoRequerido="order.void"
        textoConfirmar="Anular pago"
        onConfirmar={async ({ motivo, nota, autorizacion }) => {
          if (!anulando) return
          const res = await fetch(`/api/table-sessions/payments/${anulando.id}/anular`, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ motivo, nota, autorizacion }),
          })
          const data = await res.json().catch(() => ({}))
          if (!res.ok) throw new Error(data.error ?? "No se pudo anular el pago")
          toast({
            title: "Pago anulado",
            description: `${fmt(anulando.amount)} vuelve a estar pendiente.${data.autorizadoPor ? ` Autorizó ${data.autorizadoPor}.` : ""}${data.enLinea ? " Devuélvelo por transferencia." : ""}`,
          })
          onPagoRegistrado({ division: { ...division, pagos: data.payments ?? division.pagos, resumen: data.resumen ?? division.resumen }, cuentaCerrada: false })
        }}
      />

      {resumen.saldoPendiente > 0.01 && (
        <div className="space-y-2 pt-1">
          <Button
            type="button"
            variant="outline"
            className="w-full"
            onClick={() => abrirCobro({ dinerId: null, nombre: "", saldo: resumen.saldoPendiente })}
          >
            Registrar un monto sin persona
          </Button>
          <Button type="button" variant="secondary" className="w-full" onClick={onCobrarElResto}>
            Cobrar el resto ({fmt(resumen.saldoPendiente)}) como cuenta completa
          </Button>
          <p className="text-[11px] text-muted-foreground text-center">
            Cuando la suma cubre el consumo, la cuenta se cierra sola y la mesa queda libre.
          </p>
        </div>
      )}
    </div>
  )
}
