/**
 * 字典搜索匹配度 / 高亮（与 PC dictSearchRank、后端 DictSearchRankService 对齐）
 * 小程序侧：按 rank_mode 决定是否本地重排；高亮始终本地拆分（禁止 v-html）
 */

/**
 * @param {string} text
 * @param {string} keyword
 * @param {string} [extra]
 * @returns {number}
 */
export function scoreDictMatch(text, keyword, extra) {
  const kw = String(keyword || '').trim()
  if (!kw) return 0
  const main = String(text || '').trim()
  if (!main) return 0
  let s = scoreOne(main, kw)
  if (extra) {
    s = Math.max(s, Math.floor(scoreOne(String(extra), kw) * 0.9))
  }
  return s
}

function scoreOne(haystack, needle) {
  if (haystack === needle) return 100
  const lowerH = haystack.toLowerCase()
  const lowerN = needle.toLowerCase()
  const pos = lowerH.indexOf(lowerN)
  if (pos < 0) return 0
  if (pos === 0) {
    const lenBonus = Math.max(0, 10 - Math.abs(haystack.length - needle.length))
    return 80 + Math.min(15, lenBonus)
  }
  return Math.max(20, 60 - Math.min(40, pos))
}

/**
 * @template T
 * @param {T[]} items
 * @param {string} keyword
 * @param {(item: T) => string} getText
 * @param {(item: T) => string} [getExtra]
 */
export function rankByMatchScore(items, keyword, getText, getExtra) {
  const kw = String(keyword || '').trim()
  const scored = (items || []).map((item) => {
    const match_score = kw
      ? scoreDictMatch(getText(item), kw, getExtra ? getExtra(item) : '')
      : 0
    return Object.assign({}, item, { match_score })
  })
  if (!kw) return scored
  return scored.sort((a, b) => b.match_score - a.match_score)
}

/**
 * @param {string} text
 * @param {string} keyword
 * @returns {{ text: string, hit: boolean }[]}
 */
export function splitHighlight(text, keyword) {
  const raw = String(text == null ? '' : text)
  const kw = String(keyword || '').trim()
  if (!raw || !kw) return [{ text: raw, hit: false }]
  const lower = raw.toLowerCase()
  const needle = kw.toLowerCase()
  const parts = []
  let start = 0
  let idx = lower.indexOf(needle, start)
  while (idx >= 0) {
    if (idx > start) {
      parts.push({ text: raw.slice(start, idx), hit: false })
    }
    parts.push({ text: raw.slice(idx, idx + kw.length), hit: true })
    start = idx + kw.length
    idx = lower.indexOf(needle, start)
  }
  if (start < raw.length) {
    parts.push({ text: raw.slice(start), hit: false })
  }
  return parts.length ? parts : [{ text: raw, hit: false }]
}

/**
 * 按接口 rank_mode 决定是否前端重排；有关键字时保证匹配度降序并可展示分数
 * @param {any[]} items
 * @param {string} keyword
 * @param {(item: any) => string} getText
 * @param {string} [rankMode]
 * @param {(item: any) => string} [getExtra] 拼音等附加匹配字段
 */
export function applyDictRankAndHighlight(items, keyword, getText, rankMode, getExtra) {
  const mode = rankMode === 'frontend' ? 'frontend' : 'backend'
  const kw = String(keyword || '').trim()
  let list = items || []
  if (mode === 'frontend') {
    list = rankByMatchScore(list, keyword, getText, getExtra)
  } else if (kw) {
    const mapped = list.map((item) =>
      Object.assign({}, item, { match_score: Number(item.match_score || 0) }),
    )
    const hasPositive = mapped.some((i) => Number(i.match_score) > 0)
    if (!hasPositive) {
      list = rankByMatchScore(list, keyword, getText, getExtra)
    } else {
      list = mapped.sort((a, b) => b.match_score - a.match_score)
    }
  }
  return list.map((item) => {
    const text = getText(item) || ''
    return Object.assign({}, item, {
      match_score: Number(item.match_score || 0),
      _hlParts: splitHighlight(text, kw),
    })
  })
}
