/**
 * Hermes Agent 实时思考过程的颜文字过滤。
 *
 * 背景：Hermes 的 KawaiiSpinner 会给 thinking_callback 拼接前导颜文字与尾部省略号，
 * 形如 `(◔_◔) pondering...`。在严肃业务场景下需要剥离这些装饰，仅保留动词本身。
 *
 * 数据来源：backend/hermes-agent/agent/display.py
 *   - KAWAII_THINKING（15 个默认思考颜文字）
 *   - 各皮肤（ares / poseidon / sisyphus / charizard）覆盖的思考颜文字
 *   - KAWAII_WAITING（等待动画用的颜文字，作为兜底也一并剥离）
 *
 * 使用：在 SSE 处理 status 事件时调用 stripHermesThinkingDecoration(content)。
 */

// 默认 16 个思考颜文字（display.py: KAWAII_THINKING）
const DEFAULT_THINKING_FACES = [
  '(｡•́︿•̀｡)',
  '(◔_◔)',
  '(¬‿¬)',
  '( •_•)>⌐■-■)',
  '(⌐■_■)',
  '(´･_･`)',
  '◉_◉',
  '(°ロ°)',
  '( ˘⌣˘)♡',
  'ヽ(>∀<☆)☆',
  '٩(๑❛ᴗ❛๑)۶',
  '(⊙_⊙)',
  '(¬_¬)',
  '( ͡° ͜ʖ ͡°)',
  'ಠ_ಠ',
  '>⌐■-■',
]

// 各皮肤覆盖的思考颜文字（display.py: skin_engine.py 中的 SKIN_THINKING_FACES）
const SKIN_THINKING_FACES = [
  // ares
  '(⚔)', '(⛨)', '(▲)', '(⌁)', '(<>)',
  // poseidon
  '(Ψ)', '(∿)', '(≈)', '(◌)',
  // sisyphus
  '(◉)', '(◬)', '(○)', '(●)',
  // charizard
  '(✦)', '(◇)', '(🔥)',
]

// 等待动画用的颜文字（display.py: KAWAII_WAITING，作为兜底）
const WAITING_FACES = [
  '(￣∇￣)', '(￣ー￣)', '(─‿─)', '(︶ω︶)', '(￣︶￣)',
  '( ︶｡｡)', `(˘｡˘)`, `(•‿•)`, `(◕‿◕)`, `(✿◡‿◡)`,
]

// 合并去重，并按长度降序排列（优先匹配长串，避免前缀误判）
const ALL_FACES = Array.from(new Set([
  ...DEFAULT_THINKING_FACES,
  ...SKIN_THINKING_FACES,
  ...WAITING_FACES,
])).sort((a, b) => b.length - a.length)

/**
 * 剥离 Hermes 实时思考过程文本中的装饰：
 * 1. 反复剥离前导的已知颜文字（精确匹配）
 * 2. 兜底剥离前导的圆括号包裹片段（如新增皮肤未及时登记时）
 * 3. 去除首尾空白
 *
 * 注意：尾部省略号按 Hermes 原始输出保留，不剥离。
 *
 * @param {string} text 原始文本，如 `(◔_◔) pondering...`
 * @returns {string} 清洗后的文本，如 `pondering...`
 */
export function stripHermesThinkingDecoration(text) {
  if (!text) return ''
  let s = String(text)

  // 1. 反复剥离前导的已知颜文字（按长度降序匹配，避免短颜文字吃掉长颜文字的前缀）
  let changed = true
  while (changed) {
    changed = false
    for (const face of ALL_FACES) {
      if (s.startsWith(face)) {
        s = s.slice(face.length)
        changed = true
        break
      }
    }
    // 去掉前导空白后再尝试下一轮（颜文字之间可能由空格分隔）
    const trimmed = s.trimStart()
    if (trimmed !== s) {
      s = trimmed
      changed = true
    }
  }

  // 2. 兜底：剥离剩余的前导圆括号片段（如 `(xxx)` 或 `(xx)(yy)`）
  //    覆盖未来皮肤新增颜文字未及时登记的场景
  //    限制：`[^)]*` 保证不会跨括号贪婪匹配，最多吃到第一个 `)` 就停
  s = s.replace(/^(?:\([^)]*\)\s*)+\s*/, '')

  return s.trim()
}

/**
 * 剥离思考过程字符串开头的所有空行（含纯空白字符组成的行）。
 *
 * 背景：Hermes LLM 首个 token 经常是 `\n`，累加到 streamingThinking 后，
 * 在 `<pre>` 的 `white-space: pre-wrap` 下会渲染为首行空白，影响观感。
 * 仅剥离开头空行，保留中间与尾部的换行（属于正常思考输出格式）。
 *
 * @param {string} text 原始文本，如 `"\n\n正在分析...\n步骤一\n"`
 * @returns {string} 剥离首部空行后的文本，如 `"正在分析...\n步骤一\n"`
 */
export function trimLeadingBlankLines(text) {
  if (!text) return ''
  // [ \t]*\r?\n 匹配"可选空白 + 换行"组成的整行；+ 连续多行一次性剥离
  return String(text).replace(/^(?:[ \t]*\r?\n)+/, '')
}

// 仅用于内部测试与调试（生产可忽略）
export const __HERMES_FACES__ = ALL_FACES
