const axios = require('axios')
const env = require('../config/env')
const AppError = require('../utils/appError')

let accessTokenCache = {
    token: '',
    expiresAt: 0,
}

async function getWxOpenId(code) {
    if (!env.wechatAppId || !env.wechatSecret) {
        throw new AppError('微信小程序配置缺失', 500)
    }

    try {
        const url = 'https://api.weixin.qq.com/sns/jscode2session'
        const response = await axios.get(url, {
            params: {
                appid: env.wechatAppId,
                secret: env.wechatSecret,
                js_code: code,
                grant_type: 'authorization_code',
            },
            timeout: 10000,
        })

        const data = response.data || {}

        if (data.openid) {
            return data.openid
        }

        if (data.errcode || data.errmsg) {
            throw new AppError(`获取OpenID失败: ${data.errcode || ''} ${data.errmsg || ''}`.trim(), 502, {
                wechat: data,
            })
        }

        throw new AppError('获取OpenID失败: 响应中未包含openid', 502)
    } catch (error) {
        if (error instanceof AppError) throw error
        throw new AppError(`获取微信OpenID时发生错误: ${error.message}`, 502)
    }
}

async function getWechatAccessToken() {
    if (accessTokenCache.token && Date.now() < accessTokenCache.expiresAt) {
        return accessTokenCache.token
    }

    try {
        const response = await axios.get('https://api.weixin.qq.com/cgi-bin/token', {
            params: {
                grant_type: 'client_credential',
                appid: env.wechatAppId,
                secret: env.wechatSecret,
            },
            timeout: 10000,
        })

        const data = response.data || {}

        if (!data.access_token) {
            throw new AppError(`获取微信 access_token 失败: ${data.errcode || ''} ${data.errmsg || ''}`.trim(), 502, {
                wechat: data,
            })
        }

        accessTokenCache = {
            token: data.access_token,
            expiresAt: Date.now() + Math.max((data.expires_in || 7200) - 300, 60) * 1000,
        }

        return accessTokenCache.token
    } catch (error) {
        if (error instanceof AppError) throw error
        throw new AppError(`获取微信 access_token 时发生错误: ${error.message}`, 502)
    }
}

async function getWxPhoneNumber(phoneCode) {
    const accessToken = await getWechatAccessToken()

    try {
        const response = await axios.post(
            `https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=${accessToken}`,
            {
                code: phoneCode,
            },
            {
                headers: {
                    'Content-Type': 'application/json',
                },
                timeout: 10000,
            }
        )

        const data = response.data || {}
        const phone = data.phone_info?.purePhoneNumber || data.phone_info?.phoneNumber

        if (phone) {
            return phone
        }

        throw new AppError(`获取微信手机号失败: ${data.errcode || ''} ${data.errmsg || ''}`.trim(), 502, {
            wechat: data,
        })
    } catch (error) {
        if (error instanceof AppError) throw error
        throw new AppError(`获取微信手机号时发生错误: ${error.message}`, 502)
    }
}

module.exports = {
    getWxOpenId,
    getWxPhoneNumber,
}
