import { useEffect, useMemo, useRef, useState } from 'react';
import { useParams, useNavigate, useSearchParams, Link } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import {
  precioDual,
  formatUsd,
  checkoutSchema,
  variablesTema,
  estadoTienda,
  activarPushPedido,
  categoriaEnHorario,
  motivoFueraDeHorario,
  type EstadoTienda,
  type Restaurante,
  type Categoria,
  type Producto,
  type TipoEntrega,
  type MetodoPago,
} from '@gustito/shared';
import { Icono } from '@gustito/shared/iconos';
import { supabase } from '../lib/supabase';
import { useManifestRestaurante } from '../lib/pwa';
import { useCerrarConAtras } from '../lib/useCerrarConAtras';
import { useCarrito } from '../store/carrito';
import OpcionesModal from './OpcionesModal';
import ComoPedir from './ComoPedir';

// Precio a mostrar en la tarjeta: si el precio depende de una opcion obligatoria
// (ej. tamano de la sopa), muestra "desde $X" (la mas barata) en vez del base $0.
function precioTarjeta(p: Producto, tasa: number | null): string {
  let min = p.precio_usd;
  let varia = false;
  for (const g of p.opciones ?? []) {
    if (!g.obligatorio) continue;
    const extras = (g.opciones ?? []).map((o) => o.precio_extra || 0);
    if (!extras.length) continue;
    const menor = Math.min(...extras);
    min += menor;
    if (Math.max(...extras) > menor || menor > 0) varia = true;
  }
  if (min > 0 && (varia || p.precio_usd === 0)) return `desde ${precioDual(min, tasa)}`;
  return precioDual(p.precio_usd, tasa);
}

interface TiendaData {
  rest: Restaurante;
  cats: Categoria[];
  prods: Producto[];
}

// Las columnas que la tienda necesita de verdad. Se piden por nombre y no con
// '*' a proposito: los datos fiscales del negocio (rif, razon social,
// domicilio) NO son publicos, y pedir '*' obligaba a dejarselos abiertos a
// cualquiera. Auditoria 2026-07-30, hallazgo 3.
const COLUMNAS_TIENDA =
  'id, slug, nombre, descripcion, logo_url, portada_url, color_primario, telefono, direccion, ' +
  'latitud, longitud, tasa_bs, tasa_automatica, pago_movil_datos, metodos_pago, costo_delivery_usd, ' +
  'hace_delivery, hace_pickup, delivery_modo, delivery_radio_km, horarios, abierto, activo, publicado, ' +
  'onboarding_completo, creado_en, actualizado_en, rubro, estado_ve, municipio, en_directorio, ' +
  'num_mesas, rubros, sala_promedio_min, contador_pedidos, prefijo, ultimo_cierre_en, iva_alicuota, ' +
  'precios_con_iva';

async function cargarTienda(slug: string): Promise<TiendaData> {
  const { data: rest, error } = await supabase
    .from('restaurantes')
    .select(COLUMNAS_TIENDA)
    .eq('slug', slug)
    .eq('activo', true)
    .eq('publicado', true)
    .maybeSingle();
  if (error) throw error;
  if (!rest) throw new Error('No encontramos este restaurante.');
  const restaurante = rest as unknown as Restaurante;
  const [cats, prods] = await Promise.all([
    supabase.from('categorias').select('*').eq('restaurante_id', restaurante.id).order('orden'),
    // `archivado` es lo que el negocio saco de la carta: no se muestra. Lo que
    // esta agotado (disponible = false) SI se muestra, atenuado, porque al
    // cliente le sirve saber que el negocio lo tiene aunque hoy no haya.
    supabase
      .from('productos')
      .select('*')
      .eq('restaurante_id', restaurante.id)
      .eq('archivado', false)
      .order('orden'),
  ]);
  if (cats.error) throw cats.error;
  if (prods.error) throw prods.error;
  return {
    rest: restaurante,
    cats: (cats.data ?? []) as unknown as Categoria[],
    prods: (prods.data ?? []) as unknown as Producto[],
  };
}

function comoLlegarHref(rest: Restaurante) {
  if (rest.latitud != null && rest.longitud != null)
    return `https://www.google.com/maps/dir/?api=1&destination=${rest.latitud},${rest.longitud}`;
  return `https://www.google.com/maps/dir/?api=1&destination=${encodeURIComponent(rest.direccion || rest.nombre)}`;
}

const GRUPOS = [
  { key: 'comida', label: 'Comidas' },
  { key: 'bebida', label: 'Bebidas' },
  { key: 'adicional', label: 'Adicionales' },
];

// Datos del cliente recordados en el dispositivo, para no volver a pedirlos
// (sobre todo en mesa, al agregar pedidos extra a la misma cuenta).
interface ClienteGuardado {
  nombre?: string;
  telefono?: string;
  cedula?: string;
  correo?: string;
}
function leerCliente(): ClienteGuardado {
  try {
    return JSON.parse(localStorage.getItem('gx_cliente') || '{}') as ClienteGuardado;
  } catch {
    return {};
  }
}
interface CuentaActiva {
  id: string;
  mesa: string;
  estado: string;
  total_usd: number;
  mesero_nombre: string | null;
  abierta_en: string;
  ultimo_pedido_en: string | null;
  abierta_por: string | null;
}

// Marca en ESTE telefono que es parte de la cuenta de la mesa (porque la abrio o
// porque ya pidio ahi). Sin esto no hay como distinguir a un acompañante de la
// mesa del cliente del turno siguiente que llega y se encuentra la cuenta de otro.
const claveCuenta = (id: string) => `gx_encuenta_${id}`;
function marcaDeCuenta(id: string): boolean {
  try {
    return localStorage.getItem(claveCuenta(id)) === '1';
  } catch {
    return false;
  }
}
function marcarCuenta(id: string | null | undefined) {
  if (!id) return;
  try {
    localStorage.setItem(claveCuenta(id), '1');
  } catch {
    /* sin espacio */
  }
}

function guardarCliente(d: ClienteGuardado) {
  try {
    localStorage.setItem('gx_cliente', JSON.stringify(d));
  } catch {
    /* almacenamiento no disponible */
  }
}

