/**
 * 文本差异对比工具 — 用于简历原文与 AI 改进版本的逐字高亮对比
 *
 * 采用 Myers diff 算法的简化实现，能精确找出两段文本之间的
 * 插入、删除和保留片段，比逐字顺序扫描更准确。
 */

/** 差异片段类型 */
export interface DiffSegment {
  /** 文本内容 */
  text: string
  /** 是否为差异（需要高亮） */
  highlight: boolean
}

/**
 * 计算两段文本的差异，返回新文本中每个片段的高亮标记
 * 使用最长公共子序列（LCS）来识别相同部分，非 LCS 部分标记为差异
 *
 * @param original - 原文字符串
 * @param modified - AI 改进后的字符串
 * @returns 差异片段数组，每个片段包含文本和是否高亮
 */
export function computeDiff(original: string, modified: string): DiffSegment[] {
  if (!original || !modified) {
    return modified ? [{ text: modified, highlight: true }] : []
  }

  // 计算 LCS 表
  const m = original.length
  const n = modified.length

  // 优化：如果文本完全相同，直接返回
  if (original === modified) {
    return [{ text: modified, highlight: false }]
  }

  // 使用滚动数组优化空间，只保留两行
  let prev = new Uint16Array(n + 1)
  let curr = new Uint16Array(n + 1)

  for (let i = 1; i <= m; i++) {
    for (let j = 1; j <= n; j++) {
      if (original[i - 1] === modified[j - 1]) {
        curr[j] = prev[j - 1] + 1
      } else {
        curr[j] = Math.max(prev[j], curr[j - 1])
      }
    }
    // 交换行
    ;[prev, curr] = [curr, prev]
    curr.fill(0)
  }

  // 回溯找出 LCS 中每个字符在 modified 中的位置
  // 需要完整的 DP 表来回溯，重新计算（用二维数组但限制大小）
  const lcsSet = new Set<number>() // modified 中属于 LCS 的索引

  // 对于较长文本，使用空间优化的回溯
  if (m * n > 1000000) {
    // 文本过长时使用简化的贪心匹配
    let oi = 0
    for (let mi = 0; mi < n && oi < m; mi++) {
      if (modified[mi] === original[oi]) {
        lcsSet.add(mi)
        oi++
      }
    }
  } else {
    // 标准 LCS 回溯
    const dp: number[][] = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0))
    for (let i = 1; i <= m; i++) {
      for (let j = 1; j <= n; j++) {
        if (original[i - 1] === modified[j - 1]) {
          dp[i][j] = dp[i - 1][j - 1] + 1
        } else {
          dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1])
        }
      }
    }

    // 回溯
    let i = m, j = n
    while (i > 0 && j > 0) {
      if (original[i - 1] === modified[j - 1]) {
        lcsSet.add(j - 1)
        i--
        j--
      } else if (dp[i - 1][j] >= dp[i][j - 1]) {
        i--
      } else {
        j--
      }
    }
  }

  // 根据 LCS 标记生成差异片段
  const segments: DiffSegment[] = []
  let currentText = ''
  let currentHighlight = false

  for (let mi = 0; mi < n; mi++) {
    const isMatch = lcsSet.has(mi)
    const highlight = !isMatch

    if (mi === 0) {
      currentHighlight = highlight
      currentText = modified[mi]
    } else if (highlight === currentHighlight) {
      currentText += modified[mi]
    } else {
      segments.push({ text: currentText, highlight: currentHighlight })
      currentText = modified[mi]
      currentHighlight = highlight
    }
  }

  // 推入最后一段
  if (currentText) {
    segments.push({ text: currentText, highlight: currentHighlight })
  }

  return segments
}
