/**
 * Monto en letras para el boleto de compraventa ("son dólares americanos ochenta
 * mil con 00/100"). Enteros hasta 999.999.999.999.
 */
const UNIDADES = [
  '',
  'uno',
  'dos',
  'tres',
  'cuatro',
  'cinco',
  'seis',
  'siete',
  'ocho',
  'nueve',
  'diez',
  'once',
  'doce',
  'trece',
  'catorce',
  'quince',
  'dieciséis',
  'diecisiete',
  'dieciocho',
  'diecinueve',
  'veinte',
  'veintiuno',
  'veintidós',
  'veintitrés',
  'veinticuatro',
  'veinticinco',
  'veintiséis',
  'veintisiete',
  'veintiocho',
  'veintinueve',
];
const DECENAS = ['', '', '', 'treinta', 'cuarenta', 'cincuenta', 'sesenta', 'setenta', 'ochenta', 'noventa'];
const CENTENAS = [
  '',
  'ciento',
  'doscientos',
  'trescientos',
  'cuatrocientos',
  'quinientos',
  'seiscientos',
  'setecientos',
  'ochocientos',
  'novecientos',
];

function hasta999(n: number): string {
  if (n === 0) return '';
  if (n === 100) return 'cien';
  const c = Math.floor(n / 100);
  const r = n % 100;
  let txt = CENTENAS[c];
  if (r > 0) {
    let dec: string;
    if (r < 30) dec = UNIDADES[r];
    else {
      const d = Math.floor(r / 10);
      const u = r % 10;
      dec = u ? `${DECENAS[d]} y ${UNIDADES[u]}` : DECENAS[d];
    }
    txt = txt ? `${txt} ${dec}` : dec;
  }
  return txt;
}

/** "uno" se apocopa delante de "mil" y "millones": veintiún mil, un millón. */
const apocopar = (t: string) => t.replace(/veintiuno$/, 'veintiún').replace(/(^|\s)uno$/, '$1un');

export function enteroALetras(n: number): string {
  n = Math.floor(Math.abs(n));
  if (n === 0) return 'cero';
  const millones = Math.floor(n / 1_000_000);
  const miles = Math.floor((n % 1_000_000) / 1000);
  const resto = n % 1000;
  const partes: string[] = [];
  if (millones) {
    if (millones === 1) partes.push('un millón');
    else partes.push(`${apocopar(enteroALetras(millones))} millones`);
  }
  if (miles) partes.push(miles === 1 ? 'mil' : `${apocopar(hasta999(miles))} mil`);
  if (resto) partes.push(hasta999(resto));
  return partes.join(' ');
}

const NOMBRE_MONEDA: Record<string, string> = {
  PYG: 'guaraníes',
  USD: 'dólares americanos',
  EUR: 'euros',
  BRL: 'reales',
};

export function montoEnLetras(monto: number, monedaCodigo: string): string {
  const moneda = NOMBRE_MONEDA[monedaCodigo] ?? monedaCodigo;
  const entero = Math.floor(Math.abs(monto));
  if (monedaCodigo === 'PYG') return `${moneda} ${enteroALetras(entero)}`;
  const centavos = Math.round((Math.abs(monto) - entero) * 100);
  return `${moneda} ${enteroALetras(entero)} con ${String(centavos).padStart(2, '0')}/100`;
}
