import { useEffect, useRef, useState } from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import {
  ESTADO_META,
  ESTADO_PAGO_META,
  siguientesEstados,
  formatUsd,
  bsDesdeUsd,
  formatBs,
  enlaceWhatsApp,
  type Pedido,
  type PedidoItem,
  type Pago,
  type EstadoPedido,
} from '@gustito/shared';
import { supabase } from '../lib/supabase';
import { useAuth } from '../lib/auth';
import { useCambiosRestaurante } from '../lib/tiemporeal';
import { useTraidaAgrupada } from '../lib/agrupador';
import { Icono } from '@gustito/shared/iconos';
import { parsearOpciones } from '../lib/opciones';
import EscanearQR from './EscanearQR';
import DisponibilidadRapida from './DisponibilidadRapida';
import { useFacturaActiva } from '../components/DatosFactura';

type PedidoCompleto = Pedido & { pedido_items: PedidoItem[]; pagos: Pago[]; cuenta_id: string | null };

// Pago de mesa: vive en la cuenta de la mesa, no en un `pago` del pedido. Se cruza
// por cuenta_id para mostrar la referencia y el comprobante dentro de la orden.
// metodo_pago/referencia de cuentas_mesa son solo la INTENCION que declaro el
// cliente al pedir la cuenta (pedir_cuenta_mesa); si el mesero cobra directo
// desde el panel esos campos quedan vacios. Los cobros REALES (uno o varios,
// si se cobro por partes con metodos distintos) viven en pagos_mesa.
type PagoMesaEmbed = {
  metodo: string;
  referencia: string | null;
  comprobante_url: string | null;
  verificado: boolean;
  monto_usd: number;
};
type CuentaMesa = {
  id: string;
  estado: string;
  metodo_pago: string | null;
  referencia: string | null;
  comprobante_url: string | null;
  pagos_mesa: PagoMesaEmbed[];
};
const METODO_MESA: Record<string, string> = {
  pago_movil: 'Pago Móvil',
  efectivo: 'Efectivo',
  transferencia: 'Transferencia',
  zelle: 'Zelle',
  punto_venta: 'Punto de venta',
  perdida: 'Pérdida (no cobrado)',
};
const esPagoOnlineMesa = (m: string | null) => m === 'pago_movil' || m === 'zelle' || m === 'transferencia';

function beep() {
  try {
    const ctx = new AudioContext();
    const o = ctx.createOscillator();
    o.frequency.value = 880;
    o.connect(ctx.destination);
    o.start();
    setTimeout(() => {
      o.stop();
      ctx.close();
    }, 220);
  } catch {
    /* sin audio disponible */
  }
}

