// PRUEBA VIVA DE PUNTA A PUNTA: LA FACTURA POR CORREO CON SU PDF (2026-07-31)
//
// Recorre el camino completo contra produccion, igual que una venta real:
//   1. La imprenta da de alta al negocio y le entrega su llave.
//   2. La Estacion emite por la puerta publica /api/emitir MANDANDO SU MARCA
//      (logo, color, mensaje), como hace la Estacion de verdad.
//   3. Se comprueba que la imprenta guardo esa marca junto al documento.
//   4. Se encola el correo y se dispara el drenaje tocando /api/estacion.
//   5. Se verifica que el correo salio (estado 'enviado' en la base): si el
//      PDF adjunto estuviera malo, Mailtrap lo habria rechazado y quedaria
//      escrito el error.
//   6. Limpieza total: ni un rastro del emisor de prueba.
//
// Uso: node scripts/test_correo_pdf.mjs [correo-destino]
import { readFileSync } from 'node:fs';

const REF = 'szzhhlevtrcambcoytiz';
const PAT = readFileSync(new URL('../.sb_token', import.meta.url), 'utf8').trim();
const SELLO = process.env.SELLO ?? 'https://sello.gustitoxpress.app';
const DESTINO = process.argv[2] ?? 'gonzalezcicpc@gmail.com';

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';
// El restaurante DEMO (nunca uno real): la cola de Gustito exige un
// restaurante existente, y todo lo sembrado se borra al final.
const DEMO = '52057e85-f82a-4aaa-8577-3a75d269eb65';
const lit = (s) => `'${String(s).replace(/'/g, "''")}'`;

const limpiar = () => sql(`
  delete from fiscal.correos_factura where emisor_id in (select id from fiscal.emisores where rif = ${lit(RIF)});
  delete from fiscal.cola_gustito 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)};
`);

// Una venta de verdad, con dos renglones y dos alicuotas distintas.
const DOCUMENTO = {
  emisor: { rif: RIF, razon_social: 'Arepa Power Restaurant', domicilio_fiscal: 'Av. Principal, Araure, Portuguesa' },
  cliente: { nombre: 'María Rodríguez Peña', cedula: 'V-22606827' },
  canal: 'mesa',
  renglones: [
    { nombre: 'Arepa', cantidad: 2, precio_usd: 5, alicuota: 16, base_usd: 8.62, iva_usd: 1.38, total_usd: 10 },
    { nombre: 'Jugo de parchita', cantidad: 1, precio_usd: 2, alicuota: 0, base_usd: 2, iva_usd: 0, total_usd: 2 },
  ],
  por_alicuota: [
    { alicuota: 16, base_usd: 8.62, iva_usd: 1.38 },
    { alicuota: 0, base_usd: 2, iva_usd: 0 },
  ],
  base_usd: 10.62, iva_usd: 1.38, total_usd: 12, tasa_bs: 746.63, total_bs: 8959.56,
  pago: { metodo: 'pago_movil', referencia: '4821' },
  origen_id: 'prueba-correo-pdf',
};

const MARCA = {
  mensaje_pie: 'Gracias por preferirnos. Te esperamos de nuevo en Arepa Power.',
  color: '#C9A227',
};

