/**
 * Pure string utilities shared across modules.
 */

/**
 * Spanish single-letter conjunctions that stay lowercase in Title Case,
 * except when they are the first word of the string.
 *
 * Standard Spanish typography rule (RAE): preposiciones y conjunciones
 * (a, con, de, e, en, o, por, u, y…) van en minúscula salvo que sean la
 * primera palabra. Single-letter conjunctions are included here so a
 * "Y" between two words renders correctly.
 */
const LOWERCASE_WORDS = new Set(['y', 'e', 'o', 'u']);

/**
 * Convert a brand/category name to Title Case.
 *
 * Splits on word boundaries (space, hyphen, dot, ampersand, slash) and
 * uppercases the first letter of each word, lowercasing the rest of the
 * word. Punctuation and whitespace separators are preserved verbatim.
 *
 * Behavior:
 * - If the input is ALL-CAPS (every letter is uppercase and at least one
 *   is lowercase-equivalent), each word is Title Cased and Spanish
 *   single-letter conjunctions (y/e/o/u) are lowercased unless they
 *   are the first word.
 * - If the input has mixed case (e.g. "BioSana"), it is returned
 *   unchanged. This makes the function idempotent for re-application:
 *   a Title-Cased string is a fixed point, and a mixed-case string is
 *   not what we're trying to fix.
 * - Empty string → empty string.
 *
 * @example
 * toTitleCase('A.VOGEL')                    // 'A.Vogel'
 * toTitleCase('BIOCOP')                     // 'Biocop'
 * toTitleCase('EL GRANERO INTEGRAL')        // 'El Granero Integral'
 * toTitleCase('COMPLEMENTOS Y NUTRICIÓN')   // 'Complementos y Nutrición'
 * toTitleCase('DULCES LISSEN')              // 'Dulces Lissen'
 * toTitleCase('La Finestra Sul Cielo')      // 'La Finestra Sul Cielo' (unchanged)
 * toTitleCase('BioSana')                     // 'BioSana' (unchanged)
 * toTitleCase('')                            // ''
 */
export function toTitleCase(input: string): string {
  if (!input) return input;
  // Only transform strings that are entirely uppercase. A mixed-case string
  // is treated as already-formatted and returned verbatim.
  if (input !== input.toUpperCase() || input === input.toLowerCase()) {
    return input;
  }
  // Split keeping the delimiters so we can reconstruct the string verbatim.
  const parts = input.split(/([\s.\-/&]+)/g);
  let isFirstWord = true;
  return parts
    .map((part) => {
      if (/^[\s.\-/&]+$/.test(part)) return part;
      if (part.length === 0) return part;
      const lower = part.toLocaleLowerCase('es-ES');
      if (!isFirstWord && LOWERCASE_WORDS.has(lower)) return lower;
      isFirstWord = false;
      return part.charAt(0).toLocaleUpperCase('es-ES') + part.slice(1).toLocaleLowerCase('es-ES');
    })
    .join('');
}
