export function scoreMatch(candidate: string, query: string): number | null {
  const c = candidate.toLowerCase()
  const q = query.toLowerCase().trim()
  if (!q) return 0
  if (c === q) return 10_000
  if (c.startsWith(q)) return 5_000 - c.length
  const idx = c.indexOf(q)
  if (idx >= 0) return 2_000 - idx

  let qi = 0
  let score = 0
  let streak = 0
  for (let i = 0; i < c.length && qi < q.length; i++) {
    if (c[i] === q[qi]) {
      qi++
      streak++
      score += 10 + streak * 5
    } else {
      streak = 0
    }
  }
  if (qi < q.length) return null
  return score
}

export type MatchHighlightRange = Readonly<{ start: number; end: number }>

export function computeMatchHighlightRanges(
  text: string,
  query: string,
): MatchHighlightRange[] {
  const q = String(query ?? '')
    .trim()
    .toLowerCase()
  if (!q) return []

  const source = String(text ?? '')
  if (!source) return []
  const lower = source.toLowerCase()

  const exactIdx = lower.indexOf(q)
  if (exactIdx >= 0) return [{ start: exactIdx, end: exactIdx + q.length }]

  const positions: number[] = []
  let qi = 0
  for (let i = 0; i < lower.length && qi < q.length; i++) {
    if (lower[i] === q[qi]) {
      positions.push(i)
      qi++
    }
  }
  if (qi < q.length) return []

  const ranges: MatchHighlightRange[] = []
  let start = positions[0]!
  let prev = positions[0]!
  for (let i = 1; i < positions.length; i++) {
    const pos = positions[i]!
    if (pos === prev + 1) {
      prev = pos
      continue
    }
    ranges.push({ start, end: prev + 1 })
    start = pos
    prev = pos
  }
  ranges.push({ start, end: prev + 1 })
  return ranges
}