try {
  await limpiar();

  // LECCION CARA (2026-07-31): se mando un correo de prueba segundos despues
  // de un despliegue y lo atendio el codigo VIEJO todavia propagandose. Gilberto
  // recibio la factura con el diseño anterior y con razon reclamo que no habia
  // cambios. Desde entonces la prueba NO manda nada sin antes comprobar que la
  // imprenta desplegada responde con el molde en uso.
  console.log('\n== 0. La imprenta desplegada esta al dia ==');
  let listo = false;
  for (let i = 0; i < 10 && !listo; i++) {
    const m = await fetch(`${SELLO}/api/muestra`).catch(() => null);
    if (m?.ok && (m.headers.get('content-type') ?? '').includes('pdf')) {
      const bytes = new Uint8Array(await m.arrayBuffer());
      listo = bytes.length > 3000 && String.fromCharCode(...bytes.subarray(0, 5)) === '%PDF-';
    }
    if (!listo) await new Promise((s) => setTimeout(s, 3000));
  }
  check(listo, 'la muestra viva responde un PDF armado con el molde actual');
  if (!listo) throw new Error('La imprenta desplegada no responde la muestra: no se manda ningun correo con codigo viejo.');

  console.log('\n== 1. La imprenta da de alta al negocio ==');
  await sql(`select fiscal.guardar_cliente(${lit(RIF)}, 'Arepa Power Restaurant', 'Av. Principal, Araure, Portuguesa',
    null, null, null, null, 'Estacion Fiscal', 'A', true, 'emisor temporal de la prueba del correo con PDF');`);
  const llave = (await sql(`select fiscal.crear_llave(${lit(RIF)}, 'llave de la prueba') as v;`))[0].v;
  check(typeof llave === 'string' && llave.length > 10, 'queda dado de alta y con su llave');

  console.log('\n== 2. La Estacion emite por la puerta publica, mandando su marca ==');
  const r = await fetch(`${SELLO}/api/emitir`, {
    method: 'POST',
    headers: { authorization: `Bearer ${llave}`, 'content-type': 'application/json' },
    body: JSON.stringify({
      rif: RIF, serie: 'A', tipo: 'factura', numero_documento: 1,
      hash: 'prueba-correo-pdf-1', fecha: new Date().toISOString(),
      base_bs: 7928.24, iva_bs: 1031.32, total_bs: 8959.56,
      documento: DOCUMENTO,
      marca: MARCA,
    }),
  });
  const acuse = await r.json();
  check(r.ok, `la imprenta acepta y numera (HTTP ${r.status})`);
  check(Number.isFinite(acuse.numero_control), `numero de control ${acuse.numero_control}`);
  check(!!acuse.numero_control_texto, `en la forma del art. 30 (${acuse.numero_control_texto})`);
  check(!!acuse.fecha_asignacion, 'con su fecha de asignacion');
  const token = String(acuse.sello ?? '').split('/v/')[1];
  check(!!token, 'y su enlace de comprobacion');

  console.log('\n== 3. La marca quedo guardada junto al documento ==');
  const guardada = await sql(`select d.marca from fiscal.documentos d
    join fiscal.emisores e on e.id = d.emisor_id where e.rif = ${lit(RIF)};`);
  check(guardada[0]?.marca?.color === '#C9A227', 'el color del negocio');
  check(/Gracias por preferirnos/.test(guardada[0]?.marca?.mensaje_pie ?? ''), 'y su mensaje del pie');

  console.log('\n== 4. Se encola el correo y se dispara el envio ==');
  // El correo cuelga de la cola de Gustito, igual que en una venta real: se
  // siembra su fila (con el restaurante DEMO, jamas uno real) y de ahi sale.
  await sql(`
    insert into fiscal.cola_gustito (restaurante_id, emisor_id, tipo, origen_id, estado, token, sellado_en, numero_documento, numero_control)
    select ${lit(DEMO)}::uuid, e.id, 'pedido', gen_random_uuid(), 'sellado', ${lit(token)}, now(), 1, ${acuse.numero_control}
      from fiscal.emisores e where e.rif = ${lit(RIF)};
    insert into fiscal.correos_factura (cola_id, emisor_id, token, para, estado)
    select c.id, c.emisor_id, ${lit(token)}, ${lit(DESTINO)}, 'pendiente'
      from fiscal.cola_gustito c
      join fiscal.emisores e on e.id = c.emisor_id
     where e.rif = ${lit(RIF)};
  `);
  const pendiente = await sql(`select public.fn_correos_factura_pendientes(5) as v;`);
  const fila = (pendiente[0]?.v ?? []).find((x) => x.para === DESTINO);
  check(!!fila?.documento, 'el correo pendiente lleva el documento completo para armar el PDF');
  check(!!fila?.marca, 'y la marca del negocio');

  // El drenaje corre detras del latido de la Estacion, como en la vida real.
  const latido = await fetch(`${SELLO}/api/estacion`, {
    method: 'POST',
    headers: { authorization: `Bearer ${llave}`, 'content-type': 'application/json' },
    body: JSON.stringify({ accion: 'latido', rif: RIF, version: '1.0.0' }),
  });
  check(latido.ok, `el latido de la Estacion pasa (HTTP ${latido.status})`);

  console.log('\n== 5. El correo salio de verdad (con su PDF adjunto) ==');
  // El envio ocurre en waitUntil, despues de responder: se le da su momento.
  let estado = null;
  for (let i = 0; i < 12; i++) {
    await new Promise((s) => setTimeout(s, 2500));
    const q = await sql(`select estado, intentos, ultimo_error from fiscal.correos_factura c
      join fiscal.emisores e on e.id = c.emisor_id where e.rif = ${lit(RIF)};`);
    estado = q[0];
    if (estado?.estado !== 'pendiente') break;
    // Cada vuelta toca el latido otra vez: si el primero no alcanzo a drenar.
    await fetch(`${SELLO}/api/estacion`, {
      method: 'POST',
      headers: { authorization: `Bearer ${llave}`, 'content-type': 'application/json' },
      body: JSON.stringify({ accion: 'latido', rif: RIF, version: '1.0.0' }),
    }).catch(() => null);
  }
  check(estado?.estado === 'enviado', `el correo quedo como enviado (estado: ${estado?.estado}${estado?.ultimo_error ? `, error: ${estado.ultimo_error}` : ''})`);
  if (estado?.estado === 'enviado') {
    console.log(`\n  >>> Revisa ${DESTINO}: la factura debe llegar con el PDF adjunto,`);
    console.log('      el color dorado del negocio y su mensaje al pie.');
  }
} 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 ? '\nCORREO CON PDF: 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
