// EL RIF DEL COMPRADOR AL COBRAR (2026-07-29)
//
// Bloque 2 del plan: la BD ya sabia guardar los datos del comprador
// (`guardar_datos_fiscales`), pero no habia pantalla. Esta prueba cubre lo que
// esa pantalla llama, contra la base viva:
//
//   - Si el negocio no esta habilitado por la imprenta, no se guarda nada (y
//     por eso el bloque ni siquiera aparece en la app).
//   - Un RIF con el digito verificador malo se rechaza con mensaje claro.
//   - Un RIF bueno queda guardado en el pedido y en la cuenta de mesa.
//   - Una vez sellado el documento, NO se le cambian los datos al comprador:
//     eso se corrige con nota de credito, no editando la venta.
//
// Limpia todo lo que crea.
import { readFileSync } from 'node:fs';

const REF = 'szzhhlevtrcambcoytiz';
const PAT = readFileSync(new URL('../.sb_token', import.meta.url), 'utf8').trim();
const RIF = 'V-22606827-5'; // RIF real de prueba, distinto al del emprendimiento
const RIF_CLIENTE = 'J-50856106-6'; // el que "pide factura"

let fallos = 0;
const check = (cond, msg) => {
  console.log((cond ? '  OK  ' : '  XX  ') + msg);
  if (!cond) fallos++;
};

