import { Snowflake } from '@sapphire/snowflake'

/**
 * 得到雪花ID
 */
export function getSnowflake(): bigint {
  const epoch = new Date('2025-07-01T00:00:00.000Z')
  const snowflake = new Snowflake(epoch)
  snowflake.workerId = 1
  return snowflake.generate()
}

/**
 * 并发控制池，限制同时执行的异步任务数量
 * @param tasks 异步任务数组（每个任务为返回 Promise 的函数）
 * @param concurrency 最大并发数
 * @returns Promise，解析为所有任务结果的数组
 */
export async function concurrentPool<T>(tasks: (() => Promise<T>)[], concurrency: number): Promise<T[]> {
  // 存储所有任务的结果
  const results: T[] = []
  // 存储当前正在执行的任务
  const executing: Promise<void>[] = []
  let index = 0 // 任务索引，用于按顺序添加任务

  // 创建执行器函数
  const execute = async (taskIndex: number): Promise<void> => {
    try {
      // 执行任务并获取结果
      const result = await tasks[taskIndex]!()
      results[taskIndex] = result // 按原始顺序存储结果
    }
    catch (error) {
      results[taskIndex] = error as any // 捕获错误（可根据需求调整）
    }
    finally {
      // 无论成功失败，任务完成后从执行队列移除
      const executingIndex = executing.findIndex(p => p === executing[taskIndex])
      if (executingIndex !== -1) {
        executing.splice(executingIndex, 1)
      }
    }
  }

  // 启动初始并发任务
  while (index < Math.min(concurrency, tasks.length)) {
    const taskPromise = execute(index)
    executing.push(taskPromise)
    index++
  }

  // 动态管理任务池
  while (index < tasks.length) {
    if (executing.length < concurrency) {
      const taskPromise = execute(index)
      executing.push(taskPromise)
      index++
    }
    else {
      // 等待任意一个任务完成
      await Promise.race(executing)
    }
  }

  // 等待所有剩余任务完成
  await Promise.all(executing)
  return results
}

/**
 * 判断连个版本号大于小于或者等于
 * @param v1 - 版本号1
 * @param v2 - 版本号2
 * @returns -
 * 当 v1 大于 v2 时返回 1
 * 当 v1 等于 v2 时返回 0
 * 当 v1 小于 v2 时返回 -1
 */
export function compareVersion(v1: string, v2: string, operator: '_' | '-' | '.' = '.'): -1 | 0 | 1 {
  if (v1 === v2) {
    return 0
  }

  const vs1 = v1.split(operator).map(a => Number.parseInt(a))
  const vs2 = v2.split(operator).map(a => Number.parseInt(a))

  const length = Math.min(vs1.length, vs2.length)
  for (let i = 0; i < length; i++) {
    const s1 = vs1[i] || 0
    const s2 = vs2[i] || 0
    if (s1 > s2) {
      return 1
    }
    else if (s1 < s2) {
      return -1
    }
  }
  if (length === vs1.length) {
    return -1
  }
  else {
    return 1
  }
}
