// Aislamiento ESTRICTO entre meseras ("cada quien lo suyo"). Prueba contra prod.
//  - MISMO local: B NO ve ni cobra ni suma a la mesa de A; SÍ ve/cobra la suya y
//    las mesas SIN asignar (para tomarlas). El cliente (anon) sigue viendo su cuenta.
//  - OTRO local: B no ve nada de arepa-power.
// 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 credenciales'); 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 { data: demo } = await svc.from('restaurantes').select('id').eq('slug', 'demo-gustito').maybeSingle();
const { data: otro } = await svc.from('restaurantes').select('id,nombre').neq('slug', 'demo-gustito').eq('publicado', true).limit(1).maybeSingle();
if (!demo?.id) { console.log('Demo no disponible'); process.exit(1); }
const REST = demo.id, OTRO = otro?.id;
const { data: prods } = await svc.from('productos').select('id').eq('restaurante_id', REST).eq('disponible', true).limit(1);
const PROD = prods[0].id;

const EMAIL_A = 'mesera.a.aisla@gustitoxpress.app', EMAIL_B = 'mesera.b.aisla@gustitoxpress.app', CLAVE = 'AislaTest2026!';
let uidA, uidB;

const limpiar = async () => {
  for (const mesa of ['ZA1', 'ZB1', 'ZC1']) {
    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('pagos_mesa').delete().eq('cuenta_id', c.id);
      await svc.from('pedidos').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);
    }
  }
  const { data: list } = await svc.auth.admin.listUsers({ page: 1, perPage: 1000 });
  for (const u of list?.users ?? []) if (u.email === EMAIL_A || u.email === EMAIL_B) await svc.auth.admin.deleteUser(u.id).catch(() => {});
};

const pedir = async (cli, mesa) => {
  const { data, error } = await cli.rpc('crear_pedido', {
    p_restaurante_id: REST, p_cliente_nombre: 'x', p_cliente_telefono: '',
    p_tipo_entrega: 'mesa', p_metodo_pago: 'efectivo',
    p_items: [{ producto_id: PROD, cantidad: 1 }], p_mesa: mesa,
  });
  return { data: data?.[0], error };
};

