// PRUEBA VIVA DE LA SALUD DE LOS REPORTES MENSUALES (2026-07-31)
//
// Art. 29 numeral 5 de la 000102: la imprenta remite la relacion de cada mes
// dentro de los diez dias continuos siguientes. Art. 34: dejar de informar dos
// o mas periodos mensuales es causal de REVOCATORIA. La funcion
// fiscal.salud_reportes() es la que alimenta el aviso del panel; aqui se
// comprueba contra la base viva, con un emisor de prueba que se limpia al
// final:
//   1. Un mes cerrado con documentos y sin remitir, pasada la fecha, sale VENCIDO.
//   2. El mes en curso NO aparece (todavia no se puede reportar).
//   3. Al marcar el periodo como remitido, deja de estar vencido.
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; }
}

// RIF real con digito verificador valido, distinto al del emprendimiento.
// Es el mismo temporal que usan las otras suites vivas; se borra al final.
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)};
`);

try {
  await limpiar();

  console.log('\n== 0. Siembra: un emisor con un mes viejo sin reportar ==');
  // Por la puerta canonica del alta: el serial con su digito verificador lo
  // asigna la propia imprenta, no se inventa a mano.
  await sql(`
    select fiscal.guardar_cliente(${lit(RIF)}, 'Prueba Salud Reportes', 'Acarigua',
      null, null, null, null, 'prueba', 'A', true, 'emisor temporal de la prueba de salud de reportes');
  `);
  // Un documento en la MITAD de hace dos meses (siempre vencido, corra el dia
  // que corra la prueba: su fecha limite fue el 10 del mes pasado) y otro en el
  // mes en curso (que no debe aparecer).
  await sql(`
    insert into fiscal.documentos (emisor_id, serie, tipo, numero_documento, numero_control, token, hash_documento, fecha_emision, base_bs, iva_bs, total_bs, documento, recibido_en)
    select e.id, 'A', 'factura', 999901, 999901, 'salud-token-1', 'salud-hash-1',
           now(), 100, 16, 116, '{}'::jsonb,
           ((date_trunc('month', now() at time zone 'America/Caracas') - interval '45 days') at time zone 'America/Caracas')
      from fiscal.emisores e where e.rif = ${lit(RIF)};
    insert into fiscal.documentos (emisor_id, serie, tipo, numero_documento, numero_control, token, hash_documento, fecha_emision, base_bs, iva_bs, total_bs, documento, recibido_en)
    select e.id, 'A', 'factura', 999902, 999902, 'salud-token-2', 'salud-hash-2',
           now(), 200, 32, 232, '{}'::jsonb, now()
      from fiscal.emisores e where e.rif = ${lit(RIF)};
  `);
  console.log('  OK  sembrado');

  console.log('\n== 1. El mes viejo sin remitir sale VENCIDO ==');
  const salud1 = await sql(`select * from fiscal.salud_reportes() where rif = ${lit(RIF)};`);
  check(salud1.length === 1, `aparece UN solo periodo (${salud1.length}): el mes en curso no se reporta todavia`);
  const p = salud1[0];
  check(p?.documentos === 1, `con su documento contado (${p?.documentos})`);
  check(p?.reportado === false, 'sin remitir');
  check(p?.vencido === true, 'y VENCIDO: paso el dia 10 del mes siguiente (art. 29)');

  console.log('\n== 2. La accion del panel responde lo mismo ==');
  const porPanel = await sql(`select public.fn_panel_imprenta('salud_reportes') as v;`);
  const fila = (porPanel[0]?.v ?? []).find((x) => x.rif === RIF);
  check(!!fila && fila.vencido === true, 'el despachador del panel trae el periodo vencido');

  console.log('\n== 2b. La pestaña del reporte llama por su nombre y le responden ==');
  // Bug vivo cazado por esta prueba: la pantalla llama 'resumen_mensual' y
  // 'relacion_mensual', y el despachador solo conocia 'resumen' y 'relacion'.
  const resumen = await sql(`select public.fn_panel_imprenta('resumen_mensual',
    jsonb_build_object('rif', ${lit(RIF)}, 'anio', ${p.anio}, 'mes', ${p.mes})) as v;`);
  check(resumen[0]?.v?.documentos === 1, `'resumen_mensual' responde el periodo (${resumen[0]?.v?.documentos} documento)`);
  const relacion = await sql(`select public.fn_panel_imprenta('relacion_mensual',
    jsonb_build_object('rif', ${lit(RIF)}, 'anio', ${p.anio}, 'mes', ${p.mes})) as v;`);
  check(Array.isArray(relacion[0]?.v) && relacion[0].v.length === 1, `'relacion_mensual' responde la lista (${relacion[0]?.v?.length} fila)`);
  check(!!relacion[0]?.v?.[0]?.fecha_asignacion, 'y cada fila trae la fecha de asignacion del control (art. 32)');
  // Cada accion tiene UN solo nombre, el que usa la pantalla. Los alias cortos
  // se quitaron: tener dos nombres para lo mismo fue justo lo que dejo pasar el
  // desajuste sin que nadie lo notara. Quien vela por eso ahora es
  // scripts/test_acciones_panel.mjs, que compara las dos listas.
  let rebotoElCorto = false;
  try {
    await sql(`select public.fn_panel_imprenta('resumen',
      jsonb_build_object('rif', ${lit(RIF)}, 'anio', ${p.anio}, 'mes', ${p.mes})) as v;`);
  } catch { rebotoElCorto = true; }
  check(rebotoElCorto, `el nombre viejo 'resumen' ya no existe (un solo nombre por accion)`);

  console.log('\n== 2c. El tablero cuenta el mismo vencido ==');
  const tab = await sql(`select public.fn_panel_imprenta('tablero') as v;`);
  check((tab[0]?.v?.periodos_sin_reportar ?? 0) >= 1, `periodos_sin_reportar del tablero lo incluye (${tab[0]?.v?.periodos_sin_reportar})`);

  console.log('\n== 3. Marcar el periodo como remitido lo saca del rojo ==');
  await sql(`select fiscal.marcar_enviado(${lit(RIF)}, ${p.anio}, ${p.mes}, 'prueba-salud', 'remision de prueba');`);
  const salud2 = await sql(`select * from fiscal.salud_reportes() where rif = ${lit(RIF)};`);
  check(salud2[0]?.reportado === true, 'queda como remitido');
  check(salud2[0]?.vencido === false, 'y ya no esta vencido');
} 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 ? '\nSALUD DE REPORTES: 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
