// Verificacion del COBRO DE MESA + roles (efectivo vs electronico) contra la BD viva.
// Modelo: el mesero registra cualquier metodo; EFECTIVO cierra de una, ELECTRONICO
// del mesero queda "por revisar" y solo el DUEÑO (panel) lo verifica y libera.
// Demo, mesas T70/T71, un mesero (staff) y un dueño. 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').eq('restaurante_id', REST).eq('disponible', true).limit(1);
const PROD_ID = prods[0].id;

const CLAVE = 'PagoTest2026!';
const EMAIL_MES = 'mesero.test.pago@gustitoxpress.app';
const EMAIL_DUE = 'dueno.test.pago@gustitoxpress.app';
let meseroUid, duenoUid;
const limpiar = async () => {
  for (const mesa of ['T70', 'T71']) {
    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);
    }
  }
  if (meseroUid) await svc.auth.admin.deleteUser(meseroUid).catch(() => {});
  if (duenoUid) await svc.auth.admin.deleteUser(duenoUid).catch(() => {});
};

const pedir = async (cli, mesa, cant, comensalId) => {
  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_ID, cantidad: cant, _c: mesa + (comensalId ?? '') + cant }],
    p_mesa: mesa, p_comensal_id: comensalId,
  });
  if (error) throw new Error('crear_pedido: ' + error.message);
  return data[0];
};

