// Verifica el nuevo rol 'encargado': opera el negocio (pedidos/cocina/mesas/
// menu, incluso mesas ajenas y anular cobros) pero NO ve lo gerencial
// (estadisticas/reporte de pagos/caja/config) ni administra personal.
// Usa el restaurante DEMO, mesa TF99, 1 dueño + 1 encargado + 1 staff
// temporales, 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 nuevo = () => createClient(URL, ANON, { auth: { persistSession: false } });
const svc = createClient(URL, SERVICE, { auth: { persistSession: false } });
const MESA = 'TF99';

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').eq('restaurante_id', REST).eq('disponible', true).limit(1);
const PROD_ID = prods?.[0]?.id;
const { data: cats } = await svc.from('categorias').select('id').eq('restaurante_id', REST).limit(1);
const CAT_ID = cats?.[0]?.id;

const EMAIL_ENC = 'encargado.test.rol@gustitoxpress.app';
const EMAIL_STAFF = 'staff.test.rol@gustitoxpress.app';
const CLAVE = 'RolEnc2026!';
let uidEnc, uidStaff;
let cuentaMeseroId, cuentaEncargadoId, productoTest, pagoMesaId;

const limpiar = async () => {
  for (const cId of [cuentaMeseroId, cuentaEncargadoId]) {
    if (!cId) continue;
    await svc.from('pagos_mesa').delete().eq('cuenta_id', cId);
    await svc.from('pedidos').update({ cuenta_id: null }).eq('cuenta_id', cId);
    await svc.from('cuentas_mesa').delete().eq('id', cId);
  }
  if (productoTest) await svc.from('productos').delete().eq('id', productoTest);
  if (uidEnc) await svc.auth.admin.deleteUser(uidEnc).catch(() => {});
  if (uidStaff) await svc.auth.admin.deleteUser(uidStaff).catch(() => {});
};