export default function Tienda() {
  const { slug = '' } = useParams();
  const [checkoutAbierto, setCheckoutAbierto] = useState(false);
  const [catSel, setCatSel] = useState<string | null>(null);
  const [grupoSel, setGrupoSel] = useState<string | null>(null);
  const [modalProd, setModalProd] = useState<Producto | null>(null);
  const [ayuda, setAyuda] = useState(false);
  const [verMenuIgual, setVerMenuIgual] = useState(false);
  const teniaCuentaRef = useRef(false);
  const carrito = useCarrito();
  const [searchParams] = useSearchParams();
  const navigate = useNavigate();
  const mesa = searchParams.get('mesa');
  // "Agregar mas" desde la cuenta trae ?agregar=1: se queda en el menu, no redirige.
  const agregar = searchParams.get('agregar');

  const { data, isLoading, error } = useQuery({
    queryKey: ['tienda', slug],
    queryFn: () => cargarTienda(slug),
  });
  useManifestRestaurante(data?.rest);

  // Recuperacion de mesa: si esta cuenta (restaurante+mesa) tiene una cuenta
  // abierta, al re-escanear el QR el cliente la recupera aunque haya cerrado.
  const restId = data?.rest?.id;
  const cuentaActivaQ = useQuery({
    queryKey: ['cuenta-activa', restId, mesa],
    enabled: !!(restId && mesa),
    queryFn: async () => {
      const { data: d } = await supabase.rpc('cuenta_mesa_activa', {
        p_restaurante_id: restId as string,
        p_mesa: mesa as string,
      });
      return (d as unknown as CuentaActiva[])?.[0] ?? null;
    },
    refetchInterval: 12000,
  });

  // Adopcion: si la mesa YA tiene pedidos, al escanear el cliente aterriza en SU
  // cuenta (para ver la cuenta). Recien abierta (sin pedidos) se queda en el MENU
  // para poder pedir. Con ?agregar=1 tambien se queda en el menu.
  const cuentaActivaId = cuentaActivaQ.data?.id;
  const cuentaConOrdenes = Number(cuentaActivaQ.data?.total_usd ?? 0) > 0;
  // ...pero SOLO si este telefono es de esa cuenta (la abrio o ya pidio ahi). Si
  // no, seria meter al cliente del turno siguiente en la cuenta de otro: veria
  // lo que consumieron y hasta podria pagarlo. Ese se queda en el MENU con un
  // aviso y la opcion de llamar al mesero.
  const soyDeLaCuenta = !!cuentaActivaId && marcaDeCuenta(cuentaActivaId);
  useEffect(() => {
    if (mesa && !agregar && cuentaActivaId && cuentaConOrdenes && soyDeLaCuenta) {
      navigate(`/cuenta/${cuentaActivaId}`, { replace: true });
    }
  }, [mesa, agregar, cuentaActivaId, cuentaConOrdenes, soyDeLaCuenta, navigate]);
  // Recuerda que el cliente tuvo mesa abierta CON CONSUMO, para despedirlo cuando
  // se la cobren. Ojo: solo con consumo. Una mesa que nadie uso se cierra sola a
  // los 5 minutos (fn_cerrar_mesas_vacias), y si eso despidiera al cliente,
  // botariamos de la pantalla justo al que estaba escogiendo tranquilo. Sin
  // consumo se queda en el menu y, cuando pida, la mesa se le abre de nuevo.
  useEffect(() => {
    if (cuentaActivaId && cuentaConOrdenes) teniaCuentaRef.current = true;
  }, [cuentaActivaId, cuentaConOrdenes]);

  if (isLoading) return <Centrado>Cargando menu...</Centrado>;
  if (error || !data) return <Centrado>{(error as Error)?.message ?? 'Error'}</Centrado>;

  // Mesa con cuenta que YA tiene pedidos y es la MIA: el efecto de arriba lleva
  // a la cuenta. Si no es la mia, sigo al menu (con el aviso de mesa ocupada).
  if (mesa && !agregar && cuentaActivaId && cuentaConOrdenes && soyDeLaCuenta) {
    return <Centrado>Abriendo tu mesa...</Centrado>;
  }
  // Averiguando si la mesa tiene cuenta: un momento (evita parpadeo).
  if (mesa && !agregar && cuentaActivaQ.isLoading) {
    return <Centrado>Un momento...</Centrado>;
  }
  // El cliente tuvo su mesa abierta y la cobraron/cerraron: despedirse.
  if (mesa && !agregar && teniaCuentaRef.current && !cuentaActivaId) {
    return <Centrado>¡Gracias por tu visita! La Mesa {mesa} ya se cerró.</Centrado>;
  }
  // Mesa SIN cuenta activa: bienvenida + nombre (abre la mesa) y luego cae al MENU.
  if (mesa && !agregar && !cuentaActivaId && !verMenuIgual) {
    return (
      <BienvenidaMesa
        restId={data.rest.id}
        restNombre={data.rest.nombre}
        restColor={data.rest.color_primario}
        mesa={mesa}
        onListo={async () => {
          // Quien ABRE la mesa queda marcado como parte de esa cuenta.
          const r = await cuentaActivaQ.refetch();
          marcarCuenta(r.data?.id);
        }}
        onVerMenu={() => setVerMenuIgual(true)}
      />
    );
  }

  const { rest, cats, prods } = data;
  const tasa = rest.tasa_bs;
  const estado = estadoTienda(rest);
  const catsConItems = cats.filter((c) => prods.some((p) => p.categoria_id === c.id));
  const gruposPresentes = GRUPOS.filter((g) => catsConItems.some((c) => (c.grupo ?? 'comida') === g.key));
  const grupoActivo =
    grupoSel && gruposPresentes.some((g) => g.key === grupoSel) ? grupoSel : gruposPresentes[0]?.key ?? 'comida';
  const catsGrupo = catsConItems.filter((c) => (c.grupo ?? 'comida') === grupoActivo);
  // Se queda en el desplegable "Menú" hasta que el cliente elija categoria. Solo cuando
  // el negocio tiene UNA sola categoria la muestra directo (no hay nada que elegir).
  const catActiva =
    catSel && catsGrupo.some((c) => c.id === catSel)
      ? catSel
      : catsConItems.length === 1
        ? catsGrupo[0]?.id ?? null
        : null;

  // Toda tarjeta abre el selector: con opciones -> elegir; sin opciones -> elegir cuantas.
  const pedir = (p: Producto) => setModalProd(p);

  return (
    <div
      className="min-h-full bg-crema pb-28 overflow-x-hidden"
      style={variablesTema(rest.color_primario) as React.CSSProperties}
    >
      <Hero rest={rest} estado={estado} />

      {(rest.direccion || (rest.latitud != null && rest.longitud != null)) && (
        <div className="max-w-4xl mx-auto px-4 mt-4">
          <a
            href={comoLlegarHref(rest)}
            target="_blank"
            rel="noreferrer"
            className="flex items-center gap-3 bg-white rounded-2xl p-3 shadow-tarjeta"
          >
            <span className="w-10 h-10 rounded-full bg-marca-claro text-marca-oscuro grid place-items-center">
              <Icono nombre="pin" />
            </span>
            <div className="flex-1 min-w-0">
              <p className="text-sm font-bold text-stone-800">Como llegar</p>
              {rest.direccion && <p className="text-xs text-stone-500 truncate">{rest.direccion}</p>}
            </div>
            <span className="text-marca-oscuro text-2xl leading-none shrink-0" aria-label="Abrir mapa">›</span>
          </a>
        </div>
      )}

      <div className="max-w-4xl mx-auto px-4 mt-3">
        <button
          onClick={() => setAyuda(true)}
          className="flex w-full items-center gap-3 bg-white rounded-2xl p-3 shadow-tarjeta text-left"
        >
          <span className="w-10 h-10 rounded-full bg-marca-claro text-marca-oscuro grid place-items-center">
            <Icono nombre="pregunta" />
          </span>
          <div className="flex-1 min-w-0">
            <p className="text-sm font-bold text-stone-800">¿Cómo pedir?</p>
            <p className="text-xs text-stone-500">Guía rápida paso a paso</p>
          </div>
          <span className="text-marca-oscuro text-2xl leading-none shrink-0" aria-label="Abrir guía">›</span>
        </button>
      </div>

      <div className="max-w-4xl mx-auto px-4 mt-3">
        <Link
          to="/verificar"
          className="flex w-full items-center gap-3 bg-white rounded-2xl p-3 shadow-tarjeta text-left"
        >
          <span className="w-10 h-10 rounded-full bg-marca-claro text-marca-oscuro grid place-items-center">
            <Icono nombre="recibo" />
          </span>
          <div className="flex-1 min-w-0">
            <p className="text-sm font-bold text-stone-800">¿Ya hiciste un pedido?</p>
            <p className="text-xs text-stone-500">Verifícalo y sigue tu estado</p>
          </div>
          <span className="text-marca-oscuro text-2xl leading-none shrink-0" aria-label="Verificar pedido">›</span>
        </Link>
      </div>

      {mesa && (
        <div className="max-w-4xl mx-auto px-4 mt-4">
          <div className="bg-marca text-marca-contraste text-center text-sm font-bold py-2 rounded-xl">
            Estas pidiendo desde la Mesa {mesa}
          </div>
        </div>
      )}

      {mesa && cuentaActivaQ.data && (soyDeLaCuenta || !cuentaConOrdenes) && (
        <div className="mx-auto mt-3 max-w-4xl px-4">
          <Link
            to={`/cuenta/${cuentaActivaQ.data.id}`}
            className="flex items-center justify-between gap-3 rounded-2xl border-2 border-marca bg-white p-3 shadow-tarjeta"
          >
            <div className="min-w-0">
              <p className="text-sm font-bold text-marca-oscuro">Tu cuenta de la Mesa {mesa} sigue abierta</p>
              <p className="text-xs text-stone-500">Toca para ver tus pedidos y pagar</p>
            </div>
            <span className="shrink-0 font-extrabold text-marca-oscuro">
              {precioDual(cuentaActivaQ.data.total_usd, rest.tasa_bs)}
            </span>
          </Link>
        </div>
      )}

      {/* La mesa tiene una cuenta que NO es de este telefono. Puede ser que este
          acompañando (lo normal, todo va a la misma cuenta) o que acabe de
          llegar y la mesa quedo mal cerrada. No se puede adivinar: se le
          pregunta, y si acaba de llegar se le avisa al negocio. */}
      {mesa && cuentaActivaQ.data && cuentaConOrdenes && !soyDeLaCuenta && (
        <MesaDeOtro
          cuenta={cuentaActivaQ.data}
          mesa={mesa}
          tasa={rest.tasa_bs}
          onSoyDeAqui={() => {
            marcarCuenta(cuentaActivaQ.data?.id);
            navigate(`/cuenta/${cuentaActivaQ.data?.id}`);
          }}
        />
      )}

      {catsConItems.length > 1 && (
        <div className="mx-auto mt-4 max-w-4xl px-4">
          {gruposPresentes.length > 1 && (
            <div
              className="grid gap-1.5 rounded-2xl bg-stone-100 p-1"
              style={{ gridTemplateColumns: `repeat(${gruposPresentes.length}, minmax(0, 1fr))` }}
            >
              {gruposPresentes.map((g) => (
                <button
                  key={g.key}
                  onClick={() => {
                    setGrupoSel(g.key);
                    setCatSel(null);
                  }}
                  className={`rounded-xl py-2.5 text-sm font-bold transition ${
                    grupoActivo === g.key ? 'bg-marca text-marca-contraste shadow-flotante' : 'text-stone-500'
                  }`}
                >
                  {g.label}
                </button>
              ))}
            </div>
          )}
          {catsGrupo.length > 0 && (
            <div className="relative mt-3">
              <select
                value={catActiva ?? ''}
                onChange={(e) => setCatSel(e.target.value)}
                className="w-full appearance-none rounded-xl border-2 border-marca bg-white px-4 py-3 pr-10 text-sm font-bold text-marca-oscuro outline-none"
              >
                <option value="">Menú</option>
                {catsGrupo.map((c) => (
                  <option key={c.id} value={c.id}>
                    {c.nombre}
                  </option>
                ))}
              </select>
              <span className="pointer-events-none absolute right-4 top-1/2 -translate-y-1/2 text-marca-oscuro">▾</span>
            </div>
          )}
        </div>
      )}

      <main className="mx-auto max-w-4xl px-4">
        {catsConItems.length === 0 ? (
          <p className="py-16 text-center text-stone-400">Este restaurante aun no cargo su menu.</p>
        ) : catActiva ? (
          catsConItems
            .filter((cat) => cat.id === catActiva)
            .map((cat) => {
              // Categoria con horario propio (ej. sopas solo domingos, arepas
              // desde las 5pm): se muestra igual, pero apagada y diciendo por
              // que. El candado de verdad esta en crear_pedido.
              const fueraDeHorario = !categoriaEnHorario(cat);
              return (
                <section key={cat.id} className="mt-6">
                  <h2 className="mb-2.5 font-display text-xl font-extrabold text-stone-800">{cat.nombre}</h2>
                  {fueraDeHorario && (
                    <p className="mb-2.5 rounded-xl bg-amber-50 px-3 py-2 text-sm font-semibold text-amber-800 ring-1 ring-amber-200">
                      Ahorita no se está vendiendo. {motivoFueraDeHorario(cat)}.
                    </p>
                  )}
                  <div className={`grid gap-2.5 sm:grid-cols-2${fueraDeHorario ? ' opacity-60' : ''}`}>
                    {prods
                      .filter((p) => p.categoria_id === cat.id)
                      .sort((a, b) => Number(b.disponible) - Number(a.disponible))
                      .map((p) => (
                        <ProductoCard
                          key={p.id}
                          producto={fueraDeHorario ? { ...p, disponible: false } : p}
                          tasa={tasa}
                          onAgregar={() => pedir(p)}
                        />
                      ))}
                  </div>
                </section>
              );
            })
        ) : (
          <div className="mt-8 rounded-2xl bg-white p-8 text-center shadow-tarjeta">
            <Icono nombre="plato" className="mx-auto h-10 w-10 text-marca-oscuro" />
            <p className="mt-3 font-display text-2xl font-extrabold text-marca-oscuro">¡Bienvenido!</p>
            <p className="mt-1.5 text-sm text-stone-500">
              Selecciona en el menú de arriba la categoría de tu elección para ver los platos.
            </p>
          </div>
        )}
      </main>

      {/* Pie de la tienda: marca + documentos legales siempre alcanzables. */}
      <footer className="mx-auto max-w-4xl px-4 pb-28 pt-10 text-center">
        <p className="text-xs text-stone-400">
          Con tecnología de <span className="font-bold">Gustito Xpress</span>
        </p>
        <p className="mt-1 text-xs text-stone-400">
          <a href="/terminos" target="_blank" rel="noreferrer" className="font-semibold underline">
            Términos
          </a>
          {' · '}
          <a href="/privacidad" target="_blank" rel="noreferrer" className="font-semibold underline">
            Privacidad
          </a>
        </p>
      </footer>

      {carrito.cantidadTotal() > 0 &&
        (estado.abierto ? (
          <button
            onClick={() => setCheckoutAbierto(true)}
            className="fixed bottom-[calc(1rem+env(safe-area-inset-bottom))] left-4 right-4 max-w-4xl mx-auto bg-marca text-marca-contraste rounded-2xl py-3.5 px-5 shadow-flotante flex items-center justify-between font-bold active:scale-[0.99] transition"
          >
            <span className="flex items-center gap-2">
              <span className="bg-marca-contraste/25 rounded-full w-6 h-6 grid place-items-center text-sm">
                {carrito.cantidadTotal()}
              </span>
              Ver pedido
            </span>
            <span>{formatUsd(carrito.total())}</span>
          </button>
        ) : (
          <div className="fixed bottom-[calc(1rem+env(safe-area-inset-bottom))] left-4 right-4 max-w-4xl mx-auto bg-stone-800 text-white rounded-2xl py-3 px-5 shadow-flotante flex items-center justify-between">
            <span className="flex items-center gap-2 font-bold">
              <Icono nombre="candado" className="h-4 w-4" />
              Cerrado ahora
            </span>
            <span className="text-xs font-semibold text-white/80 text-right">
              {estado.detalle ?? 'Vuelve en el horario de atención'}
            </span>
          </div>
        ))}

      {checkoutAbierto && (
        <Checkout
          rest={rest}
          mesa={mesa}
          cuentaActiva={!!cuentaActivaQ.data}
          mesaConConsumo={cuentaConOrdenes}
          onCerrar={() => setCheckoutAbierto(false)}
        />
      )}
      {modalProd && (
        <OpcionesModal
          producto={modalProd}
          tasa={tasa}
          onAgregar={(items) => items.forEach(({ cantidad, ...it }) => carrito.agregar(slug, it, cantidad ?? 1))}
          onCerrar={() => setModalProd(null)}
        />
      )}
      {ayuda && <ComoPedir onCerrar={() => setAyuda(false)} />}
    </div>
  );
}