try {
  await limpiar();
  const { data: um } = await svc.auth.admin.createUser({ email: EMAIL_MES, password: CLAVE, email_confirm: true });
  meseroUid = um.user.id;
  await svc.from('perfiles').upsert({ id: meseroUid, rol: 'staff', restaurante_id: REST, nombre: 'Pago Mesero' });
  const { data: ud } = await svc.auth.admin.createUser({ email: EMAIL_DUE, password: CLAVE, email_confirm: true });
  duenoUid = ud.user.id;
  await svc.from('perfiles').upsert({ id: duenoUid, rol: 'dueno', restaurante_id: REST, nombre: 'Pago Dueno' });

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

  // ===== Mesa T70: cliente paga su parte en linea + mesero cierra en efectivo =====
  const { data: cta70 } = await mesero.rpc('abrir_mesa', { p_mesa: 'T70', p_comensales: 2, p_modo: 'separada', p_nombres: ['Pedro', 'Ana'] });
  const { data: coms } = await svc.from('comensales_mesa').select('id,nombre').eq('cuenta_id', cta70);
  const pedroId = coms.find((c) => c.nombre === 'Pedro').id;
  const anaId = coms.find((c) => c.nombre === 'Ana').id;
  const rPedro = await pedir(mesero, 'T70', 2, pedroId);
  await pedir(mesero, 'T70', 1, anaId);
  const { data: pPedro } = await svc.from('pedidos').select('total_usd').eq('id', rPedro.pedido_id).maybeSingle();

  const { data: pago1 } = await anon.rpc('pagar_parte_cliente', { p_cuenta_id: cta70, p_comensal_id: pedroId, p_metodo: 'pago_movil', p_referencia: '1234' });
  const pagoPedro = pago1[0].pago_id;
  check(!!pagoPedro, 'Cliente paga su parte en linea (por revisar)');
  const { error: eMesVer } = await mesero.rpc('verificar_pago_cliente', { p_pago_id: pagoPedro, p_ok: true });
  check(!!eMesVer, 'El MESERO no puede verificar pagos (' + (eMesVer?.message ?? 'sin error!') + ')');
  const { error: eAnonVer } = await anon.rpc('verificar_pago_cliente', { p_pago_id: pagoPedro, p_ok: true });
  check(!!eAnonVer, 'El cliente tampoco verifica');
  const { error: eDueVer } = await dueno.rpc('verificar_pago_cliente', { p_pago_id: pagoPedro, p_ok: true });
  check(!eDueVer, 'El DUEÑO verifica la parte de Pedro' + (eDueVer ? ' -> ' + eDueVer.message : ''));
  const { data: cta70a } = await svc.from('cuentas_mesa').select('estado').eq('id', cta70).maybeSingle();
  check(cta70a?.estado !== 'cerrada', 'La mesa sigue abierta (falta Ana)');

  const { data: cerr70 } = await mesero.rpc('cobrar_y_cerrar_mesa', { p_cuenta_id: cta70, p_metodo: 'efectivo', p_propina: 5 });
  check(cerr70?.[0]?.cerrada === true, 'Mesero cobra el resto en EFECTIVO y la mesa se CIERRA de una');
  const { data: pagos70 } = await svc.from('pagos_mesa').select('metodo,verificado,monto_usd,propina_usd').eq('cuenta_id', cta70);
  check((pagos70 ?? []).some((p) => p.metodo === 'efectivo' && p.verificado), 'Quedo registrado el pago en efectivo');
  check((pagos70 ?? []).some((p) => Number(p.propina_usd) === 5), 'La propina de $5 quedo registrada en el pago');
  const { data: peds70 } = await svc.from('pedidos').select('estado').eq('cuenta_id', cta70).neq('estado', 'cancelado');
  check((peds70 ?? []).length > 0 && (peds70 ?? []).every((p) => p.estado === 'entregado'), 'Al cerrar, los pedidos de mesa quedan ENTREGADO (cuentan como venta)');

  // Rendimiento por mesero: el dueño ve al mesero con ventas y la propina; el mesero NO puede.
  const { data: rendMes } = await dueno.rpc('rendimiento_meseros', { p_restaurante_id: REST });
  const filaMes = (rendMes ?? []).find((r) => r.mesero_id === meseroUid);
  check(!!filaMes && Number(filaMes.ventas_usd) > 0, 'rendimiento_meseros: el dueño ve ventas del mesero' + (filaMes ? ` ($${filaMes.ventas_usd})` : ' (no aparece!)'));
  check(!!filaMes && Number(filaMes.propinas_usd) >= 5, 'rendimiento_meseros: la propina del mesero aparece');
  const { error: eRendMes } = await mesero.rpc('rendimiento_meseros', { p_restaurante_id: REST });
  check(!!eRendMes, 'rendimiento_meseros: un mesero NO puede consultarlo (solo dueño)');

  // ===== Mesa T71: mesero registra ELECTRONICO -> por revisar -> dueño libera =====
  const { data: cta71 } = await mesero.rpc('abrir_mesa', { p_mesa: 'T71', p_comensales: 1, p_modo: 'unica' });
  await pedir(mesero, 'T71', 1, null);
  const { data: cerr71 } = await mesero.rpc('cobrar_y_cerrar_mesa', { p_cuenta_id: cta71, p_metodo: 'pago_movil', p_referencia: '9876' });
  check(cerr71?.[0]?.cerrada === false, 'Mesero registra pago MOVIL: NO cierra (queda por revisar)');
  const pagoT71 = cerr71[0].pago_id;
  const { data: cta71a } = await svc.from('cuentas_mesa').select('estado').eq('id', cta71).maybeSingle();
  check(cta71a?.estado !== 'cerrada', 'La mesa sigue abierta esperando al panel');
  const { data: revList } = await dueno.rpc('pagos_por_revisar', { p_restaurante_id: REST });
  check((revList ?? []).some((r) => r.pago_id === pagoT71), 'El pago aparece "por revisar" en el panel');
  const { error: eVer71 } = await dueno.rpc('verificar_pago_cliente', { p_pago_id: pagoT71, p_ok: true });
  check(!eVer71, 'El DUEÑO verifica el pago electronico' + (eVer71 ? ' -> ' + eVer71.message : ''));
  const { data: cta71b } = await svc.from('cuentas_mesa').select('estado').eq('id', cta71).maybeSingle();
  check(cta71b?.estado === 'cerrada', 'Al verificar, la mesa se LIBERA (se cierra)');
} catch (e) {
  console.log('  XX  Excepción: ' + e.message);
  fallos++;
} finally {
  await limpiar();
  console.log('\nLimpieza hecha');
}

console.log(fallos === 0 ? '\nCOBRO DE MESA + ROLES OK' : `\nCOBRO DE MESA + ROLES: ${fallos} FALLO(S)`);
process.exit(fallos === 0 ? 0 : 1);
