// PRUEBA DEL PANEL DE LA IMPRENTA (2026-07-28)
// El negocio visto desde la silla de Gilberto: entrar, dar de alta un cliente,
// generarle su llave, verlo facturar y sacar el reporte del SENIAT. Se prueba
// contra el panel publicado. Limpia lo que crea.
import { readFileSync } from 'node:fs';

const REF = 'szzhhlevtrcambcoytiz';
const PAT = readFileSync(new URL('../.sb_token', import.meta.url), 'utf8').trim();
const PANEL = process.env.PANEL ?? 'https://sello.gustitoxpress.app';
const USUARIO = process.env.PANEL_USUARIO ?? 'gilberto';
// La clave NO se escribe aca. Vive en .panel_clave, que git no sube: una clave
// en el codigo es una clave publicada, y el freno de la puerta no sirve de nada
// si la clave anda por ahi escrita.
const CLAVE =
  process.env.PANEL_CLAVE ?? readFileSync(new URL('../.panel_clave', 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(t.slice(0, 200));
  return JSON.parse(t);
}

const RIF = 'V-22606827-5'; // RIF real distinto al del emprendimiento, para no pisar datos
const lit = (s) => `'${String(s).replace(/'/g, "''")}'`;
const limpiar = () =>
  sql(`delete from fiscal.intentos where quien=${lit(RIF)};
       delete from fiscal.envios_mensuales 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.consultas_qr where token in (select token from fiscal.documentos d join fiscal.emisores e on e.id=d.emisor_id where e.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.emisores where rif=${lit(RIF)};`);

let galleta = '';
async function api(accion, datos) {
  const r = await fetch(`${PANEL}/api/admin`, {
    method: 'POST',
    headers: { 'content-type': 'application/json', ...(galleta ? { cookie: galleta } : {}) },
    body: JSON.stringify({ accion, datos: datos || {} }),
  });
  const set = r.headers.get('set-cookie');
  if (set) galleta = set.split(';')[0];
  return { estado: r.status, cuerpo: await r.json().catch(() => ({})) };
}

try {
  await limpiar();

  console.log('\n== 1. Sin entrar, no se ve nada ==');
  const sinSesion = await api('clientes');
  check(sinSesion.estado === 401, `pide sesion (HTTP ${sinSesion.estado})`);

  console.log('\n== 2. Clave mala no entra ==');
  const mala = await api('entrar', { usuario: USUARIO, clave: 'estanoes' });
  check(mala.estado === 401, `rebota (HTTP ${mala.estado})`);
  check(mala.cuerpo.error === 'Usuario o clave incorrectos', 'sin decir cual de los dos fallo');

  console.log('\n== 3. Con la clave correcta se entra ==');
  const entrada = await api('entrar', { usuario: USUARIO, clave: CLAVE });
  check(entrada.estado === 200, `entra (HTTP ${entrada.estado})`);
  check(!!entrada.cuerpo.nombre, `y saluda por su nombre (${entrada.cuerpo.nombre})`);
  check(galleta.startsWith('gxf_panel='), 'con su sesion firmada');

  console.log('\n== 4. Dar de alta un cliente ==');
  const rifMalo = await api('guardar_cliente', { rif: 'J-12345678-9', razon_social: 'Inventado', domicilio: 'X' });
  check(rifMalo.estado === 400, 'un RIF invalido se rechaza');
  const alta = await api('guardar_cliente', {
    rif: RIF,
    razon_social: 'Comercial de prueba',
    domicilio: 'Araure, Portuguesa',
    representante: 'Gilberto Gonzalez',
    correo: 'prueba@ejemplo.com',
    sistema: 'Profit Plus',
    serie: 'C',
    rif_comprobado: true,
  });
  check(alta.estado === 200, `el cliente queda dado de alta (${alta.cuerpo.datos})`);

  console.log('\n== 5. Aparece en la lista con sus datos ==');
  const lista = (await api('clientes')).cuerpo.datos;
  const cli = lista.find((c) => c.rif === RIF);
  check(!!cli, 'sale en la lista de clientes');
  check(cli.sistema === 'Profit Plus' && cli.serie_asignada === 'C', `con su sistema y su serie (${cli.sistema}, serie ${cli.serie_asignada})`);
  check(cli.rif_comprobado === true, 'y marcado que ya entrego el comprobante de RIF');
  check(cli.documentos_mes === 0, 'todavia sin documentos');

  console.log('\n== 6. Generarle su llave ==');
  const llave = (await api('crear_llave', { rif: RIF, nombre: 'su sistema administrativo' })).cuerpo.datos;
  check(String(llave).startsWith('gxf_'), `sale la llave para entregarsela (${String(llave).slice(0, 12)}...)`);
  const llaves = (await api('llaves', { rif: RIF })).cuerpo.datos;
  check(llaves.length === 1 && llaves[0].activa, 'y queda registrada como activa');
  check(!JSON.stringify(llaves).includes(String(llave).slice(4)), 'sin que el panel vuelva a mostrarla nunca');

  console.log('\n== 7. El cliente factura con esa llave ==');
  const emision = await fetch(`${PANEL}/api/emitir`, {
    method: 'POST',
    headers: { authorization: `Bearer ${llave}`, 'content-type': 'application/json' },
    body: JSON.stringify({
      rif: RIF, serie: 'C', tipo: 'factura', numero_documento: 1, hash: 'panel-doc-1',
      fecha: new Date().toISOString(), base_bs: 5000, iva_bs: 800, total_bs: 5800,
      documento: { origen: 'Profit del cliente' },
    }),
  });
  check(emision.status === 200, `emite sin problema (HTTP ${emision.status})`);
  const lista2 = (await api('clientes')).cuerpo.datos.find((c) => c.rif === RIF);
  check(lista2.documentos_mes === 1, `y el panel ya lo cuenta (${lista2.documentos_mes} documento)`);
  check(Number(lista2.total_mes_bs) === 5800, `con lo facturado del mes (${lista2.total_mes_bs})`);

  console.log('\n== 8. El reporte del SENIAT ==');
  const hoy = new Date();
  const resumen = (await api('resumen_mensual', { rif: RIF, anio: hoy.getFullYear(), mes: hoy.getMonth() + 1 })).cuerpo.datos;
  check(resumen.documentos === 1, `el periodo trae su documento (${resumen.documentos})`);
  check(resumen.ya_enviado === false, 'y avisa que todavia no se ha reportado');
  const relacion = (await api('relacion_mensual', { rif: RIF, anio: hoy.getFullYear(), mes: hoy.getMonth() + 1 })).cuerpo.datos;
  check(relacion.length === 1 && relacion[0].numero_control, 'la relacion sale con su numero de control');
  await api('marcar_enviado', { rif: RIF, anio: hoy.getFullYear(), mes: hoy.getMonth() + 1 });
  const resumen2 = (await api('resumen_mensual', { rif: RIF, anio: hoy.getFullYear(), mes: hoy.getMonth() + 1 })).cuerpo.datos;
  check(resumen2.ya_enviado === true, 'y al marcarlo queda la constancia');

  console.log('\n== 9. Suspender a un cliente que no pago ==');
  await api('activar_cliente', { rif: RIF, activo: false });
  const bloqueado = await fetch(`${PANEL}/api/emitir`, {
    method: 'POST',
    headers: { authorization: `Bearer ${llave}`, 'content-type': 'application/json' },
    body: JSON.stringify({
      rif: RIF, serie: 'C', tipo: 'factura', numero_documento: 2, hash: 'panel-doc-2',
      fecha: new Date().toISOString(), base_bs: 100, iva_bs: 16, total_bs: 116,
      documento: {},
    }),
  });
  check(bloqueado.status === 401, `suspendido, ya no puede emitir (HTTP ${bloqueado.status})`);

  console.log('\n== 10. Revocar una llave ==');
  await api('activar_cliente', { rif: RIF, activo: true });
  await api('revocar_llave', { id: llaves[0].id });
  const conRevocada = await fetch(`${PANEL}/api/emitir`, {
    method: 'POST',
    headers: { authorization: `Bearer ${llave}`, 'content-type': 'application/json' },
    body: JSON.stringify({
      rif: RIF, serie: 'C', tipo: 'factura', numero_documento: 3, hash: 'panel-doc-3',
      fecha: new Date().toISOString(), base_bs: 100, iva_bs: 16, total_bs: 116,
      documento: {},
    }),
  });
  check(conRevocada.status === 401, `con la llave revocada tampoco (HTTP ${conRevocada.status})`);
} catch (e) {
  console.log('  XX  ' + String(e).slice(0, 200));
  fallos++;
} finally {
  await limpiar();
}

console.log(fallos === 0 ? '\nPANEL DE LA IMPRENTA: TODO VERDE' : `\n${fallos} FALLO(S)`);
process.exit(fallos === 0 ? 0 : 1);