function Hero({ rest, estado }: { rest: Restaurante; estado: EstadoTienda }) {
  return (
    <header>
      <div className="h-40 relative bg-gradient-to-br from-marca to-marca-oscuro overflow-hidden">
        {rest.portada_url && (
          <img src={rest.portada_url} alt="" className="absolute inset-0 h-full w-full object-cover" />
        )}
        <div className="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent" />
      </div>
      <div className="px-4 max-w-4xl mx-auto -mt-10 relative">
        <div className="w-20 h-20 rounded-2xl ring-4 ring-crema bg-white shadow-tarjeta overflow-hidden grid place-items-center text-3xl">
          {rest.logo_url ? (
            <img src={rest.logo_url} alt="" className="w-full h-full object-cover" />
          ) : (
            <Icono nombre="plato" className="h-9 w-9 text-marca-oscuro" />
          )}
        </div>
        <h1 className="font-display text-[26px] font-extrabold text-stone-900 mt-2 leading-[1.08]">{rest.nombre}</h1>
        {rest.descripcion && <p className="text-sm text-stone-500 mt-0.5">{rest.descripcion}</p>}
        <div className="flex flex-wrap items-center gap-2 mt-3">
          <span
            className={`text-xs font-bold px-2.5 py-1 rounded-full ${
              estado.abierto ? 'bg-green-100 text-green-700' : 'bg-stone-200 text-stone-500'
            }`}
          >
            {estado.abierto ? '● Abierto' : '● Cerrado'}
          </span>
          {estado.detalle && (
            <span
              className={`text-xs font-semibold px-2.5 py-1 rounded-full ${
                estado.abierto ? 'bg-stone-100 text-stone-600' : 'bg-amber-100 text-amber-700'
              }`}
            >
              {estado.detalle}
            </span>
          )}
          {rest.tasa_bs ? (
            <span className="text-xs font-semibold px-2.5 py-1 rounded-full bg-stone-100 text-stone-600">
              Bs {rest.tasa_bs} / $
            </span>
          ) : null}
          {rest.hace_delivery && (
            <span
              className={`text-xs font-semibold px-2.5 py-1 rounded-full ${
                rest.costo_delivery_usd === 0 ? 'bg-green-100 text-green-700' : 'bg-marca-claro text-marca-oscuro'
              }`}
            >
              {rest.costo_delivery_usd === 0 ? 'Delivery gratis' : `Delivery ${formatUsd(rest.costo_delivery_usd)}`}
            </span>
          )}
        </div>
      </div>
    </header>
  );
}