export default function Pedidos({
  restauranteId,
  restauranteNombre,
  marca,
  txtMarca,
  acento,
}: {
  restauranteId: string;
  restauranteNombre: string;
  marca: string;
  txtMarca: string;
  acento: string;
}) {
  const qc = useQueryClient();
  const { perfil } = useAuth();
  const esStaff = perfil?.rol === 'staff';
  // La anulacion de una factura se PIDE desde aqui, pero la nota de credito la
  // emite la Estacion Fiscal: Gustito solo manda la solicitud por la cola.
  // Dueño y encargado pueden pedirla (decidido 2026-07-29); el mesero no.
  const facturaActiva = useFacturaActiva(restauranteId);
  const puedeAnularFactura = !esStaff && facturaActiva;
  const [ncPedido, setNcPedido] = useState<{ id: string; codigo: string } | null>(null);
  const [ncMotivo, setNcMotivo] = useState('');
  const [ncSalida, setNcSalida] = useState<{ ok: boolean; texto: string } | null>(null);
  const [ncEnviando, setNcEnviando] = useState(false);
  const [escanear, setEscanear] = useState(false);
  const [agotar, setAgotar] = useState(false);
  const [filtro, setFiltro] = useState<'activos' | 'entregados' | 'cancelados' | 'todos'>('activos');
  const [tiempos, setTiempos] = useState<Record<string, string>>({});
  const [busqueda, setBusqueda] = useState('');
  const [busquedaDeb, setBusquedaDeb] = useState('');
  useEffect(() => {
    const id = setTimeout(() => setBusquedaDeb(busqueda.trim()), 300);
    return () => clearTimeout(id);
  }, [busqueda]);
  const buscando = busquedaDeb.length >= 2;

  const pedidosQ = useQuery({
    queryKey: ['pedidos', restauranteId, busquedaDeb, esStaff ? perfil?.id : 'all'],
    queryFn: async () => {
      let query = supabase.from('pedidos').select('*, pedido_items(*), pagos(*)').eq('restaurante_id', restauranteId);
      // El mesero ve solo lo que él tomó; el dueño ve todo.
      if (esStaff && perfil?.id) query = query.eq('mesero_id', perfil.id);
      if (busquedaDeb.length >= 2) {
        // Busca en historial completo (no solo los 50 recientes) por codigo/nombre/telefono.
        const t = busquedaDeb.replace(/[%,()]/g, ' ');
        query = query.or(`codigo.ilike.%${t}%,cliente_nombre.ilike.%${t}%,cliente_telefono.ilike.%${t}%`);
      }
      const { data, error } = await query.order('recibido_en', { ascending: false }).limit(50);
      if (error) throw error;
      return (data ?? []) as unknown as PedidoCompleto[];
    },
  });

  // Cuentas de mesa (para mostrar el pago de la mesa dentro de la orden). OJO:
  // mis_cuentas_mesa (la RPC del panel de Mesas) solo trae cuentas ACTIVAS, asi
  // que una mesa ya cobrada y cerrada desaparecia de aqui y esta seccion nunca
  // mostraba el metodo/referencia real. Trae directo por cuenta_id (activas Y
  // cerradas) de los pedidos visibles; RLS sigue aislando por mesero igual.
  // Misma clave de cache que Mesas/AlertaPagosMesa: se refresca en tiempo real con ellas.
  // Se ordenan para que la clave sea la misma aunque los pedidos vengan en otro
  // orden: si no, cada reacomodo se veria como una consulta distinta.
  const cuentaIds = [...new Set((pedidosQ.data ?? []).map((p) => p.cuenta_id).filter((id): id is string => !!id))].sort();
  const cuentasQ = useQuery({
    // OJO con esta clave. Antes era exactamente ['cuentas-mesa', restauranteId],
    // la MISMA de Mesas y del aviso de pagos, pero esas dos piden otra cosa
    // (la RPC mis_cuentas_mesa) y esta pide por lista de ids. Al compartir clave,
    // el reloj de una disparaba la consulta de la otra, y esta salia con la
    // lista vacia: una peticion `id=in.()` preguntando por nada, en bucle.
    // Ahora lleva tramos propios al final, asi que es su propia entrada de
    // cache; y como el prefijo sigue siendo ['cuentas-mesa', restauranteId], las
    // invalidaciones de Mesas y de los avisos la siguen alcanzando, que era lo
    // que se buscaba al compartirla.
    queryKey: ['cuentas-mesa', restauranteId, 'de-pedidos', cuentaIds.join(',')],
    enabled: cuentaIds.length > 0,
    queryFn: async () => {
      // Cinturon: aunque algo la dispare sin ids, no sale una consulta vacia.
      if (cuentaIds.length === 0) return [];
      const { data, error } = await supabase
        .from('cuentas_mesa')
        .select('id,estado,metodo_pago,referencia,comprobante_url,pagos_mesa(metodo,referencia,comprobante_url,verificado,monto_usd)')
        .in('id', cuentaIds);
      if (error) throw error;
      return (data as unknown as CuentaMesa[]) ?? [];
    },
    refetchInterval: 15000,
  });

  const repartidoresQ = useQuery({
    queryKey: ['repartidores', restauranteId],
    queryFn: async () => {
      // mis_repartidores trae el NOMBRE (de perfiles), para distinguir a quien asignar.
      const { data, error } = await supabase.rpc('mis_repartidores');
      if (error) throw error;
      return (data as unknown as {
        repartidor_id: string;
        nombre: string | null;
        vehiculo: string | null;
        estado: string;
      }[]) ?? [];
    },
  });

  // Pedidos que ya avisamos como "listos" para no repetir el sonido.
  const listoRef = useRef<Set<string>>(new Set());

  /**
   * Mete los pedidos que llegaron en TODAS las listas que haya guardadas.
   *
   * OJO, aqui habia un hueco viejo: el empalme escribia a mano en la clave
   * ['pedidos', id, ''], de tres tramos, pero la lista pasa a guardarse con
   * CUATRO desde que la clave gano a quien pertenece (el mesero ve lo suyo, el
   * dueño ve todo). Desde entonces se escribia en una gaveta que no existe y la
   * pantalla no se enteraba de nada hasta que alguien recargara. Ahora se
   * recorren las listas que de verdad estan guardadas.
   */
  function empalmar(filas: PedidoCompleto[]) {
    if (filas.length === 0) return;
    const nuevos = new Map(filas.map((f) => [f.id, f]));
    for (const guardada of qc.getQueryCache().findAll({ queryKey: ['pedidos', restauranteId] })) {
      const busqueda = String(guardada.queryKey[2] ?? '');
      qc.setQueryData<PedidoCompleto[]>(guardada.queryKey, (prev) => {
        if (!prev) return prev;
        // Con una busqueda escrita solo se refresca lo que ya salia en ella:
        // colar un pedido nuevo mostraria algo que no cumple lo buscado.
        if (busqueda) {
          if (!prev.some((p) => nuevos.has(p.id))) return prev;
          return prev.map((p) => nuevos.get(p.id) ?? p);
        }
        const otros = prev.filter((p) => !nuevos.has(p.id));
        return [...nuevos.values(), ...otros]
          .sort((a, b) => new Date(b.recibido_en).getTime() - new Date(a.recibido_en).getTime())
          .slice(0, 50);
      });
    }
  }

  /** Saca un pedido borrado de todas las listas guardadas. */
  function quitarDeLasListas(id: string) {
    for (const guardada of qc.getQueryCache().findAll({ queryKey: ['pedidos', restauranteId] })) {
      qc.setQueryData<PedidoCompleto[]>(guardada.queryKey, (prev) =>
        prev ? prev.filter((p) => p.id !== id) : prev,
      );
    }
  }

  // Los pedidos que cambiaron se traen JUNTOS, no de uno en uno: una rafaga de
  // avisos era una rafaga de consultas, y con eso el navegador se quedaba sin
  // recursos y se congelaba la pantalla. Ver lib/agrupador.ts.
  const traerPedidos = useTraidaAgrupada<PedidoCompleto>(
    async (ids) => {
      const { data } = await supabase
        .from('pedidos')
        .select('*, pedido_items(*), pagos(*)')
        .in('id', ids);
      return (data as unknown as PedidoCompleto[]) ?? [];
    },
    (filas) => empalmar(filas),
  );

  useCambiosRestaurante(restauranteId, {
    onCambio: async (c) => {
      if (c.tabla !== 'pedidos') return;
      // El beep de "pedido nuevo" ahora es global (en el Panel, suena en cualquier
      // pestaña). Aqui solo avisamos cuando la cocina marca un pedido "listo".
      if (c.nuevo?.estado === 'listo' && !listoRef.current.has(c.id)) {
        // La cocina lo marco listo: avisar al encargado (doble beep para distinguir).
        listoRef.current.add(c.id);
        beep();
        setTimeout(beep, 320);
      }
      if (c.nuevo?.estado && c.nuevo.estado !== 'listo') listoRef.current.delete(c.id);

      // En vez de rebajar los 50 pedidos con sus items y pagos en CADA evento, traemos
      // SOLO los pedidos que cambiaron y los empalmamos en la vista principal (sin
      // busqueda). Aparecen igual de instantaneos, pero se mueve lo justo y, si
      // llegan varios avisos de golpe, salen todos en UNA consulta.
      if (c.accion === 'DELETE') {
        quitarDeLasListas(c.id);
        return;
      }
      traerPedidos(c.id);
    },
    // Volvio la conexion: la reconstruccion fila-por-fila pudo perderse cambios
    // durante la caida, asi que refrescamos la lista completa una vez.
    onResync: () => qc.invalidateQueries({ queryKey: ['pedidos', restauranteId] }),
  });

  async function cambiarEstado(pedidoId: string, nuevo: EstadoPedido) {
    if (nuevo === 'cancelado' && !confirm('Seguro que quieres CANCELAR este pedido? No se puede deshacer.')) return;
    const { error } = await supabase.rpc('cambiar_estado_pedido', {
      p_pedido_id: pedidoId,
      p_nuevo_estado: nuevo,
    });
    if (error) alert(error.message);
    else qc.invalidateQueries({ queryKey: ['pedidos', restauranteId] });
  }

  async function quitarItem(itemId: string) {
    if (!confirm('¿Quitar este renglón del pedido? Se recalcula el total.')) return;
    const { error } = await supabase.rpc('quitar_item_pedido', { p_item_id: itemId });
    if (error) alert(error.message);
    else qc.invalidateQueries({ queryKey: ['pedidos', restauranteId] });
  }

  async function aceptar(pedidoId: string, minStr: string) {
    const min = parseInt(minStr, 10);
    if (Number.isNaN(min) || min <= 0) {
      alert('Pon el tiempo estimado en minutos (ej. 20)');
      return;
    }
    const { error } = await supabase.rpc('aceptar_pedido', { p_pedido_id: pedidoId, p_min: min });
    if (error) alert(error.message);
    else qc.invalidateQueries({ queryKey: ['pedidos', restauranteId] });
  }

  async function confirmarPago(pagoId: string, estado: 'confirmado' | 'rechazado') {
    if (estado === 'rechazado' && !confirm('Rechazar el pago de este pedido? El cliente vera que su pago fue rechazado.'))
      return;
    const { error } = await supabase.rpc('confirmar_pago', { p_pago_id: pagoId, p_estado: estado });
    if (error) alert(error.message);
    else qc.invalidateQueries({ queryKey: ['pedidos', restauranteId] });
  }

  async function asignar(pedidoId: string, repartidorId: string) {
    if (!repartidorId) return;
    const { error } = await supabase.rpc('asignar_repartidor', {
      p_pedido_id: pedidoId,
      p_repartidor_id: repartidorId,
    });
    if (error) alert(error.message);
    else qc.invalidateQueries({ queryKey: ['pedidos', restauranteId] });
  }

  async function verComprobante(path: string) {
    const { data, error } = await supabase.storage.from('comprobantes').createSignedUrl(path, 120);
    if (error) alert(error.message);
    else window.open(data.signedUrl, '_blank');
  }

  async function pedirNotaCredito() {
    if (!ncPedido || ncEnviando) return;
    const motivo = ncMotivo.trim();
    if (!motivo) {
      setNcSalida({ ok: false, texto: 'Escribe el motivo: queda escrito en el documento.' });
      return;
    }
    setNcEnviando(true);
    const { data, error } = await supabase.rpc('anular_venta_fiscal', {
      p_restaurante: restauranteId,
      p_tipo: 'pedido',
      p_origen_id: ncPedido.id,
      p_motivo: motivo,
    });
    setNcEnviando(false);
    if (error) {
      setNcSalida({ ok: false, texto: error.message });
      return;
    }
    const r = data as unknown as { ok?: boolean; accion?: string; motivo?: string };
    if (r?.ok) {
      setNcSalida({
        ok: true,
        texto:
          r.accion === 'ya_solicitada'
            ? 'Esta venta ya tiene su solicitud de anulación en camino.'
            : r.accion === 'descartada'
              ? 'Esta venta se descartó antes de facturarse: no hay documento que anular.'
              : 'Listo. La solicitud viaja a la Estación Fiscal y la nota de crédito sale en el próximo enlace.',
      });
    } else {
      setNcSalida({
        ok: false,
        texto:
          r?.motivo === 'sin_sellar'
            ? 'La factura de esta venta todavía no ha sido emitida. Intenta en unos minutos.'
            : r?.motivo === 'sin_documento'
              ? 'Esta venta no entró al circuito de facturación.'
              : 'La facturación no está habilitada para este negocio.',
      });
    }
  }

  const pedidos = pedidosQ.data ?? [];
  const repartidores = repartidoresQ.data ?? [];
  const cuentaPorId = new Map((cuentasQ.data ?? []).map((c) => [c.id, c]));
  const nombreRep = (id: string | null | undefined) =>
    repartidores.find((r) => r.repartidor_id === id)?.nombre ?? 'Repartidor';

  const activos = pedidos.filter((p) => p.estado !== 'entregado' && p.estado !== 'cancelado');
  // Al buscar mostramos todas las coincidencias (ignora el filtro de estado).
  const pedidosFiltrados = buscando
    ? pedidos
    : filtro === 'todos'
      ? pedidos
      : filtro === 'activos'
        ? activos
        : filtro === 'entregados'
          ? pedidos.filter((p) => p.estado === 'entregado')
          : pedidos.filter((p) => p.estado === 'cancelado');

  const filtros: [typeof filtro, string][] = [
    ['activos', `Activos${activos.length ? ` (${activos.length})` : ''}`],
    ['entregados', 'Entregados'],
    ['cancelados', 'Cancelados'],
    ['todos', 'Todos'],
  ];

  return (
    <div className="space-y-3">
      <div className="flex flex-wrap justify-end gap-2">
        <button onClick={() => setAgotar(true)} className="btn bg-white/10 text-white ring-1 ring-white/15">
          Agotados
        </button>
        <button onClick={() => setEscanear(true)} className="btn bg-white/10 text-white ring-1 ring-white/15">
          Escanear ticket
        </button>
      </div>

      {/* Buscador (busca en todo el historial por código, nombre o teléfono) */}
      <div className="relative">
        <Icono nombre="buscar" className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-white/70" />
        <input
          className="w-full rounded-xl border border-white/15 bg-superficie-2 py-2.5 pl-9 pr-9 text-sm font-medium text-white placeholder:text-white/45 outline-none focus:border-white/35"
          placeholder="Buscar por código, nombre o teléfono"
          value={busqueda}
          onChange={(e) => setBusqueda(e.target.value)}
        />
        {busqueda && (
          <button
            onClick={() => setBusqueda('')}
            className="absolute right-2 top-1/2 -translate-y-1/2 rounded-full px-2 py-0.5 text-lg leading-none text-white/70 hover:bg-white/10"
            aria-label="Limpiar"
          >
            ×
          </button>
        )}
      </div>

      {buscando ? (
        <p className="text-xs text-white/70">
          Resultados para "<b className="text-white">{busquedaDeb}</b>" · {pedidos.length}
          {pedidos.length === 50 ? '+' : ''} pedido{pedidos.length === 1 ? '' : 's'}
        </p>
      ) : (
        <div className="no-scrollbar flex gap-1.5 overflow-x-auto">
          {filtros.map(([f, label]) => (
          <button
            key={f}
            onClick={() => setFiltro(f)}
            className={`shrink-0 whitespace-nowrap rounded-full px-3.5 py-1.5 text-sm font-semibold transition ${
              filtro === f ? '' : 'bg-white/10 text-white/85 hover:bg-white/15'
            }`}
            style={filtro === f ? { background: marca, color: txtMarca } : undefined}
          >
            {label}
          </button>
          ))}
        </div>
      )}
      {escanear && <EscanearQR restauranteId={restauranteId} onCerrar={() => setEscanear(false)} />}
      {agotar && <DisponibilidadRapida restauranteId={restauranteId} onCerrar={() => setAgotar(false)} />}
      {ncPedido && (
        <div
          className="fixed inset-0 z-[70] flex items-center justify-center bg-black/70 p-4"
          onClick={() => !ncEnviando && setNcPedido(null)}
        >
          <div
            className="w-full max-w-sm rounded-2xl bg-superficie p-5 text-white ring-1 ring-white/15"
            onClick={(e) => e.stopPropagation()}
          >
            <p className="text-lg font-extrabold">Anular la factura del pedido {ncPedido.codigo}</p>
            {ncSalida?.ok ? (
              <>
                <p className="mt-2 rounded-xl bg-green-500/10 px-3 py-2.5 text-sm font-semibold text-green-400">
                  {ncSalida.texto}
                </p>
                <button
                  onClick={() => setNcPedido(null)}
                  className="mt-4 w-full rounded-xl py-2.5 text-sm font-extrabold shadow-lg"
                  style={{ background: marca, color: txtMarca }}
                >
                  Entendido
                </button>
              </>
            ) : (
              <>
                <p className="mt-1.5 text-sm text-white/70">
                  La venta no se borra: la Estación Fiscal emite una nota de crédito que la corrige, y las dos
                  quedan en el libro. Escribe el motivo, que queda en el documento.
                </p>
                <textarea
                  className="mt-3 w-full rounded-xl border border-white/15 bg-superficie-2 px-3 py-2.5 text-sm font-medium outline-none placeholder:text-white/45 focus:border-white/35"
                  rows={2}
                  placeholder="Ej. el cliente devolvió el pedido"
                  value={ncMotivo}
                  onChange={(e) => setNcMotivo(e.target.value)}
                />
                {ncSalida && (
                  <p className="mt-2 rounded-xl bg-red-500/10 px-3 py-2 text-sm font-semibold text-red-400">
                    {ncSalida.texto}
                  </p>
                )}
                <div className="mt-4 flex gap-2">
                  <button
                    onClick={() => setNcPedido(null)}
                    disabled={ncEnviando}
                    className="flex-1 rounded-xl border border-white/15 py-2.5 text-sm font-bold text-white/85 hover:bg-white/10"
                  >
                    Volver
                  </button>
                  <button
                    onClick={() => void pedirNotaCredito()}
                    disabled={ncEnviando}
                    className="flex-1 rounded-xl py-2.5 text-sm font-extrabold shadow-lg disabled:opacity-75"
                    style={{ background: marca, color: txtMarca }}
                  >
                    {ncEnviando ? 'Enviando...' : 'Sí, pedir la nota'}
                  </button>
                </div>
              </>
            )}
          </div>
        </div>
      )}
      {pedidosQ.isLoading && <p className="text-white/70">Cargando pedidos...</p>}
      {pedidosQ.error && <p className="text-red-600">{(pedidosQ.error as Error).message}</p>}
      {!pedidosQ.isLoading && pedidosFiltrados.length === 0 && (
        <div className="rounded-2xl border border-dashed border-white/15 bg-superficie py-12 text-center">
          <Icono nombre="recibo" className="mx-auto h-10 w-10 text-white/30" />
          <p className="mt-2 font-bold text-white">
            {buscando ? 'Sin resultados' : pedidos.length === 0 ? 'Aún no hay pedidos' : 'Nada en este filtro'}
          </p>
          <p className="mt-1 text-sm text-white/70">
            {buscando
              ? `No hay pedidos que coincidan con "${busquedaDeb}".`
              : pedidos.length === 0
                ? 'Suena una alerta apenas entre un pedido nuevo.'
                : 'Prueba con otro filtro de arriba.'}
          </p>
        </div>
      )}
      {pedidosFiltrados.map((p) => {
        const pago = p.pagos?.[0];
        const editable = p.estado !== 'entregado' && p.estado !== 'cancelado';
        const min = Math.max(0, Math.floor((Date.now() - new Date(p.recibido_en).getTime()) / 60000));
        const itemsWa = (p.pedido_items ?? [])
          .map((it) => `• ${it.cantidad}x ${it.nombre}${it.nota ? ` (${it.nota})` : ''}`)
          .join('\n');
        const entregaWa =
          p.tipo_entrega === 'mesa'
            ? `Mesa ${p.mesa ?? ''}`.trim()
            : p.tipo_entrega === 'delivery'
              ? `Delivery${p.direccion ? ` · ${p.direccion}` : ''}`
              : p.tipo_entrega === 'reserva'
                ? `Reserva de mesa · ${p.personas ?? 1} persona${(p.personas ?? 1) === 1 ? '' : 's'}`
                : 'Para llevar';
        const wa = enlaceWhatsApp(
          p.cliente_telefono,
          `*${restauranteNombre}*\n\n` +
            `Hola ${p.cliente_nombre}! Le escribimos por su pedido ${p.codigo}:\n\n` +
            (itemsWa ? itemsWa + '\n\n' : '') +
            `Total: ${formatUsd(p.total_usd)}\n${entregaWa}`,
        );
        const tipoTxt =
          p.tipo_entrega === 'delivery'
            ? `Delivery${p.costo_delivery_usd === 0 ? ' gratis' : ''}${p.direccion ? ' · ' + p.direccion : ''}`
            : p.tipo_entrega === 'mesa'
              ? `Mesa ${p.mesa ?? ''}`.trim()
              : p.tipo_entrega === 'reserva'
                ? p.cuenta_id
                  ? `Reserva sentada · Mesa ${p.mesa ?? ''}`.trim()
                  : `Reserva de mesa · ${p.personas ?? 1} persona${(p.personas ?? 1) === 1 ? '' : 's'}`
                : 'Para retirar';
        return (
          <article
            key={p.id}
            className={`overflow-hidden rounded-2xl bg-superficie shadow-sm ${
              p.estado === 'listo' ? 'border-2 border-sky-400/60 ring-2 ring-sky-500/20' : 'border border-white/15'
            }`}
          >
            {/* Franja de estado */}
            <div className="h-1.5 w-full" style={{ backgroundColor: ESTADO_META[p.estado].color }} />

            {/* Cabecera */}
            <div className="flex items-start justify-between gap-3 p-4">
              <div className="min-w-0">
                <div className="flex flex-wrap items-center gap-2">
                  <p className="text-lg font-extrabold text-white">{p.codigo}</p>
                  {p.para_llevar && (
                    <span className="rounded-full bg-amber-400/20 px-2 py-0.5 text-[11px] font-black text-amber-300 ring-1 ring-amber-400/40">
                      PARA LLEVAR
                    </span>
                  )}
                  <span className="rounded-full bg-white/10 px-2 py-0.5 text-[11px] font-semibold text-white/70">
                    hace {min} min
                  </span>
                </div>
                <p className="mt-0.5 truncate text-sm font-medium text-white">{p.cliente_nombre}</p>
                <p className="truncate text-xs text-white/70">
                  {tipoTxt}
                  {p.mesero_nombre ? ` · Atiende ${p.mesero_nombre}` : ''}
                </p>
              </div>
              <span
                className="shrink-0 rounded-full px-2.5 py-1 text-xs font-bold text-white"
                style={{ backgroundColor: ESTADO_META[p.estado].color }}
              >
                {ESTADO_META[p.estado].label}
              </span>
            </div>

            <div className="px-4 pb-4">
              {p.estado === 'listo' && (
                <div className="mb-3 flex items-center gap-2 rounded-xl bg-sky-500/10 px-3 py-2 text-sm font-bold text-sky-300 ring-1 ring-sky-500/30">
                  🔔 La cocina lo marcó listo:{' '}
                  {p.tipo_entrega === 'delivery'
                    ? p.repartidor_id
                      ? `entrégaselo a ${nombreRep(p.repartidor_id)}`
                      : 'asignar repartidor'
                    : p.tipo_entrega === 'mesa'
                      ? `servir en Mesa ${p.mesa ?? ''}`.trim()
                      : 'el cliente lo retira'}
                </div>
              )}
              {/* Contacto con el cliente */}
              {p.cliente_telefono && (
                <div className="mb-3 flex flex-wrap gap-2">
                  {wa && (
                    <a
                      href={wa}
                      target="_blank"
                      rel="noopener noreferrer"
                      className="inline-flex items-center gap-1.5 rounded-lg bg-[#25D366] px-3 py-1.5 text-xs font-bold text-white"
                    >
                      <svg viewBox="0 0 24 24" fill="currentColor" className="h-3.5 w-3.5" aria-hidden>
                        <path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51l-.57-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.71.306 1.263.489 1.694.626.712.226 1.36.194 1.872.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347M12.05 21.785h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884" />
                      </svg>
                      WhatsApp
                    </a>
                  )}
                  <a
                    href={`tel:${p.cliente_telefono}`}
                    className="inline-flex items-center rounded-lg border border-white/20 px-3 py-1.5 text-xs font-bold text-white/85"
                  >
                    Llamar
                  </a>
                </div>
              )}

              {/* Items — el detalle de lo que pidio el cliente, legible por grupo */}
              <ul className="space-y-3 border-y border-white/10 py-3">
                {p.pedido_items?.map((it) => {
                  const { grupos, libre } = parsearOpciones(it.nota);
                  return (
                    <li key={it.id} className="text-sm text-white">
                      <div className="flex items-start justify-between gap-2">
                        <div className="flex min-w-0 items-start gap-2">
                          <span
                            className="mt-px shrink-0 rounded-md px-1.5 py-0.5 text-xs font-black tabular-nums"
                            style={{ background: acento + '22', color: acento }}
                          >
                            {it.cantidad}×
                          </span>
                          <span className="min-w-0 font-semibold">{it.nombre}</span>
                        </div>
                        <span className="flex shrink-0 items-center gap-2">
                          <span className="font-bold tabular-nums text-white/85">{formatUsd(it.precio_usd * it.cantidad)}</span>
                          {editable && (
                            <button
                              onClick={() => quitarItem(it.id)}
                              className="text-red-400/70 hover:text-red-400"
                              title="Quitar este renglón"
                              aria-label="Quitar renglón"
                            >
                              <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                                <path d="M3 6h18M8 6V4h8v2M6 6l1 14h10l1-14M10 11v6M14 11v6" />
                              </svg>
                            </button>
                          )}
                        </span>
                      </div>
                      {(grupos.length > 0 || libre.length > 0) && (
                        <div className="ml-8 mt-1.5 space-y-1 border-l-2 pl-3" style={{ borderColor: acento }}>
                          {grupos.map((g, i) => (
                            <p key={i} className="text-xs leading-snug">
                              <span className="text-white/70">{g.label}: </span>
                              <span className="font-semibold text-white">{g.val}</span>
                            </p>
                          ))}
                          {libre.map((l, i) => (
                            <p key={i} className="text-xs font-bold text-amber-300">
                              Nota: {l}
                            </p>
                          ))}
                        </div>
                      )}
                    </li>
                  );
                })}
              </ul>
              {p.nota && (
                <p className="mt-2 rounded-lg bg-amber-500/10 px-3 py-2 text-xs font-semibold text-amber-200 ring-1 ring-amber-500/30">
                  Nota del pedido: {p.nota}
                </p>
              )}

              {/* Total + estado del pago */}
              <div className="mt-3 flex items-center justify-between gap-2 text-sm">
                <span className="text-base font-extrabold text-white">
                  Total {formatUsd(p.total_usd)}
                  {p.tasa_bs != null && p.tasa_bs > 0 && (
                    <span className="ml-1.5 text-xs font-semibold text-white/70">· {formatBs(bsDesdeUsd(p.total_usd, p.tasa_bs))}</span>
                  )}
                </span>
                {pago && (
                  <span
                    className="shrink-0 rounded-full px-2 py-0.5 text-xs font-bold text-white"
                    style={{ backgroundColor: ESTADO_PAGO_META[pago.estado].color }}
                  >
                    {METODO_MESA[p.metodo_pago] ?? p.metodo_pago} · {ESTADO_PAGO_META[pago.estado].label}
                    {pago.referencia && ` · Ref ${pago.referencia}`}
                  </span>
                )}
              </div>

              {/* Pago de la mesa: no hay `pago` del pedido, vive en la cuenta de la mesa.
                  Los cobros REALES (pagos_mesa) mandan sobre metodo_pago/referencia de
                  cuentas_mesa, que es solo la intencion que declaro el cliente al pedir
                  la cuenta: si el mesero cobro directo desde el panel (o cobro por partes
                  con metodos distintos), esos campos pueden quedar vacios o incompletos. */}
              {p.tipo_entrega === 'mesa' && p.cuenta_id && (() => {
                const cta = cuentaPorId.get(p.cuenta_id);
                if (!cta) return null;
                const pagosReales = cta.pagos_mesa ?? [];
                // "Abierta" sin pago solicitado ni cobrado aun: no hay nada que mostrar.
                if (!pagosReales.length && cta.estado === 'abierta' && !cta.referencia && !cta.comprobante_url) return null;
                const online = esPagoOnlineMesa(cta.metodo_pago);
                const cerrada = cta.estado === 'cerrada';
                return (
                  <div className={`mt-3 rounded-xl p-3 ring-1 ${cerrada ? 'bg-green-500/10 ring-green-500/30' : 'bg-amber-500/10 ring-amber-500/30'}`}>
                    <p className={`text-sm font-bold ${cerrada ? 'text-green-300' : 'text-amber-200'}`}>
                      Pago de la Mesa {p.mesa}
                      {cerrada && !pagosReales.length ? ' · cobrada' : ''}
                    </p>
                    {pagosReales.length > 0 ? (
                      <div className="mt-1.5 space-y-1.5">
                        {pagosReales.map((pg, i) => {
                          const esPerdida = pg.metodo === 'perdida';
                          return (
                            <p key={i} className="text-xs leading-relaxed text-white/80">
                              <span className={esPerdida ? 'font-bold text-red-400' : 'font-bold text-white'}>
                                {METODO_MESA[pg.metodo] ?? pg.metodo}
                              </span>{' '}
                              · {formatUsd(pg.monto_usd)}
                              {!pg.verificado && <span className="ml-1 font-bold text-amber-300">(por revisar)</span>}
                              {pg.referencia && (
                                <span>
                                  {' '}
                                  · Ref <b className="text-white">{pg.referencia}</b>
                                </span>
                              )}
                              {pg.comprobante_url && (
                                <button
                                  onClick={() => verComprobante(pg.comprobante_url!)}
                                  className="ml-1 font-bold text-dorado underline"
                                >
                                  Ver comprobante
                                </button>
                              )}
                            </p>
                          );
                        })}
                      </div>
                    ) : (
                      <>
                        <p className="mt-0.5 text-xs text-white/70">
                          {cta.estado === 'por_pagar'
                            ? online
                              ? 'El cliente marcó que pagó. Verifícalo.'
                              : 'El cliente pidió la cuenta.'
                            : 'Cuenta de la mesa'}
                          {cta.metodo_pago ? ` · ${METODO_MESA[cta.metodo_pago] ?? cta.metodo_pago}` : ''}
                        </p>
                        {(cta.referencia || cta.comprobante_url) && (
                          <div className="mt-2 flex flex-wrap items-center gap-3 text-xs text-white/70">
                            {cta.referencia && (
                              <span>
                                Ref: <b className="text-white">{cta.referencia}</b>
                              </span>
                            )}
                            {cta.comprobante_url ? (
                              <button
                                onClick={() => verComprobante(cta.comprobante_url!)}
                                className="font-bold text-dorado underline"
                              >
                                Ver comprobante
                              </button>
                            ) : online ? (
                              <span>Sin captura, verifica por la referencia</span>
                            ) : null}
                          </div>
                        )}
                      </>
                    )}
                    {!cerrada && (
                      <p className="mt-2 text-xs text-white/70">
                        Verifica y cobra la mesa en la sección <b className="text-white">Mesas</b>.
                      </p>
                    )}
                  </div>
                );
              })()}

              {/* Referencia / comprobante que envio el cliente */}
              {pago && (pago.referencia || pago.comprobante_url) && (
                <div className="mt-2 flex flex-wrap items-center gap-3 text-xs text-white/70">
                  {pago.referencia && (
                    <span>
                      Ref: <b>{pago.referencia}</b>
                    </span>
                  )}
                  {pago.comprobante_url && (
                    <button
                      onClick={() => verComprobante(pago.comprobante_url!)}
                      className="font-bold text-dorado underline"
                    >
                      Ver comprobante
                    </button>
                  )}
                </div>
              )}

              {/* Reserva de mesa sin asignar todavia: el mesero la sienta escaneando
                  el ticket QR del cliente al llegar (boton "Escanear ticket" arriba;
                  ahi mismo verifica que sea la persona y le asigna la mesa). */}
              {p.tipo_entrega === 'reserva' && !p.cuenta_id && editable && (
                <p className="mt-3 rounded-xl bg-sky-500/10 px-3 py-2 text-xs font-semibold text-sky-200 ring-1 ring-sky-500/30">
                  Cuando llegue, escanea su ticket QR (botón "Escanear ticket" arriba) para asignarle mesa.
                </p>
              )}

              {/* Confirmar pago */}
              {pago && pago.estado !== 'confirmado' && (
                <div className="mt-3 flex gap-2">
                  <button
                    onClick={() => confirmarPago(pago.id, 'confirmado')}
                    className="btn bg-green-600 text-white"
                  >
                    Confirmar pago
                  </button>
                  <button onClick={() => confirmarPago(pago.id, 'rechazado')} className="btn border border-white/20 text-white/85">
                    Rechazar
                  </button>
                </div>
              )}

              {/* Aceptar + tiempo estimado (lo ve el cliente en su seguimiento).
                  Si un mesero ya tomo este pedido de mesa, lo pone ella misma
                  desde su tablet al tomarlo (PuntoDeVenta.tsx); el panel solo
                  lo pone para mostrador/delivery y para mesa pedida por QR
                  (sin mesero, el cliente pidio solo desde su telefono). */}
              {['recibido', 'confirmado', 'preparando'].includes(p.estado) && !(p.tipo_entrega === 'mesa' && p.mesero_id) && (
                <div className="mt-3 rounded-xl bg-amber-500/10 p-2.5 ring-1 ring-amber-500/30">
                  <p className="mb-1.5 text-xs font-semibold text-amber-200">
                    {p.tiempo_estimado_min != null
                      ? `Tiempo estimado: ${p.tiempo_estimado_min} min (el cliente lo ve)`
                      : 'Ponle el tiempo estimado para avisarle al cliente'}
                  </p>
                  <div className="flex items-center gap-2">
                    <input
                      type="number"
                      min="1"
                      placeholder="min"
                      className="input w-20"
                      value={tiempos[p.id] ?? (p.tiempo_estimado_min?.toString() ?? '')}
                      onChange={(e) => setTiempos((t) => ({ ...t, [p.id]: e.target.value }))}
                    />
                    <span className="text-sm text-white/70">min</span>
                    <button
                      onClick={() => aceptar(p.id, tiempos[p.id] ?? (p.tiempo_estimado_min?.toString() ?? ''))}
                      className="btn ml-auto bg-green-600 text-white"
                    >
                      {p.estado === 'recibido' ? 'Aceptar pedido' : 'Guardar tiempo'}
                    </button>
                  </div>
                </div>
              )}

              {/* Asignar / reasignar repartidor (se puede cambiar por si el asignado no puede) */}
              {p.tipo_entrega === 'delivery' && !['entregado', 'cancelado'].includes(p.estado) && (
                <div className="mt-3">
                  {p.repartidor_id && (
                    <p className="mb-1 text-xs text-white/70">
                      Repartidor: <b className="text-white">{nombreRep(p.repartidor_id)}</b>
                    </p>
                  )}
                  <select
                    className="input"
                    value=""
                    onChange={(e) => {
                      if (e.target.value) asignar(p.id, e.target.value);
                    }}
                  >
                    <option value="" disabled>
                      {p.repartidor_id ? 'Reasignar a otro repartidor...' : 'Asignar repartidor...'}
                    </option>
                    {repartidores
                      .filter((r) => r.repartidor_id !== p.repartidor_id)
                      .map((r) => (
                        <option key={r.repartidor_id} value={r.repartidor_id}>
                          {r.nombre ?? 'Repartidor'}
                          {r.vehiculo ? ` · ${r.vehiculo}` : ''} ({r.estado})
                        </option>
                      ))}
                  </select>
                </div>
              )}

              {/* Si el delivery ya va con repartidor, el repartidor marca en camino/entregado */}
              {p.tipo_entrega === 'delivery' && p.repartidor_id && p.estado === 'en_camino' && (
                <p className="mt-3 rounded-lg bg-white/5 px-3 py-2 text-xs font-semibold text-white/70">
                  🛵 {nombreRep(p.repartidor_id)} va en camino. El repartidor marca la entrega.
                </p>
              )}

              {/* Cambiar estado (para delivery con repartidor, esos pasos los hace el repartidor) */}
              {(() => {
                const trans = siguientesEstados(p.estado, p.tipo_entrega).filter(
                  (s) =>
                    !(
                      p.tipo_entrega === 'delivery' &&
                      p.repartidor_id &&
                      (s === 'en_camino' || s === 'entregado')
                    ),
                );
                if (trans.length === 0) return null;
                return (
                  <div className="mt-3">
                    <p className="mb-1 text-xs font-semibold text-white/70">Cambiar a:</p>
                    <div className="flex flex-wrap gap-2">
                      {trans.map((s) => (
                        <button
                          key={s}
                          onClick={() => cambiarEstado(p.id, s)}
                          className="btn text-white"
                          style={{ backgroundColor: ESTADO_META[s].color }}
                        >
                          {ESTADO_META[s].label}
                        </button>
                      ))}
                    </div>
                  </div>
                );
              })()}

              {editable && (
                <button
                  onClick={() => cambiarEstado(p.id, 'cancelado')}
                  className="mt-3 w-full rounded-xl border border-red-500/40 py-2 text-sm font-bold text-red-400 hover:bg-red-500/10"
                >
                  Cancelar / eliminar pedido
                </button>
              )}

              {/* La factura de una venta entregada se anula con nota de crédito
                  (la emite la Estación Fiscal; aquí solo se pide). Los pedidos
                  de mesa se facturan por la cuenta, no sueltos. */}
              {puedeAnularFactura && p.estado === 'entregado' && !p.cuenta_id && (
                <button
                  onClick={() => {
                    setNcPedido({ id: p.id, codigo: p.codigo });
                    setNcMotivo('');
                    setNcSalida(null);
                  }}
                  className="mt-3 w-full rounded-xl border border-amber-500/40 py-2 text-sm font-bold text-amber-400 hover:bg-amber-500/10"
                >
                  Anular factura (nota de crédito)
                </button>
              )}
            </div>
          </article>
        );
      })}
    </div>
  );
}
