// Tests del renderizador de templates de acreditación bancaria.
// Cubre placeholders, encadenamiento de filtros y unescape de separadores.

import { renderTemplate, unescapeSeparator } from './template-renderer';

describe('renderTemplate — placeholders', () => {
  it('reemplaza un placeholder simple', () => {
    expect(renderTemplate('Hola {{nombre}}', { nombre: 'Juan' })).toBe('Hola Juan');
  });

  it('placeholder ausente → string vacío', () => {
    expect(renderTemplate('Hola {{nombre}}', {})).toBe('Hola ');
  });

  it('null/undefined → string vacío', () => {
    expect(renderTemplate('[{{a}}|{{b}}]', { a: null, b: undefined })).toBe('[|]');
  });

  it('número se serializa', () => {
    expect(renderTemplate('{{x}}', { x: 1234.5 })).toBe('1234.5');
  });

  it('Date se serializa como ISO YYYY-MM-DD', () => {
    expect(renderTemplate('{{f}}', { f: new Date('2026-05-13T12:34:56Z') })).toBe('2026-05-13');
  });
});

describe('renderTemplate — filtros', () => {
  it('upper / lower / trim', () => {
    expect(renderTemplate('{{x|upper}}', { x: 'hola' })).toBe('HOLA');
    expect(renderTemplate('{{x|lower}}', { x: 'HOLA' })).toBe('hola');
    expect(renderTemplate('{{x|trim}}', { x: '  hola  ' })).toBe('hola');
  });

  it('noaccent quita acentos', () => {
    expect(renderTemplate('{{x|noaccent}}', { x: 'Pérez Núñez' })).toBe('Perez Nunez');
  });

  it('trunc:N corta a N caracteres', () => {
    expect(renderTemplate('{{x|trunc:5}}', { x: 'Hola Mundo' })).toBe('Hola ');
    expect(renderTemplate('{{x|trunc:50}}', { x: 'corto' })).toBe('corto');
  });

  it('padl:N rellena con espacios a la izquierda', () => {
    expect(renderTemplate('[{{x|padl:6}}]', { x: 'abc' })).toBe('[   abc]');
  });

  it('padr:N rellena con espacios a la derecha', () => {
    expect(renderTemplate('[{{x|padr:6}}]', { x: 'abc' })).toBe('[abc   ]');
  });

  it('pad0:N rellena con ceros a la izquierda (típico bancario posicional)', () => {
    expect(renderTemplate('{{x|pad0:8}}', { x: '12345' })).toBe('00012345');
  });

  it('num:N formatea número con N decimales sin separadores', () => {
    expect(renderTemplate('{{x|num:0}}', { x: 1234.5 })).toBe('1235');
    expect(renderTemplate('{{x|num:2}}', { x: 1234.5 })).toBe('1234.50');
  });

  it('replace:from:to reemplaza ocurrencias', () => {
    expect(renderTemplate('{{x|replace:-:_}}', { x: 'a-b-c' })).toBe('a_b_c');
  });

  it('default:VAL usa VAL cuando el campo está vacío', () => {
    expect(renderTemplate('{{x|default:N/A}}', { x: '' })).toBe('N/A');
    expect(renderTemplate('{{x|default:N/A}}', { x: 'OK' })).toBe('OK');
  });

  it('filtros encadenados se aplican en orden', () => {
    // primero noaccent, luego upper, luego trunc
    expect(renderTemplate('{{x|noaccent|upper|trunc:5}}', { x: 'Pérez González' })).toBe('PEREZ');
  });

  it('filtro desconocido se ignora (no rompe)', () => {
    expect(renderTemplate('{{x|filtroQueNoExiste|upper}}', { x: 'hola' })).toBe('HOLA');
  });
});

describe('renderTemplate — escenarios bancarios reales', () => {
  it('formato delimitado típico (BCP / Continental simplificado)', () => {
    const tpl = '{{cedula}};{{nombre_completo|upper|trunc:40}};{{cuenta_bancaria}};{{monto|num:0}}';
    const ctx = {
      cedula: '1234567',
      nombre_completo: 'Pérez González, Juan Carlos',
      cuenta_bancaria: '123456789',
      monto: 3_250_000.5,
    };
    expect(renderTemplate(tpl, ctx)).toBe('1234567;PÉREZ GONZÁLEZ, JUAN CARLOS;123456789;3250001');
  });

  it('formato posicional con padding (Banco con ancho fijo)', () => {
    const tpl =
      '{{cedula|pad0:10}}{{nombre_completo|noaccent|upper|padr:30}}{{cuenta_bancaria|pad0:15}}{{monto_centavos|pad0:12}}';
    const ctx = {
      cedula: '1234567',
      nombre_completo: 'Pérez Núñez',
      cuenta_bancaria: '987654',
      monto_centavos: 325_000_050,
    };
    const out = renderTemplate(tpl, ctx);
    // Cédula 10 chars + nombre 30 chars + cuenta 15 chars + monto 12 chars = 67 chars
    expect(out.length).toBe(10 + 30 + 15 + 12);
    expect(out.slice(0, 10)).toBe('0001234567');
    expect(out.slice(10, 40)).toBe('PEREZ NUNEZ                   ');
    expect(out.slice(40, 55)).toBe('000000000987654');
    expect(out.slice(55)).toBe('000325000050');
  });
});

describe('unescapeSeparator', () => {
  it.each([
    ['\\n', '\n'],
    ['\\r\\n', '\r\n'],
    ['\\t', '\t'],
    [';', ';'],
    [null, '\n'],
    [undefined, '\n'],
    ['', '\n'],
  ])('unescape %p → %p', (input, expected) => {
    expect(unescapeSeparator(input as any)).toBe(expected);
  });
});