function ProductoCard({
  producto,
  tasa,
  onAgregar,
}: {
  producto: Producto;
  tasa: number | null;
  onAgregar: () => void;
}) {
  const agotado = !producto.disponible;
  return (
    <div className={`flex gap-3 bg-white rounded-2xl p-3 shadow-tarjeta ${agotado ? 'opacity-60' : ''}`}>
      <div className="w-[70px] h-[70px] rounded-xl bg-marca-claro overflow-hidden grid place-items-center shrink-0">
        {producto.foto_url ? (
          <img src={producto.foto_url} alt="" className="w-full h-full object-cover" />
        ) : (
          // Sin foto cargada: el glifo de la marca en tono suave, para que el
          // hueco se lea como parte del diseno y no como una imagen rota.
          <Icono nombre="plato" className="h-7 w-7 text-marca-oscuro/40" />
        )}
      </div>
      <div className="flex-1 min-w-0">
        <p className="font-display text-[15px] font-bold text-stone-800 leading-snug">{producto.nombre}</p>
        {producto.descripcion && (
          <p className="text-xs text-stone-500 line-clamp-2 mt-0.5">{producto.descripcion}</p>
        )}
        <p className="font-display text-sm font-extrabold text-marca-oscuro mt-1.5">
          {precioTarjeta(producto, tasa)}
        </p>
      </div>
      <div className="flex items-end">
        {agotado ? (
          <span className="text-xs font-semibold text-stone-400">Agotado</span>
        ) : producto.opciones && producto.opciones.length > 0 ? (
          <button
            onClick={onAgregar}
            className="h-9 rounded-full bg-marca px-3.5 text-xs font-bold text-marca-contraste shadow-flotante transition active:scale-95"
          >
            Elegir
          </button>
        ) : (
          <button
            onClick={onAgregar}
            className="grid h-9 w-9 place-items-center rounded-full bg-marca text-xl font-bold text-marca-contraste shadow-flotante transition active:scale-95"
            aria-label="Agregar"
          >
            +
          </button>
        )}
      </div>
    </div>
  );
}

