import crypto from "crypto"

export interface WechatPayConfig {
  appId: string
  appSecret: string
  mchId: string
  apiKey: string
  notifyUrl: string
}

export class WechatPayService {
  constructor(private config: WechatPayConfig) {}

  // 创建微信支付订单（扫码支付）
  async createOrder(params: {
    outTradeNo: string
    body: string
    totalFee: number
    spbillCreateIp: string
  }) {
    const orderParams = {
      appid: this.config.appId,
      mch_id: this.config.mchId,
      nonce_str: this.generateNonceStr(),
      body: params.body,
      out_trade_no: params.outTradeNo,
      total_fee: Math.round(params.totalFee * 100).toString(), // 转换为分
      spbill_create_ip: params.spbillCreateIp,
      notify_url: this.config.notifyUrl,
      trade_type: "NATIVE", // 扫码支付
    }

    const sign = this.generateSign(orderParams)
    const xmlData = this.buildXML({ ...orderParams, sign })

    // In production, make actual API call to WeChat
    // const response = await fetch("https://api.mch.weixin.qq.com/pay/unifiedorder", {
    //   method: "POST",
    //   body: xmlData,
    //   headers: { "Content-Type": "application/xml" },
    // })

    // Mock response for development
    return {
      codeUrl: `weixin://wxpay/bizpayurl?pr=${this.generateNonceStr()}`,
      prepayId: `prepay_${Date.now()}`,
      outTradeNo: params.outTradeNo,
    }
  }

  // 生成随机字符串
  private generateNonceStr(): string {
    return crypto.randomBytes(16).toString("hex")
  }

  // 生成签名
  generateSign(params: Record<string, string>): string {
    const sortedKeys = Object.keys(params).sort()
    const signString = sortedKeys
      .filter((key) => params[key] && key !== "sign")
      .map((key) => `${key}=${params[key]}`)
      .join("&")

    const signWithKey = `${signString}&key=${this.config.apiKey}`
    return crypto.createHash("md5").update(signWithKey, "utf8").digest("hex").toUpperCase()
  }

  // 验证签名
  verifySign(params: Record<string, string>): boolean {
    const receivedSign = params.sign
    if (!receivedSign) return false

    const calculatedSign = this.generateSign(params)
    return receivedSign === calculatedSign
  }

  // 构建XML数据
  private buildXML(params: Record<string, string>): string {
    const xml = ["<xml>"]
    for (const [key, value] of Object.entries(params)) {
      xml.push(`<${key}><![CDATA[${value}]]></${key}>`)
    }
    xml.push("</xml>")
    return xml.join("")
  }

  // 解析XML数据
  private async parseXML(xml: string): Promise<Record<string, string>> {
    const result: Record<string, string> = {}
    const regex = /<(\w+)><!\[CDATA\[(.*?)\]\]><\/\1>/g
    let match

    while ((match = regex.exec(xml)) !== null) {
      result[match[1]] = match[2]
    }

    return result
  }
}
