// Verificacion del FLUJO DE MESA DEL MESERO (fase 2) contra la BD viva.
// Usa el restaurante DEMO, mesas T80/T81, un mesero temporal, y LIMPIA todo.
// Env: SUPABASE_URL, SUPABASE_ANON_KEY, SUPABASE_SERVICE_KEY.
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;
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 nuevo = () => createClient(URL, ANON, { auth: { persistSession: false } });
const svc = createClient(URL, SERVICE, { auth: { persistSession: false } });
const num = (x) => Math.round(Number(x) * 100) / 100;

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

const EMAIL = 'mesero.test.flujo@gustitoxpress.app';
const CLAVE = 'MeseroFlujo2026!';
let meseroUid;
const limpiar = async () => {
  for (const mesa of ['T80', 'T81']) {
    const { data: ctas } = await svc.from('cuentas_mesa').select('id').eq('restaurante_id', REST).eq('mesa', mesa);
    for (const c of ctas ?? []) {
      await svc.from('pedidos').delete().eq('cuenta_id', c.id);
      await svc.from('cuentas_mesa').delete().eq('id', c.id); // comensales/llamadas/pagos caen en cascada
    }
  }
  if (meseroUid) await svc.auth.admin.deleteUser(meseroUid).catch(() => {});
};

try {
  await limpiar();
  const { data: u, error: eU } = await svc.auth.admin.createUser({ email: EMAIL, password: CLAVE, email_confirm: true });
  if (eU) throw new Error('createUser: ' + eU.message);
  meseroUid = u.user.id;
  await svc.from('perfiles').upsert({ id: meseroUid, rol: 'staff', restaurante_id: REST, nombre: 'Luis Mesero' });

  const mesero = nuevo();
  await mesero.auth.signInWithPassword({ email: EMAIL, password: CLAVE });
  const anon = nuevo();
  console.log('Setup listo\n');

  // 1) Abrir mesa separada con 2 personas
  const { data: ctaId, error: eAbrir } = await mesero.rpc('abrir_mesa', {
    p_mesa: 'T80', p_comensales: 2, p_modo: 'separada', p_nombres: ['Pedro', 'Ana'],
  });
  check(!eAbrir && !!ctaId, 'abrir_mesa crea la cuenta' + (eAbrir ? ' -> ' + eAbrir.message : ''));
  const { data: coms } = await svc.from('comensales_mesa').select('id,nombre,orden').eq('cuenta_id', ctaId).order('orden');
  check((coms?.length ?? 0) === 2 && coms[0].nombre === 'Pedro', 'Registra 2 personas en orden');
  const pedroId = coms.find((c) => c.nombre === 'Pedro').id;
  const anaId = coms.find((c) => c.nombre === 'Ana').id;
  const { data: ctaRow } = await svc.from('cuentas_mesa').select('modo_cuenta,comensales,mesero_id').eq('id', ctaId).maybeSingle();
  check(ctaRow?.modo_cuenta === 'separada' && ctaRow?.comensales === 2, 'La cuenta guarda modo y comensales');
  check(ctaRow?.mesero_id === meseroUid, 'La mesa queda asignada al mesero que la abrio');

  // 2) Pedidos por persona (los toma el mesero, como el POS)
  const pedir = async (comensalId, cant) => {
    const { data, error } = await mesero.rpc('crear_pedido', {
      p_restaurante_id: REST, p_cliente_nombre: 'En mesa', p_cliente_telefono: '',
      p_tipo_entrega: 'mesa', p_metodo_pago: 'efectivo',
      p_items: [{ producto_id: PROD_ID, cantidad: cant, _c: comensalId + cant }],
      p_mesa: 'T80', p_comensal_id: comensalId,
    });
    if (error) throw new Error('crear_pedido: ' + error.message);
    return data[0];
  };
  const rPedro = await pedir(pedroId, 1);
  check(rPedro.cuenta_id === ctaId, 'El pedido cae en la cuenta de la mesa');
  const { data: pPedro } = await svc.from('pedidos').select('comensal_id,total_usd,estado').eq('id', rPedro.pedido_id).maybeSingle();
  check(pPedro?.comensal_id === pedroId, 'El pedido queda amarrado a Pedro');
  check(pPedro?.estado === 'confirmado', 'El pedido de mesa entra DIRECTO a cocina (confirmado)');
  const rAna = await pedir(anaId, 2);
  const { data: pAna } = await svc.from('pedidos').select('total_usd').eq('id', rAna.pedido_id).maybeSingle();

  // 3) Persona ajena (uuid que no es de esta cuenta) -> rechazado
  const { error: eBad } = await mesero.rpc('crear_pedido', {
    p_restaurante_id: REST, p_cliente_nombre: 'En mesa', p_cliente_telefono: '',
    p_tipo_entrega: 'mesa', p_metodo_pago: 'efectivo',
    p_items: [{ producto_id: PROD_ID, cantidad: 1, _c: 'x' }],
    p_mesa: 'T80', p_comensal_id: '00000000-0000-0000-0000-000000000000',
  });
  check(!!eBad, 'Persona que no es de la mesa RECHAZADA (' + (eBad?.message ?? 'sin error!') + ')');

  // 4) cuenta_mesa: desglose por persona (lo ve el cliente)
  const { data: cm } = await anon.rpc('cuenta_mesa', { p_cuenta_id: ctaId });
  const fila = cm?.[0];
  check(fila?.modo_cuenta === 'separada', 'cuenta_mesa devuelve el modo');
  const pedroView = (fila?.comensales ?? []).find((c) => c.id === pedroId);
  const anaView = (fila?.comensales ?? []).find((c) => c.id === anaId);
  check(num(pedroView?.total_usd) === num(pPedro.total_usd), 'Total de Pedro por persona cuadra');
  check(num(anaView?.total_usd) === num(pAna.total_usd), 'Total de Ana por persona cuadra');
  const jsPedro = (fila?.pedidos ?? []).find((p) => p.comensal_id === pedroId);
  check(jsPedro?.comensal === 'Pedro', 'Cada pedido trae el nombre de su persona');

  // 5) Llamar al mesero
  const { data: l1 } = await anon.rpc('llamar_mesero', { p_cuenta_id: ctaId, p_tipo: 'mesero' });
  check(l1?.[0]?.ya_estaba === false && !!l1?.[0]?.llamada_id, 'El cliente llama al mesero (nueva)');
  const { data: l2 } = await anon.rpc('llamar_mesero', { p_cuenta_id: ctaId, p_tipo: 'mesero' });
  check(l2?.[0]?.ya_estaba === true, 'Segundo toque NO duplica la llamada');
  const { data: act } = await mesero.rpc('llamadas_activas', { p_restaurante_id: REST });
  check((act ?? []).some((a) => a.cuenta_id === ctaId && a.tipo === 'mesero'), 'La llamada aparece en el panel del mesero');

  // Cliente anon NO puede atender
  const { error: eAtAnon } = await anon.rpc('atender_llamada', { p_llamada_id: l1[0].llamada_id });
  check(!!eAtAnon, 'El cliente NO puede bajar la llamada (' + (eAtAnon?.message ?? 'sin error!') + ')');

  // Mesero atiende
  const { error: eAt } = await mesero.rpc('atender_llamada', { p_llamada_id: l1[0].llamada_id });
  check(!eAt, 'El mesero baja la llamada' + (eAt ? ' -> ' + eAt.message : ''));
  const { data: act2 } = await mesero.rpc('llamadas_activas', { p_restaurante_id: REST });
  check(!(act2 ?? []).some((a) => a.id === l1[0].llamada_id), 'La llamada ya no esta pendiente');

  // 6) Pedir la cuenta = otra llamada, tipo distinto, convive con la de mesero
  const { data: l3 } = await anon.rpc('llamar_mesero', { p_cuenta_id: ctaId, p_tipo: 'cuenta' });
  check(l3?.[0]?.ya_estaba === false, 'Pedir la cuenta es una llamada aparte');
} catch (e) {
  console.log('  XX  Excepción: ' + e.message);
  fallos++;
} finally {
  await limpiar();
  console.log('\nLimpieza hecha (cuenta, personas, pedidos, llamadas y usuario de prueba fuera)');
}

console.log(fallos === 0 ? '\nFLUJO MESERO OK' : `\nFLUJO MESERO: ${fallos} FALLO(S)`);
process.exit(fallos === 0 ? 0 : 1);
