export interface Unit {
  text: string;
  /** Whitespace/punctuation glue that originally followed this unit. */
  trailing: string;
  /** Whether this unit ends a paragraph (was followed by a blank line). */
  endsParagraph: boolean;
}

const SENTENCE_RE = /([^.!?؟…]+[.!?؟…]+)\s*/gu;

/**
 * Split `text` into translation units: paragraphs are first split by blank
 * lines, then each paragraph is split into sentences by terminal punctuation.
 * The `trailing` and `endsParagraph` fields capture the exact whitespace/
 * separator that followed each unit so that `reassembleUnits` is lossless.
 *
 * Note: `locale` is accepted for future locale-specific tuning but the regex
 * already handles both Hebrew (. ! ? …) and English sentence boundaries.
 */
export function splitIntoUnits(text: string, _locale?: string): Unit[] {
  if (!text) return [];

  const out: Unit[] = [];
  const paragraphs = text.split(/\n\s*\n/);

  paragraphs.forEach((para, pi) => {
    const isLastPara = pi === paragraphs.length - 1;
    const matches = [...para.matchAll(SENTENCE_RE)];

    if (matches.length === 0) {
      if (para.trim().length > 0) {
        // No terminal punctuation — treat whole paragraph as one unit.
        out.push({
          text: para.trim(),
          trailing: '',
          endsParagraph: !isLastPara,
        });
      }
      return;
    }

    matches.forEach((m, mi) => {
      const isLastInPara = mi === matches.length - 1;
      // m[1] is guaranteed by the capturing group in SENTENCE_RE.
      const sentence = m[1] as string;
      // Capture the whitespace that followed the sentence inside the paragraph.
      // matchAll gives us m[0] = full match including trailing \s*; the
      // trailing spaces between sentences inside a para are encoded here.
      const rawTrailing = m[0].slice(sentence.length); // everything after the sentence

      out.push({
        text: sentence.trim(),
        trailing: isLastInPara ? rawTrailing : rawTrailing || ' ',
        endsParagraph: isLastInPara && !isLastPara,
      });
    });
  });

  return out;
}

/**
 * Reassemble translated units back into a full string. Each translation
 * replaces the original `text`; the original `trailing` and paragraph
 * separators are preserved verbatim.
 *
 * Throws if `translations.length !== units.length`.
 */
export function reassembleUnits(units: Unit[], translations: string[]): string {
  if (units.length !== translations.length) {
    throw new Error(
      `reassembleUnits: unit count mismatch — ${units.length} units vs ${translations.length} translations`,
    );
  }

  let out = '';
  units.forEach((u, i) => {
    out += translations[i];
    if (u.endsParagraph) {
      out += '\n\n';
    } else {
      out += u.trailing;
    }
  });

  return out.trimEnd();
}