try {
  await limpiar();
  const { data: ua } = await svc.auth.admin.createUser({ email: EMAIL_A, password: CLAVE, email_confirm: true });
  uidA = ua.user.id;
  await svc.from('perfiles').upsert({ id: uidA, rol: 'staff', restaurante_id: REST, nombre: 'Mesera A' });
  const { data: ub } = await svc.auth.admin.createUser({ email: EMAIL_B, password: CLAVE, email_confirm: true });
  uidB = ub.user.id;
  await svc.from('perfiles').upsert({ id: uidB, rol: 'staff', restaurante_id: REST, nombre: 'Mesera B' });

  const A = nuevo(); await A.auth.signInWithPassword({ email: EMAIL_A, password: CLAVE });
  const B = nuevo(); await B.auth.signInWithPassword({ email: EMAIL_B, password: CLAVE });
  console.log('Dos meseras del demo listas\n');

  const rA = await pedir(A, 'ZA1'); if (rA.error) throw new Error('A pedir: ' + rA.error.message);
  const rB = await pedir(B, 'ZB1'); if (rB.error) throw new Error('B pedir: ' + rB.error.message);
  const pedA = rA.data, pedB = rB.data;

  console.log('--- B NO debe ver ni tocar lo de A ---');
  const { data: pedAvistoPorB } = await B.from('pedidos').select('id').eq('id', pedA.pedido_id).maybeSingle();
  check(!pedAvistoPorB, 'B NO puede leer el pedido de A (RLS)');
  const { data: ctasB } = await B.rpc('mis_cuentas_mesa', { p_restaurante_id: REST });
  check(!(ctasB ?? []).some((c) => c.mesa === 'ZA1'), 'B NO ve la mesa de A en su lista');
  check((ctasB ?? []).some((c) => c.mesa === 'ZB1'), 'B SÍ ve su propia mesa (ZB1)');
  const { data: ctaAporB } = await B.rpc('cuenta_mesa', { p_cuenta_id: pedA.cuenta_id });
  check((ctaAporB ?? []).length === 0, 'B NO puede abrir la cuenta de A por id (cuenta_mesa)');
  const { error: eCobraA } = await B.rpc('cobrar_y_cerrar_mesa', { p_cuenta_id: pedA.cuenta_id, p_metodo: 'efectivo' });
  check(!!eCobraA, 'B NO puede cobrar la mesa de A: ' + (eCobraA?.message ?? 'SE DEJO!'));
  const { error: eSumaA } = await B.rpc('crear_pedido', {
    p_restaurante_id: REST, p_cliente_nombre: 'x', p_cliente_telefono: '', p_tipo_entrega: 'mesa',
    p_metodo_pago: 'efectivo', p_items: [{ producto_id: PROD, cantidad: 1 }], p_mesa: 'ZA1',
  });
  check(!!eSumaA, 'B NO puede sumar un pedido a la mesa de A: ' + (eSumaA?.message ?? 'SE DEJO!'));
  const { error: eCerrarA } = await B.rpc('cerrar_cuenta_mesa', { p_cuenta_id: pedA.cuenta_id });
  check(!!eCerrarA, 'B NO puede CERRAR la mesa de A: ' + (eCerrarA?.message ?? 'LA CERRO!'));
  const { error: eComensalA } = await B.rpc('agregar_comensal', { p_cuenta_id: pedA.cuenta_id, p_nombre: 'Colado' });
  check(!!eComensalA, 'B NO puede agregar comensal a la mesa de A: ' + (eComensalA?.message ?? 'LO AGREGO!'));

  console.log('\n--- B SÍ maneja lo suyo y las mesas libres ---');
  // Mesa sin asignar (la abre el cliente por QR): visible para tomarla.
  await svc.from('cuentas_mesa').insert({ restaurante_id: REST, mesa: 'ZC1', estado: 'abierta', comensales: 1, modo_cuenta: 'unica' });
  const { data: ctasB2 } = await B.rpc('mis_cuentas_mesa', { p_restaurante_id: REST });
  check((ctasB2 ?? []).some((c) => c.mesa === 'ZC1'), 'B SÍ ve una mesa SIN asignar (para tomarla)');
  const rClaim = await pedir(B, 'ZC1');
  check(!rClaim.error, 'B puede tomar una mesa libre (queda suya)' + (rClaim.error ? ' -> ' + rClaim.error.message : ''));
  const { error: eCobraMia } = await B.rpc('cobrar_y_cerrar_mesa', { p_cuenta_id: pedB.cuenta_id, p_metodo: 'efectivo' });
  check(!eCobraMia, 'B SÍ puede cobrar su propia mesa' + (eCobraMia ? ' -> ' + eCobraMia.message : ''));

  console.log('\n--- El cliente (anon) sigue viendo SU cuenta ---');
  const anon = nuevo();
  const { data: ctaAnon } = await anon.rpc('cuenta_mesa', { p_cuenta_id: pedA.cuenta_id });
  check((ctaAnon ?? []).length === 1, 'El cliente anon SÍ ve la cuenta de su mesa (no se rompio el flujo del cliente)');

  console.log('\n--- Otro local: bloqueado ---');
  if (OTRO) {
    const { data: espiaPed } = await B.from('pedidos').select('id').eq('restaurante_id', OTRO).limit(5);
    check((espiaPed ?? []).length === 0, `B NO ve pedidos de otro local (${otro.nombre})`);
    const { data: espiaCtas } = await B.rpc('mis_cuentas_mesa', { p_restaurante_id: OTRO });
    check((espiaCtas ?? []).length === 0, 'B NO ve las mesas de otro local');
  }
} catch (e) {
  console.log('  XX  Excepción: ' + e.message); fallos++;
} finally {
  await limpiar();
  console.log('\nLimpieza hecha');
}

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