// PRUEBA VIVA DE LA VIGENCIA DEL COMPROBANTE DE RIF (2026-07-31)
//
// Art. 29 numeral 2 de la 000102: la imprenta solicita al emisor el
// comprobante digital del RIF VIGENTE. El RIF vence, asi que el alta guarda la
// fecha de vencimiento y la numeracion se frena para el emisor vencido, con un
// freno TRANSITORIO: nada de palabras de rechazo definitivo, porque esto se
// arregla consignando el comprobante renovado y lo encolado debe salir solo.
// De paso se comprueba de punta a punta que la emision devuelve lo del art. 7
// (fecha de asignacion, identidad de la imprenta) contra la base viva.
import { readFileSync } from 'node:fs';

const REF = 'szzhhlevtrcambcoytiz';
const PAT = readFileSync(new URL('../.sb_token', import.meta.url), 'utf8').trim();

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(`SQL ${r.status}: ${t}`);
  try { return JSON.parse(t); } catch { return t; }
}

const RIF = 'V-22606827-5';
const lit = (s) => `'${String(s).replace(/'/g, "''")}'`;

const limpiar = () => sql(`
  delete from fiscal.envios_mensuales where emisor_id in (select id from fiscal.emisores where rif = ${lit(RIF)});
  delete from fiscal.documentos 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.llaves where emisor_id in (select id from fiscal.emisores where rif = ${lit(RIF)});
  delete from fiscal.emisores where rif = ${lit(RIF)};
`);

const emitir = (llave, hash) => sql(`
  select * from public.fn_emitir_documento(${lit(llave)}, ${lit(RIF)}, 'A', 'factura', 1,
    ${lit(hash)}, now(), 100, 16, 116, '{"prueba":"vigencia"}'::jsonb, 'prueba-vigencia');
`);

try {
  await limpiar();

  console.log('\n== 0. Alta por el panel con el RIF ya vencido ==');
  await sql(`
    select public.fn_panel_imprenta('guardar_cliente', jsonb_build_object(
      'rif', ${lit(RIF)}, 'razon_social', 'Prueba Vigencia RIF', 'domicilio', 'Araure',
      'rif_comprobado', true, 'rif_vence', (current_date - 1)::text,
      'nota', 'emisor temporal de la prueba de vigencia'), 'prueba-vigencia');
  `);
  const alta = await sql(`select rif_vence, rif_comprobado from fiscal.emisores where rif = ${lit(RIF)};`);
  check(!!alta[0]?.rif_vence, `el alta guardo la fecha de vencimiento (${alta[0]?.rif_vence})`);
  const llave = (await sql(`select fiscal.crear_llave(${lit(RIF)}, 'llave de prueba') as v;`))[0].v;
  check(typeof llave === 'string' && llave.length > 10, 'y el emisor tiene su llave');

  console.log('\n== 1. Con el RIF vencido NO se asignan numeros (art. 29 num. 2) ==');
  let mensaje = '';
  try {
    await emitir(llave, 'vigencia-hash-1');
  } catch (e) {
    mensaje = e.message;
  }
  check(/vencido/i.test(mensaje), 'la emision se frena y el mensaje dice que el RIF esta vencido');
  check(!/rechaz|invalid|no acepto/i.test(mensaje), 'sin palabras de rechazo definitivo: la cola de la Estacion reintenta cuando se renueve');
  const docs0 = await sql(`select count(*)::int as n from fiscal.documentos d join fiscal.emisores e on e.id = d.emisor_id where e.rif = ${lit(RIF)};`);
  check(docs0[0]?.n === 0, 'y no quedo ningun documento numerado');

  console.log('\n== 2. El interruptor de Gustito conoce el motivo ==');
  // Sin vinculo real no se puede ver rif_vencido de punta a punta (eso pediria
  // tocar un restaurante de verdad); se comprueba que la funcion viva tiene la
  // rama y el motivo exacto.
  const rama = await sql(`select pg_get_functiondef(p.oid) ~ 'rif_vencido' as tiene
    from pg_proc p join pg_namespace n on p.pronamespace = n.oid
    where n.nspname='public' and p.proname='fn_estado_fiscal';`);
  check(rama[0]?.tiene === true, `fn_estado_fiscal responde el motivo 'rif_vencido'`);

  console.log('\n== 3. Renovado el comprobante, la numeracion fluye sola ==');
  await sql(`
    select public.fn_panel_imprenta('guardar_cliente', jsonb_build_object(
      'rif', ${lit(RIF)}, 'razon_social', 'Prueba Vigencia RIF', 'domicilio', 'Araure',
      'rif_comprobado', true, 'rif_vence', (current_date + 365)::text,
      'nota', 'emisor temporal de la prueba de vigencia'), 'prueba-vigencia');
  `);
  const ok1 = (await emitir(llave, 'vigencia-hash-1'))[0];
  check(Number.isFinite(ok1?.numero_control), `la misma venta ahora si se numera (control ${ok1?.numero_control})`);
  check(!!ok1?.fecha_asignacion, 'con su fecha de asignacion (art. 7 num. 15)');

  console.log('\n== 4. El reintento devuelve el mismo numero con su fecha original ==');
  const ok2 = (await emitir(llave, 'vigencia-hash-1'))[0];
  check(ok2?.ya_estaba === true, 'el reintento no gasta otro numero');
  check(ok2?.numero_control === ok1.numero_control, 'mismo numero de control');
  check(ok2?.fecha_asignacion === ok1.fecha_asignacion, 'misma fecha de asignacion, la original');

  console.log('\n== 5. La lista de clientes muestra el vencimiento ==');
  const lista = await sql(`select rif_vence from fiscal.clientes() where rif = ${lit(RIF)};`);
  check(!!lista[0]?.rif_vence, `fiscal.clientes() trae rif_vence (${lista[0]?.rif_vence})`);
} catch (e) {
  console.log('  XX  ' + e.message);
  fallos++;
} finally {
  await limpiar();
  const quedo = await sql(`select count(*)::int as n from fiscal.emisores where rif = ${lit(RIF)};`).catch(() => null);
  console.log(quedo?.[0]?.n === 0 ? '  OK  limpieza completa, cero rastro del emisor de prueba' : '  XX  OJO: quedo rastro del emisor de prueba');
  if (quedo?.[0]?.n !== 0) fallos++;
}

console.log(fallos === 0 ? '\nVIGENCIA DEL RIF: TODO VERDE' : `\n${fallos} FALLO(S)`);
process.exitCode = fallos === 0 ? 0 : 1; // salida natural: process.exit() con undici cerrando revienta libuv en Node 24/Windows
