function stripAnsi(s: string): string {
  const ESC = '\u001B'
  const out: string[] = []
  for (let i = 0; i < s.length; i++) {
    if (s[i] !== ESC || s[i + 1] !== '[') {
      out.push(s[i]!)
      continue
    }
    let j = i + 2
    while (j < s.length) {
      const c = s.charCodeAt(j)
      if ((c >= 48 && c <= 57) || c === 59) {
        j++
        continue
      }
      break
    }
    if (j < s.length && s[j] === 'm') {
      i = j
      continue
    }
    out.push(s[i]!)
  }
  return out.join('')
}

export function sanitizeMarkdownText(s: string): string {
  s = stripAnsi(s)
  const out: string[] = []
  for (let i = 0; i < s.length;) {
    const cp = s.codePointAt(i)!
    const ch = cp > 0xFFFF ? String.fromCodePoint(cp) : s[i]!
    // Security: Strip ASCII control chars (except newline and tab) and C1 control chars (U+0080-U+009F)
    // This prevents ANSI escape sequences, cursor movements, and other control sequences
    if (
      !(
        (cp <= 0x1F && cp !== 0x0A && cp !== 0x09)
        || cp === 0x7F
        || (cp >= 0x80 && cp <= 0x9F)
      )
    ) {
      out.push(ch)
    }
    i += cp > 0xFFFF ? 2 : 1
  }
  return out.join('')
}
