/**
 * 排序算法可视化 - 动画步骤生成器
 * 记录每一步的数组状态和操作描述，供可视化组件播放
 */

/**
 * 生成归并排序的动画步骤
 * @param {number[]} arr - 原始数组
 * @returns {object[]} steps - 动画步骤数组
 */
export function generateMergeSortSteps(arr) {
  const steps = []
  const array = [...arr]
  const n = array.length
  // 辅助数组用于归并
  const temp = new Array(n)

  // 记录初始状态
  recordStep(steps, array, { description: '初始数组' })

  function mergeSort(lo, hi) {
    if (lo >= hi) {
      recordStep(steps, array, {
        sorted: [lo],
        range: [lo, hi],
        description: `单个元素 [${array[lo]}], 无需排序`
      })
      return
    }

    const mid = Math.floor((lo + hi) / 2)
    recordStep(steps, array, {
      range: [lo, hi],
      description: `拆分: [${lo}..${hi}] → [${lo}..${mid}] 和 [${mid+1}..${hi}]`
    })

    mergeSort(lo, mid)
    mergeSort(mid + 1, hi)

    // 归并
    merge(lo, mid, hi)
  }

  function merge(lo, mid, hi) {
    // 复制到辅助数组
    for (let i = lo; i <= hi; i++) {
      temp[i] = array[i]
    }

    recordStep(steps, array, {
      range: [lo, hi],
      merging: { left: [lo, mid], right: [mid + 1, hi] },
      description: `开始归并 [${lo}..${mid}] 和 [${mid+1}..${hi}]`
    })

    let i = lo, j = mid + 1

    for (let k = lo; k <= hi; k++) {
      if (i > mid) {
        // 左边已取完
        recordStep(steps, array, {
          range: [lo, hi],
          comparing: [i > mid ? i - 1 : i, j],
          merging: { left: [lo, mid], right: [mid + 1, hi] },
          description: `左半部分已取完, 取右半部分元素 ${temp[j]}`
        })
        array[k] = temp[j++]
        recordStep(steps, array, {
          range: [lo, hi],
          merging: { left: [lo, mid], right: [mid + 1, hi] },
          sortedIndices: getSortedRange(lo, k),
          description: `放置元素 ${array[k]} 到位置 ${k}`
        })
      } else if (j > hi) {
        // 右边已取完
        recordStep(steps, array, {
          range: [lo, hi],
          comparing: [i, j > hi ? j - 1 : j],
          merging: { left: [lo, mid], right: [mid + 1, hi] },
          description: `右半部分已取完, 取左半部分元素 ${temp[i]}`
        })
        array[k] = temp[i++]
        recordStep(steps, array, {
          range: [lo, hi],
          merging: { left: [lo, mid], right: [mid + 1, hi] },
          sortedIndices: getSortedRange(lo, k),
          description: `放置元素 ${array[k]} 到位置 ${k}`
        })
      } else if (temp[i] <= temp[j]) {
        // 左 <= 右, 取左边的
        recordStep(steps, array, {
          range: [lo, hi],
          comparing: [i, j],
          merging: { left: [lo, mid], right: [mid + 1, hi] },
          description: `比较 ${temp[i]} ≤ ${temp[j]}, 取左半部分元素 ${temp[i]}`
        })
        array[k] = temp[i++]
        recordStep(steps, array, {
          range: [lo, hi],
          merging: { left: [lo, mid], right: [mid + 1, hi] },
          sortedIndices: getSortedRange(lo, k),
          description: `放置元素 ${array[k]} 到位置 ${k}`
        })
      } else {
        // 左 > 右, 取右边的
        recordStep(steps, array, {
          range: [lo, hi],
          comparing: [i, j],
          merging: { left: [lo, mid], right: [mid + 1, hi] },
          description: `比较 ${temp[i]} > ${temp[j]}, 取右半部分元素 ${temp[j]}`
        })
        array[k] = temp[j++]
        recordStep(steps, array, {
          range: [lo, hi],
          merging: { left: [lo, mid], right: [mid + 1, hi] },
          sortedIndices: getSortedRange(lo, k),
          description: `放置元素 ${array[k]} 到位置 ${k}`
        })
      }
    }

    // 标记整个范围为已排好序
    const sortedIndices = []
    for (let k = lo; k <= hi; k++) sortedIndices.push(k)
    recordStep(steps, array, {
      sorted: sortedIndices,
      range: [lo, hi],
      description: `归并完成: [${lo}..${hi}] 已排好序`
    })
  }

  function getSortedRange(lo, k) {
    const indices = []
    for (let i = lo; i <= k; i++) indices.push(i)
    return indices
  }

  mergeSort(0, n - 1)

  // 最终完成
  const allSorted = array.map((_, i) => i)
  recordStep(steps, array, {
    sorted: allSorted,
    description: '✅ 归并排序完成!'
  })

  return steps
}

