// LA COMANDA DEL QR SALE SOLA (2026-07-27)
// Bug real del piloto: el pedido que hacia el cliente desde el QR nacia de
// borrador y solo lo podia mandar a cocina quien ABRIO la mesa desde SU
// telefono; si la mesa la abria la mesera desde el panel, la comanda no salia
// NUNCA (caso APR-0112 de Arepa Power: cobrado sin que la cocina lo viera).
// Ahora: el pedido del QR va derecho a cocina salvo que el comensal avise que
// faltan personas; en ese caso lo manda CUALQUIERA de la mesa, y si nadie lo
// manda, la red de seguridad lo suelta a los 5 minutos.
// Corre contra el restaurante DEMO (nunca contra un negocio real) y LIMPIA todo.
import { createClient } from '@supabase/supabase-js';

const URL = process.env.SUPABASE_URL || process.env.VITE_SUPABASE_URL;
const ANON = process.env.SUPABASE_ANON_KEY || process.env.VITE_SUPABASE_ANON_KEY;
const SERVICE = process.env.SUPABASE_SERVICE_KEY || process.env.SUPABASE_SERVICE_ROLE_KEY;
if (!URL || !ANON || !SERVICE) {
  console.log('Faltan SUPABASE_URL / SUPABASE_ANON_KEY / SUPABASE_SERVICE_KEY');
  process.exit(1);
}

let fallos = 0;
const check = (cond, msg) => {
  console.log((cond ? '  OK  ' : '  XX  ') + msg);
  if (!cond) fallos++;
};
const anon = () => createClient(URL, ANON, { auth: { persistSession: false } });
const svc = createClient(URL, SERVICE, { auth: { persistSession: false } });

const MESA_SOLO = 'TQ91'; // cliente solo: sale de una
const MESA_GRUPO = 'TQ92'; // esperando a los demas
const MESA_RESCATE = 'TQ93'; // nadie manda la orden: la suelta el cron
const MESA_MESERA = 'TQ94'; // pedido del personal: no debe cambiar nada
const MESAS = [MESA_SOLO, MESA_GRUPO, MESA_RESCATE, MESA_MESERA];

const EMAIL = 'mesera.test.comandaqr@gustitoxpress.app';
const CLAVE = 'ComandaQr2026!';
let staffUid = null;

const { data: rest } = await svc.from('restaurantes').select('id,abierto').eq('slug', 'demo-gustito').maybeSingle();
if (!rest?.id) {
  console.log('Demo no disponible');
  process.exit(1);
}
const REST = rest.id;
const { data: prods } = await svc
  .from('productos')
  .select('id,nombre,precio_usd')
  .eq('restaurante_id', REST)
  .eq('disponible', true)
  .limit(1);
const PROD = prods?.[0];
if (!PROD) {
  console.log('El demo no tiene productos disponibles');
  process.exit(1);
}

const limpiar = async () => {
  const { data: cuentas } = await svc.from('cuentas_mesa').select('id').eq('restaurante_id', REST).in('mesa', MESAS);
  for (const c of cuentas ?? []) {
    const { data: peds } = await svc.from('pedidos').select('id').eq('cuenta_id', c.id);
    for (const p of peds ?? []) {
      await svc.from('pedido_items').delete().eq('pedido_id', p.id);
      await svc.from('pagos').delete().eq('pedido_id', p.id);
    }
    await svc.from('pedidos').delete().eq('cuenta_id', c.id);
    await svc.from('pagos_mesa').delete().eq('cuenta_id', c.id);
    await svc.from('comensales_mesa').delete().eq('cuenta_id', c.id);
    await svc.from('cuentas_mesa').delete().eq('id', c.id);
  }
  if (staffUid) {
    await svc.from('perfiles').delete().eq('id', staffUid);
    await svc.auth.admin.deleteUser(staffUid).catch(() => {});
  }
};

const pedirQr = async (mesa, esperar) => {
  const cli = anon();
  const { data, error } = await cli.rpc('crear_pedido', {
    p_restaurante_id: REST,
    p_cliente_nombre: 'Cliente QR',
    p_cliente_telefono: '04120000000',
    p_tipo_entrega: 'mesa',
    p_metodo_pago: 'efectivo',
    p_items: [{ producto_id: PROD.id, nombre: PROD.nombre, precio_usd: PROD.precio_usd, cantidad: 1 }],
    p_mesa: mesa,
    ...(esperar === undefined ? {} : { p_esperar_mesa: esperar }),
  });
  if (error) throw new Error(`crear_pedido(${mesa}): ${error.message}`);
  return data?.[0];
};

const estadoDe = async (id) => (await svc.from('pedidos').select('estado,confirmado_en').eq('id', id).maybeSingle()).data;

