const https = require('https')
const config = require('../config')

function requestJson(url) {
  return new Promise((resolve, reject) => {
    https.get(url, res => {
      let raw = ''
      res.on('data', chunk => { raw += chunk })
      res.on('end', () => {
        try { resolve(JSON.parse(raw)) } catch (err) { reject(err) }
      })
    }).on('error', reject)
  })
}

function postJson(url, body) {
  return new Promise((resolve, reject) => {
    const data = JSON.stringify(body || {})
    const req = https.request(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Content-Length': Buffer.byteLength(data)
      }
    }, res => {
      let raw = ''
      res.on('data', chunk => { raw += chunk })
      res.on('end', () => {
        try { resolve(JSON.parse(raw)) } catch (err) { reject(err) }
      })
    })
    req.on('error', reject)
    req.write(data)
    req.end()
  })
}

let accessTokenCache = null

async function getAccessToken() {
  if (accessTokenCache && accessTokenCache.expiresAt > Date.now() + 60000) return accessTokenCache.token
  if (!config.wechat.appid || !config.wechat.secret) throw new Error('WECHAT_APPID or WECHAT_SECRET is not configured')
  const url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + encodeURIComponent(config.wechat.appid) + '&secret=' + encodeURIComponent(config.wechat.secret)
  const data = await requestJson(url)
  if (!data.access_token) throw new Error(data.errmsg || 'wechat access_token failed')
  accessTokenCache = {
    token: data.access_token,
    expiresAt: Date.now() + (Number(data.expires_in || 7200) * 1000)
  }
  return accessTokenCache.token
}

async function code2Session(code) {
  if (!config.wechat.appid || !config.wechat.secret) {
    throw new Error('WECHAT_APPID or WECHAT_SECRET is not configured')
  }
  const url = 'https://api.weixin.qq.com/sns/jscode2session?appid=' + encodeURIComponent(config.wechat.appid) + '&secret=' + encodeURIComponent(config.wechat.secret) + '&js_code=' + encodeURIComponent(code) + '&grant_type=authorization_code'
  const data = await requestJson(url)
  if (!data.openid) throw new Error(data.errmsg || 'wechat login failed')
  return data
}

async function getPhoneNumber(code) {
  if (!code) throw new Error('phone code required')
  const token = await getAccessToken()
  const url = 'https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=' + encodeURIComponent(token)
  const data = await postJson(url, { code })
  if (data.errcode) throw new Error(data.errmsg || 'get phone number failed')
  return data.phone_info || null
}

module.exports = { code2Session, getPhoneNumber }