/**
 * 生成快速排序的动画步骤
 * @param {number[]} arr - 原始数组
 * @returns {object[]} steps - 动画步骤数组
 */
export function generateQuickSortSteps(arr) {
  const steps = []
  const array = [...arr]
  const n = array.length

  recordStep(steps, array, { description: '初始数组' })

  function quickSort(lo, hi) {
    if (lo >= hi) {
      if (lo === hi) {
        recordStep(steps, array, {
          sorted: [lo],
          pivot: lo,
          description: `单个元素 [${array[lo]}], 已就位`
        })
      }
      return
    }

    recordStep(steps, array, {
      range: [lo, hi],
      description: `对区间 [${lo}..${hi}] 执行快速排序`
    })

    const pivotIndex = partition(lo, hi)

    // 标记 pivot 为已排好序
    recordStep(steps, array, {
      sorted: [pivotIndex],
      range: [lo, hi],
      description: `基准元素 ${array[pivotIndex]} 已就位于位置 ${pivotIndex}`
    })

    quickSort(lo, pivotIndex - 1)
    quickSort(pivotIndex + 1, hi)
  }

  function partition(lo, hi) {
    // 选择最右边的元素作为 pivot
    const pivotValue = array[hi]
    let i = lo - 1

    recordStep(steps, array, {
      range: [lo, hi],
      pivot: hi,
      description: `选择基准元素 pivot = ${pivotValue} (位置 ${hi})`
    })

    for (let j = lo; j < hi; j++) {
      recordStep(steps, array, {
        range: [lo, hi],
        pivot: hi,
        comparing: [j, hi],
        description: `比较 array[${j}] = ${array[j]} 与 pivot = ${pivotValue}`
      })

      if (array[j] <= pivotValue) {
        i++
        if (i !== j) {
          // 交换
          ;[array[i], array[j]] = [array[j], array[i]]
          recordStep(steps, array, {
            range: [lo, hi],
            pivot: hi,
            swapping: [i, j],
            description: `${array[j]} ≤ ${pivotValue}, 交换位置 ${i} 和 ${j}`
          })
        } else {
          recordStep(steps, array, {
            range: [lo, hi],
            pivot: hi,
            description: `${array[j]} ≤ ${pivotValue}, i = j = ${i}, 无需交换`
          })
        }
      }
    }

    // 将 pivot 放到正确位置
    if (i + 1 !== hi) {
      ;[array[i + 1], array[hi]] = [array[hi], array[i + 1]]
      recordStep(steps, array, {
        range: [lo, hi],
        swapping: [i + 1, hi],
        pivot: i + 1,
        description: `将基准元素 ${pivotValue} 放到正确位置 ${i + 1}`
      })
    } else {
      recordStep(steps, array, {
        range: [lo, hi],
        pivot: hi,
        description: `基准元素已在正确位置 ${hi}`
      })
    }

    return i + 1
  }

  quickSort(0, n - 1)

  const allSorted = array.map((_, i) => i)
  recordStep(steps, array, {
    sorted: allSorted,
    description: '✅ 快速排序完成!'
  })

  return steps
}

/**
 * 生成随机数组
 * @param {number} size
 * @param {number} maxValue
 * @returns {number[]}
 */
export function generateRandomArray(size = 10, maxValue = 50) {
  const arr = []
  for (let i = 0; i < size; i++) {
    arr.push(Math.floor(Math.random() * maxValue) + 1)
  }
  return arr
}

function recordStep(steps, array, info) {
  steps.push({
    array: [...array],
    highlights: {
      comparing: info.comparing || null,
      swapping: info.swapping || null,
      pivot: info.pivot ?? null,
      sorted: info.sorted || null,
      sortedIndices: info.sortedIndices || null,
      range: info.range || null,
      merging: info.merging || null
    },
    description: info.description || ''
  })
}