function Checkout({
  rest,
  mesa,
  cuentaActiva,
  mesaConConsumo,
  onCerrar,
}: {
  rest: Restaurante;
  mesa: string | null;
  cuentaActiva: boolean;
  /** La mesa YA tiene pedidos: la orden va corriendo, este entra derecho a cocina. */
  mesaConConsumo: boolean;
  onCerrar: () => void;
}) {
  const navigate = useNavigate();
  const carrito = useCarrito();
  const guardado = useMemo(leerCliente, []);
  const [nombre, setNombre] = useState(guardado.nombre ?? '');
  const [telefono, setTelefono] = useState(guardado.telefono ?? '');
  const [cedula, setCedula] = useState(guardado.cedula ?? '');
  const [correo, setCorreo] = useState(guardado.correo ?? '');
  // Datos del COMPRADOR para su factura. Ojo con la frontera: aqui solo se
  // RECOGE el dato y se le pasa a quien factura (la Estacion del negocio).
  // Gustito no calcula ni muestra impuesto, y esto solo aparece si la imprenta
  // habilito a ese negocio, igual que la pantalla del RIF al cobrar del panel.
  const [quiereFactura, setQuiereFactura] = useState(false);
  const [rifFiscal, setRifFiscal] = useState('');
  const [razonFiscal, setRazonFiscal] = useState('');
  // El correo solo se le pide al cliente si el negocio de verdad emite factura;
  // si no, seria pedir un dato que no se va a usar para nada.
  const facturaQ = useQuery({
    queryKey: ['estado-fiscal', rest.id],
    staleTime: 5 * 60_000,
    queryFn: async () => {
      const { data } = await supabase.rpc('fn_estado_fiscal', { p_restaurante_id: rest.id });
      return (data as { activa?: boolean } | null)?.activa === true;
    },
  });
  const facturaActiva = facturaQ.data === true;
  // Destino pendiente cuando mostramos el aviso de "local sin internet".
  const [avisoLocal, setAvisoLocal] = useState<string | null>(null);
  // Si los datos de la factura no entraron, se avisa PERO sin tumbar la compra:
  // el pedido ya esta en la cocina. Mismo molde del aviso de arriba.
  const [avisoFactura, setAvisoFactura] = useState<{ texto: string; destino: string } | null>(null);
  const [tipo, setTipo] = useState<TipoEntrega>(mesa ? 'mesa' : 'delivery');
  // Solo en mesa: el cliente puede marcar el pedido "para llevar" (va a la misma
  // cuenta pero la cocina lo empaca).
  const [paraLlevar, setParaLlevar] = useState(false);
  // UNA MESA = UNA ORDEN, pero sin trancar a nadie: por defecto el pedido va
  // DERECHO a la cocina (sale la comanda sola). Solo si el comensal avisa que
  // faltan personas por pedir, se queda esperando para salir todo en un papel.
  const [esperarMesa, setEsperarMesa] = useState(false);
  // La pregunta solo tiene sentido al ABRIR la orden; si la mesa ya tiene
  // pedidos, este va derecho a la cocina como una ronda mas.
  const preguntarEspera = !!mesa && !mesaConConsumo;
  // Solo en 'reserva' (pide remoto, avisa que va a comer en el local): cuantas
  // personas, para que el mesero sepa que mesa preparar cuando lleguen.
  const [personas, setPersonas] = useState(2);
  // "Comer aqui" solo tiene sentido si el negocio tiene mesas configuradas.
  const aceptaReserva = rest.num_mesas > 0;
  // En mesa, si ya tenemos datos guardados (validos) no los volvemos a pedir.
  const reusarDatos = tipo === 'mesa' && !!guardado.nombre && !!guardado.telefono;
  const [editarDatos, setEditarDatos] = useState(false);
  const [direccion, setDireccion] = useState('');
  const [metodo, setMetodo] = useState<MetodoPago>('pago_movil');
  const [nota, setNota] = useState('');
  const [enviando, setEnviando] = useState(false);
  const enviandoRef = useRef(false);
  const [errorMsg, setErrorMsg] = useState<string | null>(null);
  const [gps, setGps] = useState<{ lat: number; lng: number } | null>(null);
  const [ubicando, setUbicando] = useState(false);
  useCerrarConAtras(onCerrar);

  const totalConDelivery = useMemo(() => {
    const envio = tipo === 'delivery' ? rest.costo_delivery_usd : 0;
    return carrito.total() + envio;
  }, [carrito, tipo, rest.costo_delivery_usd]);

  function usarGps() {
    if (!('geolocation' in navigator)) {
      setErrorMsg('Tu dispositivo no tiene GPS.');
      return;
    }
    setUbicando(true);
    navigator.geolocation.getCurrentPosition(
      (pos) => {
        setGps({ lat: pos.coords.latitude, lng: pos.coords.longitude });
        setUbicando(false);
      },
      () => {
        setUbicando(false);
        setErrorMsg('No pudimos obtener tu ubicacion. Activa el GPS y da permiso.');
      },
      { enableHighAccuracy: true, timeout: 10000 },
    );
  }

  async function enviar() {
    if (enviandoRef.current) return; // evita doble envio por toque rapido
    setErrorMsg(null);
    const dirGps = gps ? `Ubicacion GPS: https://www.google.com/maps?q=${gps.lat},${gps.lng}` : '';
    const direccionFinal = [direccion.trim(), dirGps].filter(Boolean).join('\n');
    const payload = {
      restaurante_id: rest.id,
      cliente_nombre: nombre,
      cliente_telefono: telefono,
      cliente_cedula: cedula || undefined,
      tipo_entrega: tipo,
      mesa: mesa || undefined,
      direccion: direccionFinal || undefined,
      direccion_lat: gps?.lat,
      direccion_lng: gps?.lng,
      metodo_pago: metodo,
      nota: nota || undefined,
      personas: tipo === 'reserva' ? personas : undefined,
      items: carrito.items.map((i) => ({
        producto_id: i.producto_id,
        nombre: i.nombre,
        precio_usd: i.precio_usd,
        cantidad: i.cantidad,
        nota: [i.opcionesTexto, i.nota].filter(Boolean).join(' · ') || undefined,
        opciones: i.opcionesElegidas,
        opciones_sel: i.opcionesSel,
      })),
    };
    const parsed = checkoutSchema.safeParse(payload);
    if (!parsed.success) {
      setErrorMsg(parsed.error.issues[0]?.message ?? 'Revisa los datos');
      return;
    }
    enviandoRef.current = true;
    setEnviando(true);
    const { data, error } = await supabase.rpc('crear_pedido', {
      p_restaurante_id: rest.id,
      p_cliente_nombre: parsed.data.cliente_nombre,
      p_cliente_telefono: parsed.data.cliente_telefono,
      p_tipo_entrega: tipo,
      p_metodo_pago: metodo,
      p_items: parsed.data.items,
      p_direccion: direccionFinal || undefined,
      p_direccion_lat: gps?.lat,
      p_direccion_lng: gps?.lng,
      p_nota: nota || undefined,
      p_mesa: mesa || undefined,
      p_cedula: cedula || undefined,
      p_cliente_correo: correo.trim() || undefined,
      p_para_llevar: paraLlevar,
      p_personas: parsed.data.personas,
      // Solo se espera si el propio comensal avisó que faltan personas por pedir.
      p_esperar_mesa: tipo === 'mesa' && preguntarEspera && esperarMesa,
    });
    setEnviando(false);
    if (error) {
      enviandoRef.current = false; // permite reintentar tras un error
      setErrorMsg(error.message);
      return;
    }
    const fila = (data as unknown as { pedido_id: string; codigo: string; cuenta_id: string | null }[])?.[0];
    if (!fila) {
      enviandoRef.current = false;
      setErrorMsg('No se pudo crear el pedido.');
      return;
    }
    guardarCliente({ nombre, telefono, cedula, correo: correo.trim() || undefined });

    // Ya pidio en esta mesa: de aqui en adelante esta cuenta SI es suya.
    marcarCuenta(fila.cuenta_id);
    // Pide permiso y suscribe este aparato a los avisos de SU pedido (best-effort,
    // no bloquea la navegacion; si no da permiso, simplemente no recibe avisos).
    void activarPushPedido(supabase, fila.pedido_id);
    carrito.limpiar();
    const destino = tipo === 'mesa' && fila.cuenta_id ? `/cuenta/${fila.cuenta_id}` : `/pedido/${fila.pedido_id}`;

    // Datos del comprador para su factura. Va DESPUES de crear el pedido y a
    // proposito no lo bloquea: la comida ya entro a la cocina, y si el RIF esta
    // malo se le avisa pero no se le tumba la compra. La BD es la que valida.
    if (facturaActiva && quiereFactura && rifFiscal.trim()) {
      const { error: eFac } = await supabase.rpc('guardar_datos_fiscales', {
        p_tipo: 'pedido',
        p_id: fila.pedido_id,
        p_rif: rifFiscal.trim(),
        p_razon_social: razonFiscal.trim() || null,
        p_direccion: null,
        p_correo: correo.trim() || null,
      });
      if (eFac) {
        setAvisoFactura({
          destino,
          texto: /RIF|digito|valido/i.test(eFac.message)
            ? 'Tu pedido entró bien, pero ese RIF no es válido. Pídele al negocio que corrija los datos de tu factura.'
            : 'Tu pedido entró bien, pero no se pudieron guardar los datos de tu factura. Avísale al negocio.',
        });
        return;
      }
    }

    // Aviso SUAVE (solo pedidos de mesa): si el sistema local del negocio esta
    // sin internet en este momento, el pedido igual quedo guardado, pero mejor
    // avisarle al mesero para que no espere en el vacio. No bloquea nada.
    if (tipo === 'mesa') {
      try {
        const { data: linea } = await supabase.rpc('fn_local_en_linea', {
          p_restaurante: rest.id,
        });
        if (linea === 'sin_conexion') {
          setAvisoLocal(destino);
          return;
        }
      } catch {
        /* si la consulta falla, seguimos normal */
      }
    }
    // En mesa vamos a la cuenta acumulada; en delivery/pickup, al seguimiento.
    navigate(destino);
  }

  return (
    <div className="fixed inset-0 bg-black/40 flex items-end sm:items-center justify-center z-20">
      {avisoFactura && (
        <div className="fixed inset-0 z-30 flex items-center justify-center bg-black/60 p-5">
          <div className="w-full max-w-sm rounded-3xl bg-white p-5 text-center">
            <p className="text-lg font-extrabold text-stone-900">¡Pedido enviado!</p>
            <p className="mt-2 text-[15px] leading-relaxed text-stone-600">{avisoFactura.texto}</p>
            <button
              onClick={() => navigate(avisoFactura.destino)}
              className="mt-4 w-full rounded-2xl bg-marca py-3.5 font-bold text-marca-contraste"
            >
              Entendido
            </button>
          </div>
        </div>
      )}
      {avisoLocal && (
        <div className="fixed inset-0 z-30 flex items-center justify-center bg-black/60 p-5">
          <div className="w-full max-w-sm rounded-3xl bg-white p-5 text-center">
            <p className="text-lg font-extrabold text-stone-900">¡Pedido enviado!</p>
            <p className="mt-2 text-[15px] leading-relaxed text-stone-600">
              El sistema del local está sin internet en este momento. Tu pedido quedó guardado, pero{' '}
              <b>avísale al mesero</b> que ya pediste, para que no se quede esperando.
            </p>
            <button
              onClick={() => navigate(avisoLocal)}
              className="mt-4 w-full rounded-2xl bg-marca py-3.5 font-bold text-marca-contraste"
            >
              Entendido
            </button>
          </div>
        </div>
      )}
      <div className="bg-white w-full max-w-lg rounded-t-3xl sm:rounded-3xl max-h-[92vh] overflow-y-auto">
        <div className="p-4 border-b border-stone-100 flex items-center justify-between sticky top-0 bg-white z-10">
          <h2 className="font-extrabold text-lg">Tu pedido</h2>
          <button onClick={onCerrar} className="text-stone-400 text-2xl leading-none w-8 h-8">
            &times;
          </button>
        </div>

        <div className="p-4 space-y-3">
          {carrito.items.map((i) => (
            <div key={i.uid} className="space-y-1.5">
              <div className="flex items-center gap-2">
                <div className="flex items-center bg-stone-100 rounded-full">
                  <button className="px-2.5 py-1 text-lg" onClick={() => carrito.setCantidad(i.uid, i.cantidad - 1)}>
                    −
                  </button>
                  <span className="w-6 text-center text-sm font-bold">{i.cantidad}</span>
                  <button className="px-2.5 py-1 text-lg" onClick={() => carrito.setCantidad(i.uid, i.cantidad + 1)}>
                    +
                  </button>
                </div>
                <span className="flex-1 text-sm font-medium">{i.nombre}</span>
                <span className="text-sm font-bold">{formatUsd(i.precio_usd * i.cantidad)}</span>
              </div>
              {i.opcionesTexto && <p className="pl-1 text-xs text-stone-500">{i.opcionesTexto}</p>}
              <input
                className="input py-1.5 text-xs"
                placeholder="Personalizar (ej: sin vegetales, sin mostaza)"
                value={i.nota ?? ''}
                maxLength={200}
                onChange={(e) => carrito.setNota(i.uid, e.target.value)}
              />
              <button
                onClick={() => carrito.duplicar(i.uid)}
                className="text-xs font-semibold text-marca-oscuro"
              >
                + Agregar otro {i.nombre} para personalizarlo aparte
              </button>
            </div>
          ))}
        </div>

        <div className="p-4 space-y-3 border-t border-stone-100">
          {reusarDatos && !editarDatos ? (
            <div className="flex items-center justify-between rounded-xl bg-stone-50 p-3">
              <div className="min-w-0">
                <p className="text-sm font-semibold text-stone-700">A nombre de {nombre}</p>
                <p className="text-xs text-stone-500">Usamos tus datos, no hace falta repetirlos</p>
              </div>
              <button
                type="button"
                onClick={() => setEditarDatos(true)}
                className="shrink-0 text-xs font-bold text-marca-oscuro"
              >
                Cambiar
              </button>
            </div>
          ) : (
            <>
              <Campo label="Tu nombre">
                <input className="input" value={nombre} onChange={(e) => setNombre(e.target.value)} />
              </Campo>
              <Campo label="Telefono (ej. 0414-1234567)">
                <input
                  className="input"
                  value={telefono}
                  onChange={(e) => setTelefono(e.target.value)}
                  inputMode="tel"
                />
              </Campo>
              <Campo label="Cedula (opcional, para tu ticket)">
                <input className="input" value={cedula} onChange={(e) => setCedula(e.target.value)} />
              </Campo>
              {facturaActiva && (
                <Campo label="Correo (opcional, para enviarte tu factura)">
                  <input
                    className="input"
                    type="email"
                    autoComplete="email"
                    inputMode="email"
                    placeholder="tucorreo@ejemplo.com"
                    value={correo}
                    onChange={(e) => setCorreo(e.target.value)}
                  />
                </Campo>
              )}
              {/* La factura sale SIEMPRE. Lo unico que se elige aqui es si va con
                  los datos del comprador o como Consumidor Final, que es lo que
                  el negocio pregunta de palabra cuando uno paga. Por eso esto es
                  una casilla chiquita y no un formulario: al que solo quiere su
                  comida no se le mete friccion. */}
              {facturaActiva && (
                <div className="rounded-xl bg-marca-claro/60 p-3">
                  <label className="flex items-center gap-2 text-sm font-bold text-marca-oscuro">
                    <input
                      type="checkbox"
                      className="h-4 w-4"
                      checked={quiereFactura}
                      onChange={(e) => setQuiereFactura(e.target.checked)}
                    />
                    Necesito la factura a nombre de mi empresa
                  </label>
                  {quiereFactura ? (
                    <div className="mt-2 space-y-2">
                      <input
                        className="input"
                        placeholder="RIF (ej. J-12345678-9)"
                        value={rifFiscal}
                        onChange={(e) => setRifFiscal(e.target.value)}
                      />
                      <input
                        className="input"
                        placeholder="Nombre o razon social"
                        value={razonFiscal}
                        onChange={(e) => setRazonFiscal(e.target.value)}
                      />
                    </div>
                  ) : (
                    <p className="mt-1 text-xs text-stone-500">
                      Si no, tu factura sale igual como Consumidor Final.
                    </p>
                  )}
                </div>
              )}
            </>
          )}

          {mesa ? (
            <div className="space-y-2">
              <div className="bg-marca-claro text-marca-oscuro text-sm font-bold rounded-xl py-2.5 text-center">
                {cuentaActiva ? `Agregando a tu cuenta · Mesa ${mesa}` : `Pedido para la Mesa ${mesa}`}
              </div>
              <div className="grid grid-cols-2 gap-2">
                {[
                  { v: false, label: 'Para comer aquí' },
                  { v: true, label: 'Para llevar' },
                ].map((o) => (
                  <button
                    key={String(o.v)}
                    onClick={() => setParaLlevar(o.v)}
                    className={`rounded-xl border-2 py-2.5 text-sm font-bold transition ${
                      paraLlevar === o.v
                        ? 'border-marca bg-marca-claro text-marca-oscuro'
                        : 'border-stone-200 bg-white text-stone-500'
                    }`}
                  >
                    {o.label}
                  </button>
                ))}
              </div>
            </div>
          ) : (
            <div className={`grid gap-2 ${aceptaReserva ? 'grid-cols-3' : 'grid-cols-2'}`}>
              {(aceptaReserva
                ? (['delivery', 'pickup', 'reserva'] as TipoEntrega[])
                : (['delivery', 'pickup'] as TipoEntrega[])
              ).map((t) => (
                <button
                  key={t}
                  onClick={() => setTipo(t)}
                  className={`py-2.5 rounded-xl text-sm font-bold border-2 transition ${
                    tipo === t
                      ? 'bg-marca-claro text-marca-oscuro border-marca'
                      : 'bg-white text-stone-500 border-stone-200'
                  }`}
                >
                  {t === 'delivery' ? 'Delivery' : t === 'pickup' ? 'Buscar en tienda' : 'Reservar mesa'}
                </button>
              ))}
            </div>
          )}

          {tipo === 'reserva' && (
            <Campo label="¿Cuántas personas?">
              <div className="flex items-center justify-center gap-4 rounded-xl bg-stone-50 py-2">
                <button
                  type="button"
                  onClick={() => setPersonas((n) => Math.max(1, n - 1))}
                  className="grid h-9 w-9 place-items-center rounded-full bg-white text-xl font-bold text-marca-oscuro shadow-tarjeta"
                >
                  −
                </button>
                <span className="w-8 text-center text-lg font-extrabold text-stone-800">{personas}</span>
                <button
                  type="button"
                  onClick={() => setPersonas((n) => Math.min(50, n + 1))}
                  className="grid h-9 w-9 place-items-center rounded-full bg-white text-xl font-bold text-marca-oscuro shadow-tarjeta"
                >
                  +
                </button>
              </div>
            </Campo>
          )}

          {tipo === 'delivery' && (
            <div className="space-y-2">
              <Campo label="Direccion de entrega">
                <textarea
                  className="input"
                  rows={2}
                  value={direccion}
                  placeholder="Casa/edificio, calle y un punto de referencia"
                  onChange={(e) => setDireccion(e.target.value)}
                />
              </Campo>
              <button
                type="button"
                onClick={usarGps}
                className={`flex w-full items-center justify-center gap-2 rounded-xl border-2 py-2.5 text-sm font-bold transition ${
                  gps ? 'border-green-500 bg-green-50 text-green-700' : 'border-marca bg-marca-claro text-marca-oscuro'
                }`}
              >
                <Icono nombre={gps ? 'check' : 'pin'} className="h-4 w-4" />
                {ubicando
                  ? 'Ubicando...'
                  : gps
                    ? 'Ubicacion lista (toca para actualizar)'
                    : 'Usar mi ubicacion (GPS)'}
              </button>
              {gps && (
                <p className="text-xs text-stone-500">
                  Al repartidor le llega un enlace al mapa con tu ubicacion exacta. Igual escribe una referencia arriba.
                </p>
              )}
            </div>
          )}

          {mesa ? (
            <>
              {preguntarEspera && (
                <div className="rounded-2xl bg-white p-3 ring-2 ring-marca">
                  <p className="text-sm font-extrabold text-marca-oscuro">
                    ¿Alguien más en la mesa va a pedir por el QR?
                  </p>
                  <div className="mt-2 grid grid-cols-2 gap-2">
                    <BotonEspera
                      activo={!esperarMesa}
                      onClick={() => setEsperarMesa(false)}
                      titulo="No, mándalo ya"
                      detalle="Va de una a la cocina"
                    />
                    <BotonEspera
                      activo={esperarMesa}
                      onClick={() => setEsperarMesa(true)}
                      titulo="Sí, faltan personas"
                      detalle="Todo sale en una sola orden"
                    />
                  </div>
                  {esperarMesa && (
                    <p className="mt-2 text-[11px] leading-snug text-stone-500">
                      Cuando todos hayan pedido, cualquiera de la mesa toca "Enviar la orden a la cocina" desde la
                      cuenta. Si nadie la manda, sale sola en 5 minutos.
                    </p>
                  )}
                </div>
              )}
              <p className="rounded-xl bg-stone-50 px-3 py-2 text-xs text-stone-500">
                {paraLlevar
                  ? 'Va marcado para llevar: la cocina lo empaca. Se suma a la cuenta de la mesa y pagas todo junto al final.'
                  : 'Tu pedido se suma a la cuenta de la mesa. Pagas todo junto al final.'}
              </p>
            </>
          ) : tipo === 'reserva' ? (
            <p className="rounded-xl bg-stone-50 px-3 py-2 text-xs text-stone-500">
              Al llegar, muestra tu ticket con QR al mesero para que te asigne mesa. Ahí puedes pedir algo más y pagas
              todo junto al final, como cualquier mesa.
            </p>
          ) : (
            <Campo label="Metodo de pago">
              <select className="input" value={metodo} onChange={(e) => setMetodo(e.target.value as MetodoPago)}>
                <option value="pago_movil">Pago Movil</option>
                <option value="efectivo">Efectivo</option>
                <option value="transferencia">Transferencia</option>
                <option value="zelle">Zelle</option>
                <option value="punto_venta">Punto de venta</option>
              </select>
            </Campo>
          )}

          <Campo label="Nota (opcional)">
            <input className="input" value={nota} onChange={(e) => setNota(e.target.value)} />
          </Campo>
        </div>

        <div className="p-4 pb-[calc(1rem+env(safe-area-inset-bottom))] border-t border-stone-100 sticky bottom-0 bg-white">
          <div className="flex justify-between mb-1.5 text-sm text-stone-500">
            <span>Subtotal</span>
            <span>{formatUsd(carrito.total())}</span>
          </div>
          {tipo === 'delivery' && (
            <div className="flex justify-between mb-1.5 text-sm text-stone-500">
              <span>Delivery</span>
              <span>{rest.costo_delivery_usd === 0 ? 'Gratis' : formatUsd(rest.costo_delivery_usd)}</span>
            </div>
          )}
          <div className="flex justify-between mb-3 font-extrabold text-lg">
            <span>Total</span>
            <span>{precioDual(totalConDelivery, rest.tasa_bs)}</span>
          </div>
          {errorMsg && <p className="text-sm text-red-600 mb-2">{errorMsg}</p>}
          <button
            disabled={enviando || carrito.items.length === 0}
            onClick={enviar}
            className="w-full bg-marca text-marca-contraste font-bold rounded-2xl py-3.5 shadow-flotante disabled:opacity-60 active:scale-[0.99] transition"
          >
            {enviando
              ? 'Enviando...'
              : !mesa
                ? 'Confirmar pedido'
                : esperarMesa
                  ? paraLlevar
                    ? 'Agregar a la orden (para llevar)'
                    : 'Agregar a la orden de la mesa'
                  : paraLlevar
                    ? 'Mandar a la cocina (para llevar)'
                    : 'Mandar a la cocina'}
          </button>
          {/* Aceptacion legal del comensal: en un clic queda claro que rigen los
              terminos. Abren en pestana nueva para no perder el carrito. */}
          <p className="mt-2 text-center text-[11px] leading-snug text-stone-400">
            Al enviar tu pedido aceptas los{' '}
            <a href="/terminos" target="_blank" rel="noreferrer" className="font-semibold text-stone-500 underline">
              Términos
            </a>{' '}
            y la{' '}
            <a href="/privacidad" target="_blank" rel="noreferrer" className="font-semibold text-stone-500 underline">
              Política de Privacidad
            </a>
            .
          </p>
        </div>
      </div>
    </div>
  );
}

