// PRUEBA VIVA DEL REGISTRO DE SUBSANACIONES (2026-07-31)
//
// Art. 33 de la 000102: la imprenta subsana sin costo los errores u omisiones.
// Se comprueba contra la base viva que el reclamo queda registrado con su
// rastro (quien lo abrio, quien lo corrigio, cuando y como), que las
// validaciones frenan lo incompleto, y que la bitacora del panel anota ambos
// movimientos. Emisor temporal, limpieza total al final.
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.subsanaciones 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.series 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 temporal ==');
  await sql(`select fiscal.guardar_cliente(${lit(RIF)}, 'Prueba Subsanaciones', 'Araure',
    null, null, null, null, 'prueba', 'A', true, 'emisor temporal de la prueba de subsanaciones');`);
  console.log('  OK  sembrado');

  console.log('\n== 1. Un reclamo sin descripcion no se registra ==');
  let error = '';
  try {
    await sql(`select public.fn_panel_imprenta('abrir_subsanacion',
      jsonb_build_object('rif', ${lit(RIF)}, 'documento', 'A-1', 'descripcion', '  '), 'prueba-subsana');`);
  } catch (e) { error = e.message; }
  check(/[Dd]escriba/.test(error), 'exige describir el error u omision');

  console.log('\n== 2. El reclamo queda abierto con su rastro ==');
  await sql(`select public.fn_panel_imprenta('abrir_subsanacion',
    jsonb_build_object('rif', ${lit(RIF)}, 'documento', '00-00000017',
      'descripcion', 'El documento salio con la razon social incompleta'), 'prueba-subsana');`);
  const lista1 = await sql(`select public.fn_panel_imprenta('subsanaciones') as v;`);
  const s = (lista1[0]?.v ?? []).find((x) => x.rif === RIF);
  check(!!s, 'aparece en el registro');
  check(s?.estado === 'abierta', 'como abierta');
  check(s?.documento === '00-00000017', 'con el documento afectado');
  check(s?.abierto_por === 'prueba-subsana', 'y quien la abrio');
  check((lista1[0]?.v ?? []).findIndex((x) => x.rif === RIF) === 0 || (lista1[0]?.v ?? [])[0]?.estado === 'abierta', 'las abiertas van de primeras');

  console.log('\n== 3. Cerrarla exige decir como se corrigio ==');
  error = '';
  try {
    await sql(`select public.fn_panel_imprenta('cerrar_subsanacion',
      jsonb_build_object('id', ${lit(s.id)}, 'resolucion', ''), 'prueba-subsana');`);
  } catch (e) { error = e.message; }
  check(/como se corrigio/i.test(error), 'sin resolucion no se cierra');

  console.log('\n== 4. Subsanada, con su rastro completo ==');
  await sql(`select public.fn_panel_imprenta('cerrar_subsanacion',
    jsonb_build_object('id', ${lit(s.id)}, 'resolucion', 'Se emitio nota de credito y factura corregida, sin costo'), 'prueba-subsana');`);
  const lista2 = await sql(`select * from fiscal.subsanaciones_lista() where rif = ${lit(RIF)};`);
  check(lista2[0]?.estado === 'subsanada', 'queda como subsanada');
  check(/sin costo/.test(lista2[0]?.resolucion ?? ''), 'con la resolucion escrita');
  check(lista2[0]?.resuelto_por === 'prueba-subsana' && !!lista2[0]?.resuelto_en, 'quien y cuando la corrigio');

  console.log('\n== 5. Una subsanacion cerrada no se cierra dos veces ==');
  error = '';
  try {
    await sql(`select public.fn_panel_imprenta('cerrar_subsanacion',
      jsonb_build_object('id', ${lit(s.id)}, 'resolucion', 'otra vez'), 'prueba-subsana');`);
  } catch (e) { error = e.message; }
  check(/ya fue cerrada|no existe/i.test(error), 'el segundo cierre rebota');

  console.log('\n== 6. La bitacora del panel anota ambos movimientos ==');
  const bitacora = await sql(`select accion from fiscal.eventos_panel
    where quien = 'prueba-subsana' and accion in ('subsanacion_abierta','subsanacion_cerrada')
    order by en desc limit 5;`);
  const acciones = bitacora.map((b) => b.accion);
  check(acciones.includes('subsanacion_abierta'), 'quedo anotada la apertura');
  check(acciones.includes('subsanacion_cerrada'), 'y el cierre');
} 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 ? '\nSUBSANACIONES: 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