try {
  await limpiar();
  console.log('\n== 1. Cliente SOLO: la comanda sale de una ==');
  const solo = await pedirQr(MESA_SOLO, false);
  const e1 = await estadoDe(solo.pedido_id);
  check(e1?.estado === 'confirmado', `pedido del QR nace confirmado (fue "${e1?.estado}") = el cerebrito lo imprime`);
  check(!!e1?.confirmado_en, 'confirmado_en queda sellado (el barrido de respaldo lo encuentra)');

  console.log('\n== 2. Sin mandar el parametro: tambien sale (default seguro) ==');
  const porDefecto = await pedirQr(MESA_SOLO, undefined);
  const e2 = await estadoDe(porDefecto.pedido_id);
  check(e2?.estado === 'confirmado', `sin p_esperar_mesa nace confirmado (fue "${e2?.estado}")`);

  console.log('\n== 3. "Faltan personas por pedir": espera de borrador ==');
  const grupo = await pedirQr(MESA_GRUPO, true);
  const e3 = await estadoDe(grupo.pedido_id);
  check(e3?.estado === 'recibido', `queda de borrador (fue "${e3?.estado}")`);
  check(!e3?.confirmado_en, 'sin confirmado_en: la cocina todavia no lo ve');

  console.log('\n== 4. La manda CUALQUIERA de la mesa (antes solo el telefono que abrio) ==');
  const otro = anon(); // otro comensal, sin ninguna marca guardada
  const { data: envio, error: errEnvio } = await otro.rpc('enviar_orden_mesa', { p_cuenta_id: grupo.cuenta_id });
  check(!errEnvio, `enviar_orden_mesa sin sesion ni marca: ${errEnvio?.message ?? 'pasa'}`);
  check(Number(envio?.enviados) === 1, `manda 1 pedido a cocina (mando ${envio?.enviados})`);
  const e4 = await estadoDe(grupo.pedido_id);
  check(e4?.estado === 'confirmado', `el borrador quedo confirmado (fue "${e4?.estado}")`);

  console.log('\n== 5. RED DE SEGURIDAD: nadie mando la orden ==');
  const rescate = await pedirQr(MESA_RESCATE, true);
  const nada = await svc.rpc('fn_soltar_ordenes_mesa_vencidas');
  check(!nada.error, `la funcion corre con service_role: ${nada.error?.message ?? 'ok'}`);
  const e5a = await estadoDe(rescate.pedido_id);
  check(e5a?.estado === 'recibido', 'un borrador RECIEN hecho no se suelta (todavia estan pidiendo)');
  // Lo envejecemos 6 minutos y volvemos a correr lo que corre el cron cada minuto.
  await svc
    .from('pedidos')
    .update({ recibido_en: new Date(Date.now() - 6 * 60 * 1000).toISOString() })
    .eq('id', rescate.pedido_id);
  const soltados = await svc.rpc('fn_soltar_ordenes_mesa_vencidas');
  const e5b = await estadoDe(rescate.pedido_id);
  check(Number(soltados.data) >= 1, `suelta el borrador vencido (solto ${soltados.data})`);
  check(e5b?.estado === 'confirmado', `a los 5 min va solo a la cocina (quedo "${e5b?.estado}")`);
  check(!!e5b?.confirmado_en, 'con confirmado_en sellado: el cerebrito lo imprime igual');

  console.log('\n== 6. El rescate NO toca mesas ya cerradas ==');
  const cerrada = await pedirQr(MESA_RESCATE, true);
  await svc
    .from('pedidos')
    .update({ recibido_en: new Date(Date.now() - 9 * 60 * 1000).toISOString() })
    .eq('id', cerrada.pedido_id);
  await svc.from('cuentas_mesa').update({ estado: 'cerrada', cerrada_en: new Date().toISOString() }).eq('id', cerrada.cuenta_id);
  await svc.rpc('fn_soltar_ordenes_mesa_vencidas');
  const e6 = await estadoDe(cerrada.pedido_id);
  // Al cerrar la cuenta, el trigger trg_mesa_cerrada_entregar ya deja los
  // pedidos en 'entregado'; lo que importa es que el rescate NO mande una
  // comanda a la cocina de una mesa que ya se fue.
  check(e6?.estado !== 'confirmado', `mesa cerrada: no se manda nada a la cocina (quedo "${e6?.estado}")`);
  await svc.from('cuentas_mesa').update({ estado: 'abierta', cerrada_en: null }).eq('id', cerrada.cuenta_id);

  console.log('\n== 7. Sin regresion: el pedido que carga la MESERA sigue saliendo ==');
  const { data: creado } = await svc.auth.admin.createUser({
    email: EMAIL,
    password: CLAVE,
    email_confirm: true,
  });
  staffUid = creado?.user?.id;
  await svc.from('perfiles').upsert({ id: staffUid, nombre: 'Mesera Test QR', rol: 'staff', restaurante_id: REST });
  const cliStaff = anon();
  const { error: errLogin } = await cliStaff.auth.signInWithPassword({ email: EMAIL, password: CLAVE });
  check(!errLogin, `login de la mesera: ${errLogin?.message ?? 'ok'}`);
  const { data: dm, error: errM } = await cliStaff.rpc('crear_pedido', {
    p_restaurante_id: REST,
    p_cliente_nombre: 'Mesa 4',
    p_cliente_telefono: '04120000001',
    p_tipo_entrega: 'mesa',
    p_metodo_pago: 'efectivo',
    p_items: [{ producto_id: PROD.id, nombre: PROD.nombre, precio_usd: PROD.precio_usd, cantidad: 1 }],
    p_mesa: MESA_MESERA,
    p_esperar_mesa: true, // aunque le llegue en true, el del personal va directo
  });
  check(!errM, `la mesera crea el pedido: ${errM?.message ?? 'ok'}`);
  const e7 = await estadoDe(dm?.[0]?.pedido_id);
  check(e7?.estado === 'confirmado', `el pedido del personal sigue naciendo confirmado (fue "${e7?.estado}")`);

  console.log('\n== 8. Segunda ronda de la misma mesa ==');
  const ronda2 = await pedirQr(MESA_SOLO, false);
  const e8 = await estadoDe(ronda2.pedido_id);
  check(e8?.estado === 'confirmado', `la ronda 2 tambien sale de una (fue "${e8?.estado}")`);
  check(ronda2.cuenta_id === solo.cuenta_id, 'se suma a la MISMA cuenta de la mesa (no abre otra)');
} catch (e) {
  console.log('  XX  ' + e.message);
  fallos++;
} finally {
  await limpiar();
}

console.log(fallos === 0 ? '\nTODO VERDE' : `\n${fallos} FALLO(S)`);
process.exit(fallos === 0 ? 0 : 1);
