/**
 * Tokens para buscar en el manual (plan §6.9). Lo comparten el indexador y la
 * búsqueda: minúsculas, sin tildes, sin palabras vacías y con una reducción
 * simple de plurales, para que "facturas a crédito" encuentre "Factura" y "Crédito".
 */
const VACIAS = new Set(
  (
    'a al algo algun alguna algunas alguno algunos ante antes asi aun cada como con contra cual cuales cuando de del ' +
    'desde donde dos el ella ellas ellos en entre era es esa esas ese eso esos esta estan estas este esto estos fue ' +
    'ha hace hacer hay la las le les lo los mas me mi mis muy ni no nos o otra otro para pero poder por porque puede ' +
    'puedo que quien se segun ser si sin sobre son su sus tambien te tengo tiene tienen todo todos tu tus un una unas ' +
    'uno unos ya yo como quiero necesito favor hola'
  ).split(' '),
);

export function sinTildes(texto: string): string {
  return texto.normalize('NFD').replace(/[̀-ͯ]/g, '');
}

/** Terminaciones que se sacan para llegar a la raíz (de la más larga a la más corta). */
const SUFIJOS = ['aciones', 'iciones', 'acion', 'icion', 'cion', 'mente', 'adora', 'ador', 'ando', 'iendo', 'ado', 'ada', 'ido', 'ida', 'ar', 'er', 'ir', 'a', 'o', 'e'];

/**
 * Raíz aproximada, para que "factura", "facturas", "facturación" y "facturar" coincidan
 * ("factur"), igual que "crédito"/"créditos" ("credit") o "cuota"/"cuotas" ("cuot").
 */
function raiz(palabra: string): string {
  let p = palabra;
  if (p.length > 5 && p.endsWith('ces')) p = `${p.slice(0, -3)}z`;
  else if (p.length > 5 && /[^aeiou]es$/.test(p)) p = p.slice(0, -2);
  else if (p.length > 3 && p.endsWith('s')) p = p.slice(0, -1);
  for (const s of SUFIJOS) {
    if (p.length - s.length >= 4 && p.endsWith(s)) return p.slice(0, -s.length);
  }
  return p;
}

export function tokens(texto: string): string[] {
  return sinTildes(texto.toLowerCase())
    .split(/[^a-z0-9ñ]+/)
    .filter((p) => p.length > 1 && !VACIAS.has(p))
    .map(raiz);
}
