"use client"

import { useMemo, useState } from "react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Loader2, Minus, Plus, UserPlus, X } from "lucide-react"
import { toast } from "@/hooks/use-toast"
import { cn } from "@/lib/utils"
import type { ItemParaDividir, ResumenDivision } from "@/lib/split-bill"

/**
 * Lo que devuelve `GET /api/table-sessions/diners`: la división de una cuenta
 * tal como la tiene el servidor. Todo número que se muestra sale de `resumen`;
 * el navegador nunca suma partes.
 */
export type DivisionData = {
  session: { id: string; status: string }
  diners: { id: string; name: string }[]
  items: ItemParaDividir[]
  pagos: { id: string; dinerId: string | null; amount: number; tip: number; method: string; enLinea: boolean; anulado?: boolean; voidReason?: string | null }[]
  resumen: ResumenDivision
}

export function comensalesQuePagaron(d: DivisionData): Set<string> {
  return new Set(d.resumen.comensales.filter((c) => c.pagado > 0).map((c) => c.dinerId))
}

type Modo = "iguales" | "unidades"
type Persona = { id?: string; name: string; conPago: boolean }

interface DividirCuentaProps {
  sessionId: string
  division: DivisionData
  onGuardado: (d: DivisionData) => void
  onCancelar?: () => void
}

const MAX = 20

/**
 * Arma o rehace el reparto de una cuenta: partes iguales (N personas, todo
 * compartido) o por unidad (cada línea se reparte con un contador por persona;
 * lo que nadie tomó se comparte). Guarda con `PUT /api/table-sessions/diners`.
 * Quien ya pagó queda bloqueado: no se quita ni se le mueven sus unidades.
 */