// La mesa ya tiene cuenta y este telefono no es parte de ella. Dos caminos, sin
// enredo: acompañar (todo a la misma cuenta) o avisar que la mesa quedo ocupada.
function MesaDeOtro({
  cuenta,
  mesa,
  tasa,
  onSoyDeAqui,
}: {
  cuenta: CuentaActiva;
  mesa: string;
  tasa: number | null;
  onSoyDeAqui: () => void;
}) {
  const [avisando, setAvisando] = useState(false);
  const [avisado, setAvisado] = useState(false);
  const [errAviso, setErrAviso] = useState<string | null>(null);
  const desde = cuenta.ultimo_pedido_en ?? cuenta.abierta_en;
  const horas = (Date.now() - new Date(desde).getTime()) / 3600000;
  // Si el ultimo pedido es viejo, lo mas probable es que la mesa quedara mal
  // cerrada; ahi el aviso es fuerte. Si es reciente, la mesa esta comiendo.
  const sospechosa = horas >= 2;

  async function avisar() {
    setAvisando(true);
    setErrAviso(null);
    const { error } = await supabase.rpc('llamar_mesero', { p_cuenta_id: cuenta.id, p_tipo: 'ocupada' });
    setAvisando(false);
    if (error) setErrAviso('No pudimos avisar. Llama al mesero de viva voz, por favor.');
    else setAvisado(true);
  }

  return (
    <div className="mx-auto mt-3 max-w-4xl px-4">
      <div className={`rounded-2xl border-2 bg-white p-3 shadow-tarjeta ${sospechosa ? 'border-amber-500' : 'border-marca'}`}>
        <p className="text-sm font-extrabold text-marca-oscuro">
          {sospechosa
            ? `Ojo: la Mesa ${mesa} tiene una cuenta abierta sin cobrar`
            : `La Mesa ${mesa} ya tiene una cuenta abierta`}
        </p>
        <p className="mt-1 text-xs text-stone-600">
          {cuenta.abierta_por ? `La abrió ${cuenta.abierta_por}. ` : ''}
          Van {precioDual(cuenta.total_usd, tasa)}.{' '}
          {sospechosa
            ? 'Si acabas de sentarte, avísale al mesero antes de pedir para que no te sumen lo de otra gente.'
            : 'Si estás en esa mesa, pide tranquilo: todo se suma a la misma cuenta.'}
        </p>
        {avisado ? (
          <p className="mt-2 rounded-xl bg-marca-claro px-3 py-2 text-sm font-bold text-marca-oscuro">
            Listo, ya le avisamos al mesero. Ya viene a resolverlo.
          </p>
        ) : (
          <div className="mt-2 grid grid-cols-2 gap-2">
            <button
              onClick={onSoyDeAqui}
              className="rounded-xl border-2 border-marca px-2 py-2 text-sm font-bold text-marca-oscuro"
            >
              Estoy en esta mesa
            </button>
            <button
              onClick={avisar}
              disabled={avisando}
              className="rounded-xl bg-marca px-2 py-2 text-sm font-bold text-marca-contraste disabled:opacity-60"
            >
              {avisando ? 'Avisando...' : 'Acabo de llegar'}
            </button>
          </div>
        )}
        {errAviso && <p className="mt-2 text-xs font-semibold text-red-600">{errAviso}</p>}
      </div>
    </div>
  );
}