try {
  await limpiar();
  if (!PROD_ID || !CAT_ID) throw new Error('Demo sin productos/categorias');

  const { data: uE, error: eE } = await svc.auth.admin.createUser({ email: EMAIL_ENC, password: CLAVE, email_confirm: true });
  if (eE) throw new Error('createUser encargado: ' + eE.message);
  uidEnc = uE.user.id;
  await svc.from('perfiles').upsert({ id: uidEnc, rol: 'encargado', restaurante_id: REST, nombre: 'Encargado Test' });

  const { data: uS, error: eS } = await svc.auth.admin.createUser({ email: EMAIL_STAFF, password: CLAVE, email_confirm: true });
  if (eS) throw new Error('createUser staff: ' + eS.message);
  uidStaff = uS.user.id;
  await svc.from('perfiles').upsert({ id: uidStaff, rol: 'staff', restaurante_id: REST, nombre: 'Mesero Test' });

  const encargado = nuevo();
  await encargado.auth.signInWithPassword({ email: EMAIL_ENC, password: CLAVE });
  const mesero = nuevo();
  await mesero.auth.signInWithPassword({ email: EMAIL_STAFF, password: CLAVE });

  // --- OPERATIVO: el encargado abre mesa, toma pedido, ve mesas ajenas ---
  const { data: cIdMesero, error: eAbrirMesero } = await mesero.rpc('abrir_mesa', { p_mesa: MESA, p_comensales: 1, p_modo: 'unica' });
  check(!eAbrirMesero && !!cIdMesero, 'el mesero abre la mesa TF99' + (eAbrirMesero ? ' -> ' + eAbrirMesero.message : ''));
  cuentaMeseroId = cIdMesero;

  const { data: listaEnc, error: eListaEnc } = await encargado.rpc('mis_cuentas_mesa', { p_restaurante_id: REST });
  const filaVista = (listaEnc ?? []).find((c) => c.mesa === MESA);
  check(!eListaEnc && !!filaVista, 'el encargado VE la mesa del mesero en mis_cuentas_mesa' + (eListaEnc ? ' -> ' + eListaEnc.message : ''));

  const { data: pedEnc, error: ePedEnc } = await encargado.rpc('crear_pedido', {
    p_restaurante_id: REST,
    p_cliente_nombre: 'Cliente Encargado Test',
    p_cliente_telefono: '04120007777',
    p_tipo_entrega: 'mesa',
    p_metodo_pago: 'efectivo',
    p_items: [{ producto_id: PROD_ID, cantidad: 1 }],
    p_mesa: MESA,
  });
  check(!ePedEnc && !!pedEnc?.[0]?.pedido_id, 'el encargado SI puede tomar un pedido en la mesa AJENA (del mesero)' + (ePedEnc ? ' -> ' + ePedEnc.message : ''));

  // --- Cobrar y anular: el encargado cobra la mesa con pago_movil, y anula ---
  const { error: eCobrar } = await encargado.rpc('cobrar_y_cerrar_mesa', { p_cuenta_id: cuentaMeseroId, p_metodo: 'pago_movil', p_referencia: '00111222333' });
  check(!eCobrar, 'el encargado puede cobrar la mesa' + (eCobrar ? ' -> ' + eCobrar.message : ''));
  const { data: pagoFila } = await svc.from('pagos_mesa').select('id').eq('cuenta_id', cuentaMeseroId).maybeSingle();
  pagoMesaId = pagoFila?.id;
  if (pagoMesaId) {
    const { error: eAnular } = await encargado.from('pagos_mesa').delete().eq('id', pagoMesaId);
    check(!eAnular, 'el encargado SI puede anular el cobro de mesa (confirmado con Gilberto)' + (eAnular ? ' -> ' + eAnular.message : ''));
  } else {
    check(false, 'no se encontro la fila de pagos_mesa para anular');
  }

  // --- Menu: el encargado SI puede editar productos/categorias ---
  const { data: prodNuevo, error: eProd } = await encargado
    .from('productos')
    .insert({ restaurante_id: REST, categoria_id: CAT_ID, nombre: 'Producto Test Encargado', precio_usd: 1, disponible: true })
    .select('id')
    .single();
  check(!eProd && !!prodNuevo?.id, 'el encargado SI puede crear un producto en el Menu' + (eProd ? ' -> ' + eProd.message : ''));
  productoTest = prodNuevo?.id;

  // --- GERENCIAL: el encargado NO puede ver estadisticas/reporte de pagos/gastos ---
  const desde = new Date(Date.now() - 60 * 60 * 1000).toISOString();
  const { error: eRend } = await encargado.rpc('rendimiento_meseros', { p_restaurante_id: REST, p_desde: desde });
  check(!!eRend, 'el encargado NO puede ver rendimiento_meseros (gerencial)');

  const { error: eRep } = await encargado.rpc('reporte_pagos', { p_restaurante_id: REST, p_desde: desde });
  check(!!eRep, 'el encargado NO puede ver reporte_pagos (gerencial)');

  const { data: gastoNuevo, error: eGasto } = await encargado
    .from('gastos_caja')
    .insert({ restaurante_id: REST, concepto: 'Test', monto_usd: 1 })
    .select('id');
  check(!!eGasto || !gastoNuevo?.length, 'el encargado NO puede insertar en gastos_caja (Caja)');

  // --- PERSONAL: el encargado NO puede administrar meseros/repartidores ---
  const { error: eMisM } = await encargado.rpc('mis_meseros');
  check(!!eMisM, 'el encargado NO puede llamar mis_meseros (gestion de personal)');

  const efRes = await encargado.functions.invoke('gestionar-mesero', {
    body: { accion: 'crear', nombre: 'x', email: 'nope@test.com', password: '123456', rol: 'staff' },
  });
  const efError = efRes.error || efRes.data?.error;
  check(!!efError, 'el encargado NO puede invocar gestionar-mesero (solo el dueño)');

  // --- CONFIGURACION: el encargado NO puede actualizar el restaurante ---
  const { error: eUpdRest, count } = await encargado
    .from('restaurantes')
    .update({ sala_promedio_min: 99 })
    .eq('id', REST)
    .select('id', { count: 'exact' });
  check(!eUpdRest && (count ?? 0) === 0, 'el encargado NO puede actualizar la configuracion del restaurante (0 filas afectadas)');

  // --- El STAFF (mesero raso) sigue SIN poder ver la mesa ajena del encargado ---
  const { data: cIdEnc } = await encargado.rpc('abrir_mesa', { p_mesa: 'TF97b', p_comensales: 1, p_modo: 'unica' });
  cuentaEncargadoId = cIdEnc;
  const { data: listaStaff } = await mesero.rpc('mis_cuentas_mesa', { p_restaurante_id: REST });
  const veMesaEncargado = (listaStaff ?? []).some((c) => c.mesa === 'TF97b');
  check(!veMesaEncargado, 'el mesero raso sigue SIN ver la mesa que abrio el encargado (aislamiento intacto)');
} catch (e) {
  console.log('  XX  Excepción: ' + e.message);
  fallos++;
} finally {
  await limpiar();
  console.log('\nLimpieza hecha (mesas, pedidos, pagos, producto y usuarios de prueba fuera)');
}

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