// PRUEBA DEL SERIAL EN LA ESTACION (2026-07-30) — Modulo 4.
//
// El serial lo asigna la imprenta y la estacion lo aprende sola del latido.
// Aca se comprueba el lado del equipo, sin nube:
//   - guardarSerial / leerSerial: escritura atomica, relectura, sin archivo.
//   - La factura imprime el serial en el pie (como el registro de una maquina
//     fiscal); sin serial no imprime nada raro.
//   - El servidor lo muestra: /api/puente lo devuelve, la pantalla lo pinta, y
//     en practica (sin enlace) dice SIN SERIAL claro.
import { mkdtempSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { guardarSerial, leerSerial } from '../dist/config.js';
import { lineasFactura } from '../dist/factura.js';
import { iniciarServidor } from '../dist/servidor.js';
import { Acceso } from '../dist/acceso.js';

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

const dir = mkdtempSync(join(tmpdir(), 'fiscal-serial-'));
const PUERTO = 8757;
const base = `http://127.0.0.1:${PUERTO}`;
let servidor;

const CLAVE_DUENO = 'clave-del-dueno-2026';
const acceso = new Acceso(join(dir, 'estado', 'acceso.json'));
acceso.fijarClave('dueno', CLAVE_DUENO);
const LLAVE = acceso.llaveMaquina();

const asientoFalso = {
  seq: 1,
  serie: 'A',
  numero: 12,
  control: 12,
  tipo: 'factura',
  sellado_en: new Date().toISOString(),
  equipo: 'TEST',
  hash_anterior: 'x',
  hash: 'y',
  documento: {
    tipo: 'factura',
    emisor: { rif: 'J-50856106-6', razon_social: 'Arepa Power', domicilio_fiscal: 'Araure' },
    cliente: { nombre: 'Consumidor Final' },
    canal: 'caja',
    renglones: [{ nombre: 'Arepa', cantidad: 1, precio_usd: 5, alicuota: 16, base_usd: 4.31, iva_usd: 0.69, total_usd: 5 }],
    por_alicuota: [{ alicuota: 16, base_usd: 4.31, iva_usd: 0.69 }],
    base_usd: 4.31,
    iva_usd: 0.69,
    total_usd: 5,
    tasa_bs: 742,
    total_bs: 3710,
    pago: { metodo: 'efectivo' },
    origen_id: 'prueba:serial',
  },
};

try {
  console.log('\n== 1. El serial se guarda y se relee (y sin archivo, null) ==');
  check(leerSerial(dir) === null, 'una instalacion nueva no tiene serial');
  guardarSerial(dir, 'EF-00001-9');
  check(leerSerial(dir) === 'EF-00001-9', 'guardado y releido tal cual');
  guardarSerial(dir, 'EF-00002-7');
  check(leerSerial(dir) === 'EF-00002-7', 'si la imprenta lo cambia, se actualiza');

  console.log('\n== 2. La factura imprime el serial en el pie ==');
  const con = lineasFactura(asientoFalso, { numeroControl: '00000012', urlSello: 'https://sello.gustitoxpress.app/v/abc', serial: 'EF-00002-7' });
  check(con.some((l) => l.includes('Estacion EF-00002-7')), 'sale "Estacion EF-00002-7" como una maquina fiscal');
  const sin = lineasFactura(asientoFalso, { numeroControl: '00000012', urlSello: 'https://sello.gustitoxpress.app/v/abc' });
  check(!sin.some((l) => l.includes('Estacion EF')), 'sin serial, no imprime nada raro');

  console.log('\n== 3. El servidor lo muestra por todas sus caras ==');
  servidor = await iniciarServidor({ base: dir, puerto: PUERTO, log: () => {} });
  const entrar = await fetch(`${base}/entrar`, {
    method: 'POST',
    headers: { 'content-type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({ clave: CLAVE_DUENO }).toString(),
    redirect: 'manual',
  });
  const galleta = (entrar.headers.get('set-cookie') ?? '').split(';')[0];
  await fetch(`${base}/configurar`, {
    method: 'POST',
    headers: { cookie: galleta, 'content-type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      rif: 'J-50856106-6', razon_social: 'Arepa Power Restaurant', domicilio_fiscal: 'Araure',
      alicuota_general: '16', serie: 'A', equipo: 'SERIAL-01',
    }).toString(),
    redirect: 'manual',
  });
  const puente = await (await fetch(`${base}/api/puente`, { headers: { authorization: `Bearer ${LLAVE}` } })).json();
  check(puente.serial === 'EF-00002-7', `/api/puente lo devuelve (${puente.serial})`);
  const portada = await (await fetch(`${base}/`, { headers: { cookie: galleta } })).text();
  check(portada.includes('EF-00002-7'), 'la pantalla lo pinta en la identidad y el tablero');

  console.log('\n== 4. En practica (sin enlace y sin serial) se dice claro ==');
  rmSync(join(dir, 'estado', 'serial.json'), { force: true });
  const practica = await (await fetch(`${base}/`, { headers: { cookie: galleta } })).text();
  check(/SIN SERIAL/i.test(practica), 'la pantalla dice SIN SERIAL (practica)');
  const puente2 = await (await fetch(`${base}/api/puente`, { headers: { authorization: `Bearer ${LLAVE}` } })).json();
  check(puente2.serial === null, 'y el puente responde serial null, sin inventar');

  console.log(fallos === 0 ? '\nTODO EN VERDE' : `\n${fallos} FALLOS`);
} catch (e) {
  console.error('\nREVENTO:', e);
  fallos++;
} finally {
  servidor?.cerrar();
  rmSync(dir, { recursive: true, force: true });
}
// La salida va con un respiro: process.exit() en seco mientras el servidor
// termina de cerrar revienta en Windows (assert de libuv en async.c).
setTimeout(() => process.exit(fallos ? 1 : 0), 200);
