// Verificacion end-to-end contra la BD local viva.
// Ejercita el ciclo completo: comensal crea -> dueno gestiona -> repartidor entrega,
// probando RPCs, calculo de precios server-side y aislamiento RLS.
import { createClient } from '@supabase/supabase-js';

const URL = process.env.VITE_SUPABASE_URL || 'http://127.0.0.1:54321';
const ANON =
  process.env.VITE_SUPABASE_ANON_KEY || process.env.SUPABASE_ANON_KEY || '';
const REST = '11111111-1111-1111-1111-111111111111';

let fallos = 0;
function ok(msg) {
  console.log('  OK  ' + msg);
}
function check(cond, msg) {
  if (cond) ok(msg);
  else {
    console.log('  XX  ' + msg);
    fallos++;
  }
}
const nuevo = () => createClient(URL, ANON, { auth: { persistSession: false } });

// 1) Comensal (anon) lee el menu
const anon = nuevo();
const { data: rest } = await anon.from('restaurantes').select('*').eq('slug', 'la-esquina').maybeSingle();
check(rest?.id === REST, 'Comensal anon lee el restaurante por slug');
const { data: prods } = await anon.from('productos').select('*').eq('restaurante_id', REST).eq('disponible', true);
check((prods?.length ?? 0) >= 3, `Comensal anon lee productos disponibles (${prods?.length})`);

// 2) Comensal crea un pedido (precios calculados en el servidor)
const p1 = prods[0]; // 3.50
const p2 = prods[1]; // 5.00
const items = [
  { producto_id: p1.id, cantidad: 2 },
  { producto_id: p2.id, cantidad: 1 },
];
const esperadoSub = p1.precio_usd * 2 + p2.precio_usd * 1;
const { data: creado, error: eCrear } = await anon.rpc('crear_pedido', {
  p_restaurante_id: REST,
  p_cliente_nombre: 'Cliente Prueba',
  p_cliente_telefono: '04141234567',
  p_tipo_entrega: 'delivery',
  p_metodo_pago: 'pago_movil',
  p_items: items,
  p_direccion: 'Av. Principal, casa 5, Acarigua',
});
check(!eCrear && creado?.[0]?.pedido_id, 'Comensal crea pedido via RPC ' + (eCrear?.message ?? ''));
const pedidoId = creado?.[0]?.pedido_id;
const codigo = creado?.[0]?.codigo;
ok('Codigo de pedido: ' + codigo);

// 3) RLS: el comensal anon NO puede leer la tabla pedidos directamente
const { data: fuga } = await anon.from('pedidos').select('*');
check((fuga?.length ?? 0) === 0, 'RLS: anon NO ve la tabla pedidos (0 filas)');

// 4) Comensal consulta su pedido por RPC de seguimiento (campos seguros)
const { data: seg1 } = await anon.rpc('pedido_seguimiento', { p_pedido_id: pedidoId });
const s1 = seg1?.[0];
check(s1?.estado === 'recibido', 'Seguimiento: estado inicial "recibido"');
const esperadoTotal = esperadoSub + rest.costo_delivery_usd;
check(
  Number(s1?.total_usd) === Number(esperadoTotal),
  `Precio server-side correcto: total ${s1?.total_usd} == ${esperadoTotal} (subtotal ${esperadoSub} + delivery ${rest.costo_delivery_usd})`,
);

// 5) Dueno inicia sesion y gestiona
const dueno = nuevo();
const { error: eLogin } = await dueno.auth.signInWithPassword({
  email: 'dueno@laesquina.com',
  password: 'Dueno1234',
});
check(!eLogin, 'Dueno inicia sesion ' + (eLogin?.message ?? ''));
const { data: pedDueno } = await dueno.from('pedidos').select('*, pagos(*)').eq('id', pedidoId).maybeSingle();
check(!!pedDueno, 'Dueno ve el pedido (RLS permite a su restaurante)');
const pagoId = pedDueno?.pagos?.[0]?.id;
const { error: ePago } = await dueno.rpc('confirmar_pago', { p_pago_id: pagoId, p_estado: 'confirmado' });
check(!ePago, 'Dueno confirma el pago');

for (const st of ['confirmado', 'preparando', 'listo']) {
  const { error } = await dueno.rpc('cambiar_estado_pedido', { p_pedido_id: pedidoId, p_nuevo_estado: st });
  check(!error, `Dueno cambia estado -> ${st} ${error?.message ?? ''}`);
}

// transicion invalida debe fallar
const { error: eInv } = await dueno.rpc('cambiar_estado_pedido', {
  p_pedido_id: pedidoId,
  p_nuevo_estado: 'recibido',
});
check(!!eInv, 'Transicion invalida (listo -> recibido) es rechazada');

const { data: reps } = await dueno.from('repartidores').select('*').eq('restaurante_id', REST);
const repId = reps?.[0]?.id;
const { error: eAsig } = await dueno.rpc('asignar_repartidor', {
  p_pedido_id: pedidoId,
  p_repartidor_id: repId,
});
check(!eAsig, 'Dueno asigna repartidor');

// 6) Repartidor inicia sesion y entrega
const rep = nuevo();
const { error: eLoginR } = await rep.auth.signInWithPassword({
  email: 'repartidor@laesquina.com',
  password: 'Moto1234',
});
check(!eLoginR, 'Repartidor inicia sesion');
const { data: misPed } = await rep.from('pedidos').select('*').in('estado', ['listo', 'en_camino']);
check((misPed?.length ?? 0) === 1, `Repartidor ve solo su pedido asignado (RLS) (${misPed?.length})`);

const { error: eEnvia } = await rep.rpc('actualizar_ubicacion_repartidor', { p_lat: 9.561, p_lng: -69.203 });
check(!eEnvia, 'Repartidor persiste snapshot de ubicacion');

for (const st of ['en_camino', 'entregado']) {
  const { error } = await rep.rpc('cambiar_estado_pedido', { p_pedido_id: pedidoId, p_nuevo_estado: st });
  check(!error, `Repartidor cambia estado -> ${st} ${error?.message ?? ''}`);
}

// 7) Seguimiento final
const { data: seg2 } = await anon.rpc('pedido_seguimiento', { p_pedido_id: pedidoId });
const s2 = seg2?.[0];
check(s2?.estado === 'entregado', 'Seguimiento final: "entregado"');
check(
  Number(s2?.repartidor_latitud) === 9.561 && Number(s2?.repartidor_longitud) === -69.203,
  'Seguimiento expone la ultima ubicacion del repartidor',
);

// 8) Seguridad: un repartidor no puede confirmar pagos
const { error: eHack } = await rep.rpc('confirmar_pago', { p_pago_id: pagoId, p_estado: 'rechazado' });
check(!!eHack, 'Repartidor NO puede confirmar/rechazar pagos (sin permiso)');

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