import { Injectable, Logger, InternalServerErrorException } from '@nestjs/common'
import * as crypto from 'crypto'
import axios from 'axios'

const WX_APPID = requireEnv('WX_APPID')
const WX_SECRET = requireEnv('WX_SECRET')
const VP_APPKEY = requireEnv('VP_APPKEY')
const VP_APPKEY_SANDBOX = requireEnv('VP_APPKEY_SANDBOX')
const VP_OFFER_ID = requireEnv('VP_OFFER_ID')

function requireEnv(name: string): string {
  const val = process.env[name]
  if (!val) throw new InternalServerErrorException(`环境变量 ${name} 未配置`)
  return val
}

@Injectable()
export class VirtualPaymentService {
  private readonly logger = new Logger(VirtualPaymentService.name)

  /** 计算支付签名 pay_sig */
  computePaySig(uri: string, postBody: string, env: number): string {
    const appKey = env === 1 ? VP_APPKEY_SANDBOX : VP_APPKEY
    const data = `${uri}&${postBody}`
    return crypto.createHmac('sha256', appKey).update(data).digest('hex')
  }

  /** 通过 wx.login code 换取 session_key 并计算用户态签名 */
  async exchangeCodeAndSign(code: string, signData: string): Promise<{ openid: string; signature: string }> {
    const res = await axios.get('https://api.weixin.qq.com/sns/jscode2session', {
      params: { appid: WX_APPID, secret: WX_SECRET, js_code: code, grant_type: 'authorization_code' },
      timeout: 10000,
    })
    if (res.data.errcode) {
      throw new Error(`code2session 失败: ${res.data.errmsg}`)
    }
    const { openid, session_key } = res.data
    if (!session_key) {
      throw new Error('未获取到 session_key')
    }
    const signature = crypto.createHmac('sha256', session_key).update(signData).digest('hex')
    return { openid, signature }
  }

  /** 构建 signData JSON 字符串（与 wx.requestVirtualPayment 要求的格式一致） */
  buildSignData(outTradeNo: string, openid: string, totalFee: number, userIp: string, env: number, mode: string, buyQuantity?: number): string {
    const base = {
      offerId: VP_OFFER_ID,
      env,
      outTradeNo,
      attach: outTradeNo,
      currencyType: 'CNY' as const,
      platform: 'android' as const,
      zoneId: '',
    }
    if (mode === 'short_series_coin') {
      // 代币充值
      return JSON.stringify({
        ...base,
        buyQuantity: buyQuantity || 1,
      })
    }
    // short_series_goods — 道具直购
    return JSON.stringify({
      ...base,
      productId: openid,
      goodsPrice: totalFee,
    })
  }

  getOfferId(): string { return VP_OFFER_ID }

  /** 验证消息推送签名（可选，依赖配置的 Token） */
  verifyPushSignature(signature: string, timestamp: string, nonce: string, token: string): boolean {
    const arr = [token, timestamp, nonce].sort()
    const sha1 = crypto.createHash('sha1').update(arr.join('')).digest('hex')
    return sha1 === signature
  }
}
