// PRUEBA DEL PUENTE CON GUSTITO (2026-07-29)
//
// La puerta /api/venta ahora recibe tambien la venta CRUDA de Gustito (la misma
// forma que viaja por la cola de la nube: {tipo, origen_id, venta:{...}}). La
// convierte adentro con el MISMO conversor de la via nube: la alicuota la pone
// la Estacion, no el programa del negocio.
//
// Lo que se comprueba:
//   - /api/puente: el apreton de manos (llave buena dice a que negocio le
//     hablas; llave mala, 401 sin pistas).
//   - Venta cruda tipo 'pedido' se sella y numera.
//   - La MISMA venta otra vez (el reintento del puente, o la cola de la nube
//     llegando despues) devuelve el documento que ya existe: cero duplicados.
//   - Venta cruda tipo 'cuenta' (mesa con propina) se sella aparte.
//   - La forma vieja (VentaEntrante con alicuota) sigue andando: es la de los
//     administrativos de terceros que siguen la guia.
import { mkdtempSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
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-puente-'));
const PUERTO = 8752;
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();

let galleta = '';
const conSesion = (extra = {}) => ({ cookie: galleta, ...extra });
const conLlave = (extra = {}) => ({ authorization: `Bearer ${LLAVE}`, ...extra });

async function entrar(rol, clave) {
  const r = await fetch(`${base}/entrar`, {
    method: 'POST',
    headers: { 'content-type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({ rol, clave }).toString(),
    redirect: 'manual',
  });
  const set = r.headers.get('set-cookie');
  if (set) galleta = set.split(';')[0];
  return r.status;
}

/** La venta tal como la manda el Cerebrito (y la cola de la nube). */
const cruda = (tipo, origenId, extra = {}) => ({
  tipo,
  origen_id: origenId,
  venta: {
    codigo: tipo === 'cuenta' ? 'MESA-3' : 'AP-L0001',
    fecha: new Date().toISOString(),
    tipo_entrega: tipo === 'cuenta' ? 'mesa' : 'pickup',
    mesa: tipo === 'cuenta' ? '3' : null,
    metodo_pago: 'efectivo',
    origen: tipo === 'cuenta' ? null : 'caja',
    tasa_bs: 742.23,
    total_usd: 12,
    costo_delivery_usd: 0,
    comprador: { nombre: null, rif: null, razon_social: null, direccion: null, correo: null, telefono: null },
    renglones: [
      { nombre: 'Arepa', cantidad: 2, precio_usd: 5 },
      { nombre: 'Refresco', cantidad: 1, precio_usd: 2 },
    ],
    ...extra,
  },
});

const post = async (cuerpo) =>
  (await fetch(`${base}/api/venta`, {
    method: 'POST',
    headers: conLlave({ 'content-type': 'application/json' }),
    body: JSON.stringify(cuerpo),
  })).json();

try {
  servidor = await iniciarServidor({ base: dir, puerto: PUERTO, log: () => {} });
  check((await entrar('dueno', CLAVE_DUENO)) === 302, 'el dueño entra con su clave');
  const cfg = await fetch(`${base}/configurar`, {
    method: 'POST',
    headers: conSesion({ 'content-type': 'application/x-www-form-urlencoded' }),
    body: new URLSearchParams({
      rif: 'J-50856106-6',
      razon_social: 'Arepa Power Restaurant',
      domicilio_fiscal: 'Araure, Portuguesa',
      alicuota_general: '16',
      serie: 'A',
      equipo: 'PUENTE-01',
    }).toString(),
    redirect: 'manual',
  });
  check(cfg.status === 302, 'la estacion queda configurada (imprenta de practica)');

  console.log('\n== 1. El apreton de manos del puente ==');
  const mano = await (await fetch(`${base}/api/puente`, { headers: conLlave() })).json();
  check(mano.ok === true, 'con la llave buena responde ok');
  check(mano.rif === 'J-50856106-6', `y dice a que negocio le hablas (${mano.rif})`);
  const manoMala = await fetch(`${base}/api/puente`, { headers: { authorization: 'Bearer efm_inventada' } });
  check(manoMala.status === 401, `con llave mala, 401 (${manoMala.status})`);

  console.log('\n== 2. La venta cruda del Cerebrito se sella ==');
  const r1 = await post(cruda('pedido', '11111111-1111-4111-8111-111111111111'));
  check(r1.sellada === true, 'sellada');
  check(r1.serie === 'A' && r1.numero === 1, `con su numero (${r1.serie}-${r1.numero})`);
  check(!!r1.numeroControl, `y numero de control (${r1.numeroControl})`);

  console.log('\n== 3. La misma venta otra vez NO duplica ==');
  // Es lo que pasa cuando el puente reintenta, o cuando la cola de la nube
  // trae la venta que el Cerebrito ya habia entregado directo.
  const r2 = await post(cruda('pedido', '11111111-1111-4111-8111-111111111111'));
  check(r2.sellada === true && r2.numero === 1, `devuelve el documento que ya existia (${r2.numero})`);

  console.log('\n== 4. La venta de mesa (cuenta) con propina ==');
  const r3 = await post(cruda('cuenta', '22222222-2222-4222-8222-222222222222', { propina_usd: 2 }));
  check(r3.sellada === true && r3.numero === 2, `sellada como documento aparte (${r3.serie}-${r3.numero})`);

  console.log('\n== 5. La forma vieja (terceros con alicuota) sigue andando ==');
  const r4 = await post({
    origen_id: 'admin-333',
    canal: 'caja',
    cliente: { nombre: 'Consumidor final' },
    renglones: [{ nombre: 'Almuerzo', cantidad: 1, precio_usd: 8, alicuota: 16 }],
    tasa_bs: 742.23,
    pago: { metodo: 'efectivo' },
  });
  check(r4.sellada === true && r4.numero === 3, `sellada (${r4.serie}-${r4.numero})`);

  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 });
}
process.exit(fallos ? 1 : 0);
