// 随机扰动函数
function randomPerturbation(scale = 1e-7) {
    return (Math.random() * 2 - 1) * scale
}

// Haversine 公式计算两点距离（米）
function haversine(lat1, lon1, lat2, lon2) {
    const R = 6371000
    const toRad = (deg) => deg * Math.PI / 180
    const phi1 = toRad(lat1)
    const phi2 = toRad(lat2)
    const dphi = toRad(lat2 - lat1)
    const dlambda = toRad(lon2 - lon1)

    const a = Math.sin(dphi / 2) ** 2 + Math.cos(phi1) * Math.cos(phi2) * Math.sin(dlambda / 2) ** 2
    return 2 * R * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
}

/**
 * 根据原路径时间，重新生成新的时间路径数据
 */
function getPathData(pathlist, runEndTime, useTime) {
    const startTime = (runEndTime - useTime) * 1000
    const oldStartTime = parseInt(pathlist[0].d.split(' ')[0])

    const newPathlist = pathlist.map((item, i) => {
        const newItem = { ...item }
        const [oldTimeStr, suffix] = item.d.split(' ', 2)
        const oldTime = parseInt(oldTimeStr)

        if (i === 0) {
            newItem.d = `${startTime} ${suffix}`
        } else {
            const newTime = startTime + oldTime - oldStartTime
            newItem.d = `${newTime} ${suffix}`
            newItem.a += randomPerturbation()
            newItem.o += randomPerturbation()
        }
        return newItem
    })

    return newPathlist
}

/**
 * 选择打卡点
 */
function selectCheckpoints(path, checkpoints, runLogNum, pointUpdateDistance, logMaxDistance, runEndTime, pathTime) {
    const results = []
    let totalDistance = 0
    let lastCheckpointDistance = 0

    // 筛选有效打卡点
    const filteredCheckpoints = checkpoints
        .filter(cp => cp.is_del === "0" && cp.is_online === 1 && cp.ctrl_status === "1")
    // 打乱顺序
    for (let i = filteredCheckpoints.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1))
        // 避免解构交换在部分运行环境下触发 TDZ 相关异常
        const temp = filteredCheckpoints[i]
        filteredCheckpoints[i] = filteredCheckpoints[j]
        filteredCheckpoints[j] = temp
    }

    const usedCheckpoints = new Set()

    for (const p of path) {
        const parts = p.d.split(' ')
        const tsMs = parseInt(parts[0])
        const stepDistance = parseFloat(parts[1].split('_')[0]) || 0

        totalDistance += stepDistance

        for (const cp of filteredCheckpoints.slice(0, -1)) {
            if (usedCheckpoints.has(cp.id)) continue

            const [lat, lon] = cp.jingwei.split(',').map(Number)
            const dist = haversine(p.a, p.o, lat, lon)

            if (dist < logMaxDistance && (totalDistance - lastCheckpointDistance) > 200) {
                console.log(`选中打卡点 ${cp.id} ${cp.address}，距离：${dist}`)
                results.push({
                    point_id: cp.id,
                    distance: +(totalDistance / 1000).toFixed(2),
                    longitude: p.o,
                    longtitude: p.o, // 保留原字段
                    latitude: p.a,
                    address: cp.address,
                    jingwei: cp.jingwei.split(','),
                    time: Math.floor(tsMs / 1000)
                })
                usedCheckpoints.add(cp.id)
                lastCheckpointDistance = totalDistance
                break
            }
        }
    }

    if (results.length >= runLogNum) {
        // 随机抽取 runLogNum 个打卡点
        const indices = []
        while (indices.length < runLogNum) {
            const idx = Math.floor(Math.random() * results.length)
            if (!indices.includes(idx)) indices.push(idx)
        }
        indices.sort((a, b) => a - b)
        const selectedResults = indices.map(i => results[i])

        const n = selectedResults.length
        let d = 0
        for (let i = 0; i < n; i++) {
            if (selectedResults[i].time >= runEndTime - 5) {
                console.log("打卡点时间异常，重新分配时间")
                for (let j = 0; j < n; j++) {
                    selectedResults[j].time = Math.floor(runEndTime - (pathTime / n) * (n - j))
                    selectedResults[j].distance = d + 0.3 * (j + 1)
                }
                break
            }
        }
        console.log(`选中打卡点：${JSON.stringify(selectedResults)}`)
        return selectedResults
    } else {
        console.log(`选中打卡点数量不足：${JSON.stringify(results)}`)
        return false
    }
}

/**
 * 根据距离和用时生成步频数据
 */
function generateCadence(distanceKm, usedTime) {
    const paceSec = usedTime / distanceKm
    const paceMin = paceSec / 60

    let spmRange
    if (paceMin >= 8) spmRange = [85, 110]
    else if (paceMin >= 5) spmRange = [150, 170]
    else spmRange = [170, 190]

    const minutes = Math.ceil(usedTime / 60)
    const cadenceList = []

    for (let i = 0; i < minutes; i++) {
        let spm = Math.floor(Math.random() * (spmRange[1] - spmRange[0] + 1) + spmRange[0])
        if (i === minutes - 1) {
            const lastDuration = usedTime - (minutes - 1) * 60
            spm = Math.round(spm * (lastDuration / 60))
        }
        cadenceList.push(spm)
    }

    const totalSteps = cadenceList.reduce((a, b) => a + b, 0)

    return {
        cadence_list: cadenceList,
        total_steps: totalSteps
    }
}

module.exports = {
    getPathData,
    selectCheckpoints,
    generateCadence
}