// Reply / forward subject prefix handling.
//
// Real-world email subjects accumulate prefixes across clients and languages:
// "Re: AW: WG: Fwd: Re: foo". The deduplication regex needs to know ALL
// commonly-used reply/forward markers - not just the current locale's, since
// inbound messages may come from any locale. Failing to strip a foreign-locale
// prefix means the user's locale prefix gets *added on top* and the subject
// chain keeps growing.
//
// Sources: de-facto conventions in Outlook / Thunderbird / Apple Mail per
// language. Includes a handful of legacy short-forms (R:, Fw:) that some
// mobile clients still emit.

const REPLY_TOKENS = [
  "Re",      // English, Italian, French (also generic ISO)
  "RE",      // Outlook variant
  "AW",      // German (Antwort)
  "Antw",    // German verbose
  "Sv",      // Danish / Swedish / Norwegian (Svar)
  "Yn",      // Turkish (Yanit)
  "Yanit",   // Turkish verbose
  "Odp",     // Polish (Odpowiedz)
  "Ответ",   // Russian
  "Resp",    // Spanish/Portuguese variant
  "Vá",      // Hungarian
  "回复",    // Chinese
  "回覆",    // Chinese traditional
  "답장",    // Korean
  // NB: deliberately no bare "R" token — a single letter would strip the first
  // word of legitimate subjects like "R: budget 2024". The full "Re" covers
  // the common Italian/English case anyway.
];

const FORWARD_TOKENS = [
  "Fwd",     // English standard
  "Fw",      // English short / Polish / German short
  "WG",      // German (Weitergeleitet)
  "Tr",      // French (Transfert)
  "Vs",      // Danish (Videresend)
  "Enc",     // Portuguese (Encaminhar)
  "ENC",     // Portuguese caps
  "Rv",      // Spanish (Reenviar)
  "RV",      // Spanish caps
  "Rvf",     // Spanish variant
  "Inol",    // Italian (Inoltro)
  // NB: deliberately no bare "I" token — see the REPLY_TOKENS note above.
  "PD",      // Polish (Przekazane Dalej)
  "PR",      // Czech (Preposlat)
  "İlt",     // Turkish (Ilet)
  "Ilt",     // Turkish ASCII
  "Пересл",  // Russian (Peresylka)
  "Пер",     // Russian short
  "转发",    // Chinese
  "轉寄",    // Chinese traditional
  "전달",    // Korean
];

// Match a single prefix token + optional [N] counter (Outlook) or *N (Eudora)
// + colon + whitespace. Case-insensitive. The non-capturing groups keep the
// regex composable for stripping multiple prefixes in a row.
function buildPrefixRegex(tokens: string[]): RegExp {
  // Escape regex specials in tokens (none currently, but be defensive)
  const escaped = tokens.map((t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
  // Sort by length DESC so longer tokens (e.g. "Пересл") win over their
  // shorter prefixes (e.g. "Пер") during alternation matching.
  escaped.sort((a, b) => b.length - a.length);
  return new RegExp(
    `^\\s*(?:${escaped.join("|")})(?:\\[\\d+\\]|\\*\\d*)?\\s*:\\s*`,
    "i",
  );
}

const ANY_PREFIX_RE = buildPrefixRegex([...REPLY_TOKENS, ...FORWARD_TOKENS]);

/**
 * Strip any leading sequence of reply/forward prefixes (across languages) from
 * a subject line. Idempotent and safe for empty input.
 *
 * Examples:
 *   stripSubjectPrefixes("Re: AW: WG: foo")        === "foo"
 *   stripSubjectPrefixes("Re[2]: foo")             === "foo"
 *   stripSubjectPrefixes("RE: Re: foo")            === "foo"
 *   stripSubjectPrefixes("foo")                    === "foo"
 *   stripSubjectPrefixes("")                       === ""
 */
export function stripSubjectPrefixes(subject: string | undefined | null): string {
  if (!subject) return "";
  let s = subject;
  // Bounded loop: in practice you never see more than ~10 prefixes; the bound
  // protects against pathological input. Each iteration must consume input.
  for (let i = 0; i < 20; i++) {
    const next = s.replace(ANY_PREFIX_RE, "");
    if (next === s) break;
    s = next;
  }
  return s;
}

/**
 * Build a reply subject with the given locale-aware prefix. Strips any
 * pre-existing prefixes (in any language) first so chains don't accumulate.
 *
 *   buildReplySubject("AW: WG: foo", "Re:")   === "Re: foo"
 *   buildReplySubject("foo", "AW:")           === "AW: foo"
 *   buildReplySubject("", "AW:")              === "AW:"
 */
export function buildReplySubject(subject: string | undefined | null, prefix: string): string {
  const stripped = stripSubjectPrefixes(subject);
  return stripped ? `${prefix} ${stripped}` : prefix;
}

/**
 * Build a forward subject. Same logic as buildReplySubject but conceptually
 * separate for clarity at the call site.
 */
export function buildForwardSubject(subject: string | undefined | null, prefix: string): string {
  const stripped = stripSubjectPrefixes(subject);
  return stripped ? `${prefix} ${stripped}` : prefix;
}