export function DividirCuenta({ sessionId, division, onGuardado, onCancelar }: DividirCuentaProps) {
  const pagaron = useMemo(() => comensalesQuePagaron(division), [division])
  const hayShares = division.items.some((i) => (i.shares?.length ?? 0) > 0)

  const [modo, setModo] = useState<Modo>(hayShares ? "unidades" : "iguales")
  const [personas, setPersonas] = useState<Persona[]>(() => {
    const base = division.diners.map((d) => ({ id: d.id, name: d.name, conPago: pagaron.has(d.id) }))
    return base.length > 0 ? base : [{ name: "", conPago: false }, { name: "", conPago: false }]
  })
  // shares[itemId][índice de persona] = unidades
  const [shares, setShares] = useState<Record<string, Record<number, number>>>(() => {
    const idx = new Map(division.diners.map((d, i) => [d.id, i]))
    const out: Record<string, Record<number, number>> = {}
    for (const item of division.items) {
      for (const s of item.shares ?? []) {
        const i = idx.get(s.dinerId)
        if (i === undefined) continue
        ;(out[item.id] ??= {})[i] = s.quantity
      }
    }
    return out
  })
  const [guardando, setGuardando] = useState(false)

  const asignadas = (itemId: string) => Object.values(shares[itemId] ?? {}).reduce((a, b) => a + b, 0)
  const sinAsignarTotal = division.items.reduce((acc, i) => acc + (i.quantity - asignadas(i.id)), 0)

  const fijarCantidad = (n: number) => {
    // Quien ya pagó va primero y no se toca; de los libres quedan los primeros
    // `n - fijas`. Las unidades se REMAPEAN por índice viejo → nuevo: antes
    // solo se truncaban y, con un pagado detrás de un libre, «2 cervezas de
    // Ana» aparecían en la fila de Luis.
    const fijas = personas.map((p, i) => i).filter((i) => personas[i].conPago)
    const libres = personas.map((p, i) => i).filter((i) => !personas[i].conPago)
    const faltan = Math.max(0, n - fijas.length)
    const ordenViejo = [...fijas, ...libres.slice(0, faltan)]
    const nuevas: Persona[] = ordenViejo.map((i) => personas[i])
    while (nuevas.length < fijas.length + faltan) nuevas.push({ name: "", conPago: false })
    const mapa = new Map(ordenViejo.map((viejo, nuevo) => [viejo, nuevo]))
    setPersonas(nuevas)
    // Las unidades de personas que ya no están vuelven a la mesa.
    setShares((prev) => {
      const out: Record<string, Record<number, number>> = {}
      for (const [itemId, porPersona] of Object.entries(prev)) {
        for (const [i, q] of Object.entries(porPersona)) {
          const nuevo = mapa.get(Number(i))
          if (nuevo !== undefined) (out[itemId] ??= {})[nuevo] = q
        }
      }
      return out
    })
  }

  const quitarPersona = (idx: number) => {
    if (personas[idx]?.conPago) return
    setPersonas((prev) => prev.filter((_, i) => i !== idx))
    setShares((prev) => {
      const out: Record<string, Record<number, number>> = {}
      for (const [itemId, porPersona] of Object.entries(prev)) {
        for (const [i, q] of Object.entries(porPersona)) {
          const n = Number(i)
          if (n === idx) continue
          ;(out[itemId] ??= {})[n > idx ? n - 1 : n] = q
        }
      }
      return out
    })
  }

  const cambiar = (itemId: string, idx: number, delta: number, max: number) => {
    setShares((prev) => {
      const porPersona = { ...(prev[itemId] ?? {}) }
      const actual = porPersona[idx] ?? 0
      const totalOtros = Object.entries(porPersona).reduce((a, [i, q]) => (Number(i) === idx ? a : a + q), 0)
      const nuevo = Math.max(0, Math.min(actual + delta, max - totalOtros))
      if (nuevo === 0) delete porPersona[idx]
      else porPersona[idx] = nuevo
      return { ...prev, [itemId]: porPersona }
    })
  }

  const guardar = async () => {
    setGuardando(true)
    try {
      const diners = personas.map((p, i) => ({ id: p.id, name: p.name.trim() || `Persona ${i + 1}` }))
      const partes =
        modo === "unidades"
          ? Object.entries(shares).flatMap(([itemId, porPersona]) =>
              Object.entries(porPersona)
                .filter(([, q]) => q > 0)
                .map(([i, q]) => ({ itemId, dinerIndex: Number(i), quantity: q }))
            )
          : []
      const res = await fetch("/api/table-sessions/diners", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ sessionId, diners, shares: partes }),
      })
      const data = await res.json().catch(() => ({}))
      if (!res.ok) throw new Error(data.error || "No se pudo guardar la división")
      toast({
        title: "Cuenta dividida",
        description:
          modo === "iguales"
            ? `Repartida en ${diners.length} partes iguales.`
            : `Repartida entre ${diners.length} personas. Lo que nadie tomó se divide entre todos.`,
      })
      onGuardado(data as DivisionData)
    } catch (e) {
      toast({
        title: "No se pudo guardar",
        description: e instanceof Error ? e.message : "Inténtalo de nuevo",
        variant: "destructive",
      })
    } finally {
      setGuardando(false)
    }
  }

  const nombreCorto = (p: Persona, i: number) => (p.name.trim() || `P${i + 1}`).slice(0, 8)

  return (
    <div className="space-y-4">
      <p className="text-sm text-muted-foreground">Reparte la cuenta y luego cóbrale a cada quien.</p>

      {/* Modo */}
      <div className="grid grid-cols-2 gap-2">
        {(
          [
            ["iguales", "Partes iguales"],
            ["unidades", "Por unidad"],
          ] as [Modo, string][]
        ).map(([m, rotulo]) => (
          <Button
            key={m}
            type="button"
            variant={modo === m ? "default" : "outline"}
            className={cn("h-10", modo === m && "bg-primary")}
            onClick={() => setModo(m)}
          >
            {rotulo}
          </Button>
        ))}
      </div>

      {/* Personas */}
      <div className="space-y-2">
        <div className="flex items-center justify-between">
          <span className="text-sm font-medium">Personas ({personas.length})</span>
          <div className="flex gap-1">
            {[2, 3, 4].map((n) => (
              <Button
                key={n}
                type="button"
                size="sm"
                variant={personas.length === n ? "default" : "outline"}
                className="h-8 w-9 px-0"
                onClick={() => fijarCantidad(n)}
              >
                {n}
              </Button>
            ))}
          </div>
        </div>
        {personas.map((p, i) => (
          <div key={p.id ?? `nueva-${i}`} className="flex items-center gap-2">
            <span className="w-6 text-center text-xs text-muted-foreground">{i + 1}</span>
            <Input
              value={p.name}
              placeholder={`Persona ${i + 1}`}
              maxLength={40}
              readOnly={p.conPago}
              onChange={(e) => setPersonas((prev) => prev.map((q, j) => (j === i ? { ...q, name: e.target.value } : q)))}
              className={cn("h-9", p.conPago && "bg-muted")}
            />
            {p.conPago ? (
              <span className="text-[11px] text-green-700 font-medium w-14 text-right">Ya pagó</span>
            ) : (
              <Button
                type="button"
                variant="ghost"
                size="icon"
                className="h-9 w-9 shrink-0"
                disabled={personas.length <= 1}
                onClick={() => quitarPersona(i)}
                aria-label="Quitar persona"
              >
                <X className="h-4 w-4" />
              </Button>
            )}
          </div>
        ))}
        <Button
          type="button"
          variant="outline"
          size="sm"
          className="w-full"
          disabled={personas.length >= MAX}
          onClick={() => setPersonas((prev) => [...prev, { name: "", conPago: false }])}
        >
          <UserPlus className="h-4 w-4 mr-2" />
          Agregar persona
        </Button>
      </div>

      {modo === "iguales" ? (
        <p className="text-xs text-muted-foreground bg-muted/50 rounded-md p-3">
          El servidor reparte el total en partes iguales entre las {personas.length} personas; los centavos
          sobrantes van a la primera. Lo que ya se haya pagado se descuenta.
        </p>
      ) : (
        <div className="space-y-2">
          <div
            className={cn(
              "text-xs rounded-md px-3 py-2 font-medium",
              sinAsignarTotal > 0 ? "bg-amber-100 text-amber-900" : "bg-green-100 text-green-900"
            )}
          >
            {sinAsignarTotal > 0
              ? `Sin asignar: ${sinAsignarTotal} ${sinAsignarTotal === 1 ? "unidad" : "unidades"} · se reparten entre todos`
              : "Todo asignado"}
          </div>
          {division.items.map((item) => {
            const libres = item.quantity - asignadas(item.id)
            return (
              <div key={item.id} className="border rounded-md p-2 space-y-2">
                <div className="flex justify-between gap-2 text-sm">
                  <span className="font-medium truncate min-w-0">
                    {item.quantity}x {item.name}
                  </span>
                  <span className="text-muted-foreground shrink-0">
                    {libres > 0 ? `${libres} libre${libres === 1 ? "" : "s"}` : "✓"}
                  </span>
                </div>
                <div className="flex flex-wrap gap-1.5">
                  {personas.map((p, i) => {
                    const q = shares[item.id]?.[i] ?? 0
                    return (
                      <div key={p.id ?? `nueva-${i}`} className="flex items-center rounded-md border bg-background">
                        <span className="px-2 text-xs truncate max-w-16">{nombreCorto(p, i)}</span>
                        <Button
                          type="button"
                          variant="ghost"
                          size="icon"
                          className="h-8 w-8"
                          disabled={p.conPago || q === 0}
                          onClick={() => cambiar(item.id, i, -1, item.quantity)}
                          aria-label={`Quitar una unidad a ${nombreCorto(p, i)}`}
                        >
                          <Minus className="h-3 w-3" />
                        </Button>
                        <span className={cn("w-5 text-center text-sm font-bold", q > 0 && "text-primary")}>{q}</span>
                        <Button
                          type="button"
                          variant="ghost"
                          size="icon"
                          className="h-8 w-8"
                          disabled={p.conPago || libres === 0}
                          onClick={() => cambiar(item.id, i, +1, item.quantity)}
                          aria-label={`Dar una unidad a ${nombreCorto(p, i)}`}
                        >
                          <Plus className="h-3 w-3" />
                        </Button>
                      </div>
                    )
                  })}
                </div>
              </div>
            )
          })}
        </div>
      )}

      <div className="flex gap-2 pt-1">
        {onCancelar && (
          <Button type="button" variant="outline" className="flex-1" onClick={onCancelar} disabled={guardando}>
            Volver
          </Button>
        )}
        <Button type="button" className="flex-1 bg-primary" onClick={guardar} disabled={guardando || personas.length === 0}>
          {guardando ? <Loader2 className="h-4 w-4 animate-spin mr-2" /> : null}
          Guardar reparto
        </Button>
      </div>
    </div>
  )
}