async function sql(query) {
  const r = await fetch(`https://api.supabase.com/v1/projects/${REF}/database/query`, {
    method: 'POST',
    headers: { Authorization: `Bearer ${PAT}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ query }),
  });
  const t = await r.text();
  if (!r.ok) throw new Error(t.slice(0, 400));
  return JSON.parse(t);
}
const uno = async (q) => (await sql(q))[0];
const lit = (s) => `'${String(s).replace(/'/g, "''")}'`;
// Llama la RPC y devuelve el mensaje de error, o null si salio bien.
async function guardar(tipo, id, rif, razon) {
  try {
    await sql(`select public.guardar_datos_fiscales(${lit(tipo)}, ${lit(id)}, ${lit(rif)}, ${lit(razon ?? 'Cliente de prueba')}, null, null)`);
    return null;
  } catch (e) {
    const m = String(e.message).match(/"message":"([^"]+)"/);
    return m ? m[1] : String(e.message).slice(0, 120);
  }
}

let REST = null;
const limpiar = async () => {
  if (REST) {
    await sql(`delete from fiscal.cola_gustito where restaurante_id = ${lit(REST)};
               delete from fiscal.negocios where restaurante_id = ${lit(REST)};
               delete from public.pedidos where restaurante_id=${lit(REST)} and codigo like 'RIFTEST%';
               delete from public.cuentas_mesa where restaurante_id=${lit(REST)} and mesa = 'RIF01';
               update public.restaurantes set rif=null, razon_social=null, domicilio_fiscal=null where id=${lit(REST)};`);
  }
  await sql(`delete from fiscal.llaves where emisor_id in (select id from fiscal.emisores where rif=${lit(RIF)});
             delete from fiscal.series where emisor_id in (select id from fiscal.emisores where rif=${lit(RIF)});
             delete from fiscal.emisores where rif=${lit(RIF)};`);
};

try {
  const rest = await uno(`select id from public.restaurantes where slug='demo-gustito'`);
  if (!rest) throw new Error('No existe el restaurante demo');
  REST = rest.id;
  await limpiar();

  const p = await uno(`insert into public.pedidos (restaurante_id, codigo, cliente_nombre, cliente_telefono,
      tipo_entrega, estado, subtotal_usd, total_usd, tasa_bs, metodo_pago)
    values (${lit(REST)}, 'RIFTEST-1', 'Cliente', '0', 'pickup', 'recibido', 10, 10, 742.23, 'efectivo')
    returning id`);
  const c = await uno(`insert into public.cuentas_mesa (restaurante_id, mesa, estado, modo_cuenta)
    values (${lit(REST)}, 'RIF01', 'abierta', 'unica') returning id`);

  console.log('\n== 1. Sin habilitar, no se guarda nada ==');
  const apagado = (await uno(`select public.fn_estado_fiscal(${lit(REST)}) as e`)).e;
  check(apagado.activa === false, `la facturacion esta apagada (${apagado.motivo})`);
  const sinHabilitar = await guardar('pedido', p.id, RIF_CLIENTE);
  check(/no esta habilitado/i.test(sinHabilitar ?? ''), `y rebota con su motivo ("${(sinHabilitar ?? '').slice(0, 45)}...")`);

  console.log('\n== 2. La imprenta habilita al negocio ==');
  await sql(`select fiscal.guardar_cliente(${lit(RIF)}, 'Restaurante de prueba', 'Araure, Portuguesa',
              null, null, null, null, 'Gustito Xpress', 'A', true, null);
             select fiscal.vincular_negocio(${lit(REST)}, ${lit(RIF)}, 'A', 'prueba', null);
             select fiscal.crear_llave(${lit(RIF)}, 'estacion de prueba');`);
  const encendido = (await uno(`select public.fn_estado_fiscal(${lit(REST)}) as e`)).e;
  check(encendido.activa === true, 'queda habilitado, que es cuando la app muestra el campo');

  console.log('\n== 3. Un RIF malo se rechaza con mensaje claro ==');
  const malo = await guardar('pedido', p.id, 'J-12345678-9');
  check(/no es valido/i.test(malo ?? ''), `avisa del digito verificador ("${(malo ?? '').slice(0, 50)}...")`);
  const vacioAun = await uno(`select cliente_rif from public.pedidos where id=${lit(p.id)}`);
  check(vacioAun.cliente_rif === null, 'y no deja nada a medias guardado');

  console.log('\n== 4. Un RIF bueno queda guardado ==');
  const bueno = await guardar('pedido', p.id, RIF_CLIENTE, 'Comercializadora de prueba');
  check(bueno === null, 'el pedido acepta los datos del comprador');
  const guardado = await uno(`select cliente_rif, cliente_razon_social from public.pedidos where id=${lit(p.id)}`);
  check(guardado.cliente_rif === RIF_CLIENTE, `con el RIF normalizado (${guardado.cliente_rif})`);
  check(guardado.cliente_razon_social === 'Comercializadora de prueba', 'y su razon social');
  // Se acepta escrito de cualquier forma: la BD lo normaliza.
  await guardar('pedido', p.id, 'j508561066', 'Otra vez');
  const normalizado = await uno(`select cliente_rif from public.pedidos where id=${lit(p.id)}`);
  check(normalizado.cliente_rif === RIF_CLIENTE, `escrito sin guiones queda igual de bien (${normalizado.cliente_rif})`);

  console.log('\n== 5. La mesa tambien ==');
  const enMesa = await guardar('cuenta', c.id, RIF_CLIENTE, 'Comercializadora de prueba');
  check(enMesa === null, 'la cuenta de mesa acepta los datos');
  const mesaGuardada = await uno(`select cliente_rif from public.cuentas_mesa where id=${lit(c.id)}`);
  check(mesaGuardada.cliente_rif === RIF_CLIENTE, 'y quedan pegados a la cuenta, no al pedido suelto');

  console.log('\n== 6. Sellado el documento, los datos no se tocan mas ==');
  // Se simula que la Estacion ya sello esa venta.
  await sql(`insert into fiscal.cola_gustito (emisor_id, restaurante_id, tipo, origen_id, estado, sellado_en)
             select e.id, ${lit(REST)}, 'pedido', ${lit(p.id)}, 'sellado', now()
               from fiscal.emisores e where e.rif=${lit(RIF)}
             on conflict (tipo, origen_id) do update set estado='sellado'`);
  const yaSellado = await guardar('pedido', p.id, 'V-22606827-5', 'Se arrepintio');
  check(/nota de credito/i.test(yaSellado ?? ''), `manda a hacer nota de credito ("${(yaSellado ?? '').slice(0, 55)}...")`);
  const intacto = await uno(`select cliente_rif from public.pedidos where id=${lit(p.id)}`);
  check(intacto.cliente_rif === RIF_CLIENTE, 'y el documento emitido conserva a quien salio');
} catch (e) {
  console.log('  XX  ' + String(e).slice(0, 250));
  fallos++;
} finally {
  await limpiar();
}

console.log(fallos === 0 ? '\nEL RIF AL COBRAR: TODO VERDE' : `\n${fallos} FALLO(S)`);
process.exit(fallos === 0 ? 0 : 1);