function Campo({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <label className="block">
      <span className="text-xs font-semibold text-stone-500">{label}</span>
      <div className="mt-1">{children}</div>
    </label>
  );
}

// Las dos salidas de la pregunta "falta alguien por pedir?" (mismo patron visual
// que los botones de metodo de pago: se ve cual esta elegido de un vistazo).
function BotonEspera({
  activo,
  onClick,
  titulo,
  detalle,
}: {
  activo: boolean;
  onClick: () => void;
  titulo: string;
  detalle: string;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={`rounded-xl border-2 px-2 py-2 text-left transition ${
        activo ? 'border-marca bg-marca-claro text-marca-oscuro' : 'border-stone-200 text-stone-500'
      }`}
    >
      <span className="block text-sm font-bold">{titulo}</span>
      <span className="block text-[11px] leading-tight">{detalle}</span>
    </button>
  );
}

// Al escanear una mesa que no tiene cuenta abierta: el cliente pone su nombre y
// eso ABRE la mesa (queda ocupada en el panel). Puede tambien solo ver el menu.
function BienvenidaMesa({
  restId,
  restNombre,
  restColor,
  mesa,
  onListo,
  onVerMenu,
}: {
  restId: string;
  restNombre: string;
  restColor: string;
  mesa: string;
  onListo: () => void;
  onVerMenu: () => void;
}) {
  const [nombre, setNombre] = useState('');
  const [abriendo, setAbriendo] = useState(false);
  const [err, setErr] = useState<string | null>(null);

  async function abrir() {
    if (!nombre.trim()) {
      setErr('Escribe tu nombre.');
      return;
    }
    setErr(null);
    setAbriendo(true);
    const { error } = await supabase.rpc('abrir_mesa_cliente', {
      p_restaurante_id: restId,
      p_mesa: mesa,
      p_nombre: nombre.trim(),
    });
    setAbriendo(false);
    if (error) {
      setErr(error.message);
      return;
    }
    // Recuerda el nombre para que el menu/checkout lo use al pedir.
    guardarCliente({ ...leerCliente(), nombre: nombre.trim() });
    onListo();
  }

  return (
    <div className="min-h-full bg-crema" style={variablesTema(restColor) as React.CSSProperties}>
      <div className="mx-auto flex min-h-full max-w-md flex-col justify-center p-6">
        <div className="rounded-3xl bg-white p-6 text-center shadow-tarjeta">
          <p className="text-sm text-stone-500">{restNombre}</p>
          <h1 className="text-2xl font-extrabold text-marca-oscuro">Mesa {mesa}</h1>
          <p className="mt-2 text-sm text-stone-600">
            Escribe tu nombre para abrir la mesa. Así el mesero sabe que ya estás aquí.
          </p>
          <input
            className="input mt-4 text-center"
            placeholder="Tu nombre"
            value={nombre}
            onChange={(e) => setNombre(e.target.value)}
          />
          {err && <p className="mt-2 text-sm text-red-600">{err}</p>}
          <button
            onClick={abrir}
            disabled={abriendo}
            className="mt-3 w-full rounded-2xl bg-marca py-3.5 font-bold text-marca-contraste shadow-flotante disabled:opacity-60"
          >
            {abriendo ? 'Abriendo...' : 'Abrir mi mesa'}
          </button>
          <button onClick={onVerMenu} className="mt-2 w-full py-2 text-sm font-semibold text-stone-500">
            Solo ver el menú
          </button>
        </div>
      </div>
    </div>
  );
}

function Centrado({ children }: { children: React.ReactNode }) {
  return (
    <div className="min-h-full flex items-center justify-center p-6 text-center text-stone-500">{children}</div>
  );
}
