// DE CUAL IMPRENTA SALIO ESTE NUMERO (2026-07-30).
//
// Gilberto preguntó si el proveedor de respaldo lo vería raro el SENIAT en la
// evaluación. El respaldo en si no es raro (cambiar de imprenta autorizada es
// derecho del contribuyente, y solo una emite a la vez), pero al revisarlo
// aparecio un hueco de verdad: el registro de envio guardaba el numero de
// control SIN decir que imprenta lo asigno. Con dos proveedores configurados,
// un fiscal pregunta "de donde salio este numero" y no habia con que responder.
// Eso es el articulo 3 de la 000121: trazabilidad.
//
// Aca se comprueba que cada documento queda amarrado a su imprenta, y que eso
// llega al reporte y al CSV que se lleva el funcionario.
import { mkdtempSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { LibroFiscal } from '../dist/libro.js';
import { ColaTransmision } from '../dist/cola.js';
import { Auditor } from '../dist/auditor.js';
import { Bitacora } from '../dist/bitacora.js';
import { armarDocumento } from '../dist/armador.js';

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

const dir = mkdtempSync(join(tmpdir(), 'fiscal-traza-'));
const emisor = { rif: 'J-50856106-6', razon_social: 'Arepa Power', domicilio_fiscal: 'Araure', precios_con_iva: true };
const venta = (id) => ({
  origen_id: id,
  canal: 'caja',
  cliente: { nombre: 'Consumidor final' },
  renglones: [{ nombre: 'Arepa', cantidad: 1, precio_usd: 5, alicuota: 16 }],
  tasa_bs: 742.23,
  pago: { metodo: 'efectivo' },
});

/** Dos imprentas de mentira, cada una con su nombre y su numeracion. */
const imprentaFalsa = (nombre, prefijo) => ({
  nombre,
  real: true,
  n: 0,
  async emitir(asiento) {
    this.n += 1;
    return {
      numeroControl: `${prefijo}-${String(this.n).padStart(6, '0')}`,
      numeroDocumento: String(asiento.numero),
      fechaAsignacion: new Date().toISOString(),
    };
  },
});

try {
  const libro = new LibroFiscal({ ruta: join(dir, 'libro.jsonl'), serie: 'A', equipo: 'TRAZA-01' });
  const bitacora = new Bitacora(join(dir, 'bitacora.jsonl'));
  const principal = imprentaFalsa('Imprenta Principal C.A.', 'PRIN');
  const respaldo = imprentaFalsa('Imprenta de Respaldo C.A.', 'RESP');

  console.log('\n== 1. Con la principal: el documento queda amarrado a ella ==');
  const cola1 = new ColaTransmision({ ruta: join(dir, 'transmision.jsonl'), imprenta: principal });
  const a1 = libro.asentar('factura', armarDocumento(venta('v-1'), emisor));
  await cola1.encolar(a1);
  const r1 = cola1.ver(a1.seq);
  check(r1?.estado === 'enviado', 'la principal lo emitio');
  check(r1?.imprenta === 'Imprenta Principal C.A.', `y quedo escrito con cual (${r1?.imprenta})`);
  check(r1?.numeroControl?.startsWith('PRIN'), `con su numero de control (${r1?.numeroControl})`);

  console.log('\n== 2. Se pasa al respaldo (a mano) y el siguiente lo dice ==');
  bitacora.anotar('Dueño', 'local', 'imprenta_cambiada', { de: principal.nombre, a: respaldo.nombre });
  const cola2 = new ColaTransmision({ ruta: join(dir, 'transmision.jsonl'), imprenta: respaldo });
  const a2 = libro.asentar('factura', armarDocumento(venta('v-2'), emisor));
  await cola2.encolar(a2);
  const r2 = cola2.ver(a2.seq);
  check(r2?.imprenta === 'Imprenta de Respaldo C.A.', `el segundo salio del respaldo (${r2?.imprenta})`);
  check(r2?.numeroControl?.startsWith('RESP'), `con la numeracion de esa imprenta (${r2?.numeroControl})`);

  console.log('\n== 3. Lo emitido antes NO se reescribe ==');
  const r1b = cola2.ver(a1.seq);
  check(r1b?.imprenta === 'Imprenta Principal C.A.', 'el primero sigue diciendo que lo emitio la principal');
  check(r1b?.numeroControl?.startsWith('PRIN'), 'y conserva su numero de control original');

  console.log('\n== 4. La numeracion del LIBRO no se entera del cambio ==');
  check(a1.numero === 1 && a2.numero === 2, 'los correlativos siguen consecutivos (1, 2)');
  check(a2.control === a1.control + 1, 'y el numero de control interno tampoco salta');

  console.log('\n== 5. El fiscal lo ve en su consulta y en su CSV ==');
  const aud = new Auditor({ libro, bitacora, cola: cola2, quien: 'fiscal', desde: 'prueba' });
  const desde = new Date('2000-01-01');
  const hasta = new Date('2999-12-31');
  const filas = aud.reporte(desde, hasta);
  check(filas[0].imprenta === 'Imprenta Principal C.A.' && filas[1].imprenta === 'Imprenta de Respaldo C.A.',
    'el reporte dice de cual imprenta salio cada documento');
  const csv = aud.exportarCsv(desde, hasta);
  check(csv.split('\n')[0].includes('imprenta'), 'el CSV lleva su columna');
  check(csv.includes('Imprenta de Respaldo C.A.'), 'y el dato adentro');

  console.log('\n== 6. El cambio quedo en la bitacora, encadenado ==');
  const eventos = bitacora.todos();
  const cambio = eventos.find((e) => e.accion === 'imprenta_cambiada');
  check(!!cambio, 'consta quien cambio de imprenta');
  check(cambio?.detalle?.a === 'Imprenta de Respaldo C.A.', 'con el proveedor al que se paso');
  check(bitacora.verificar().integro, 'y la bitacora sigue integra');

  console.log(fallos === 0 ? '\nTODO EN VERDE' : `\n${fallos} FALLOS`);
} catch (e) {
  console.error('\nREVENTO:', e);
  fallos++;
} finally {
  rmSync(dir, { recursive: true, force: true });
}
process.exit(fallos ? 1 : 0);
