import { DataSource } from 'typeorm';
import WxPay from 'wechatpay-node-v3';
import { Buffer } from 'buffer';
import { PaymentEntity } from '../entities/payment.entity.js';
import { PaymentStatus } from '../entities/payment.types.js';
import { PaymentCreateResponse } from '../entities/payment.types.js';

/**
 * 微信支付服务
 * 使用微信支付v3 SDK，支持小程序支付
 */
export class PaymentService {
  private readonly wxPay: WxPay;
  private readonly merchantId: string;
  private readonly appId: string;
  private readonly v3Key: string;
  private readonly notifyUrl: string;

  constructor(
    private readonly dataSource: DataSource
  ) {
    // 从环境变量获取支付配置
    this.merchantId = process.env.WECHAT_MERCHANT_ID || '';
    this.appId = process.env.WX_MINI_APP_ID || '';
    this.v3Key = process.env.WECHAT_V3_KEY || '';
    this.notifyUrl = process.env.WECHAT_PAY_NOTIFY_URL || '';
    const certSerialNo = process.env.WECHAT_MERCHANT_CERT_SERIAL_NO || '';

    if (!this.merchantId || !this.appId || !this.v3Key || !certSerialNo) {
      throw new Error('微信支付配置不完整，请检查环境变量');
    }

    // 处理证书字符串，将 \n 转换为实际换行符
    const publicKey = (process.env.WECHAT_PUBLIC_KEY || '').replace(/\\n/g, '\n');
    const privateKey = (process.env.WECHAT_PRIVATE_KEY || '').replace(/\\n/g, '\n');

    // 初始化微信支付SDK
    this.wxPay = new WxPay({
      appid: this.appId,
      mchid: this.merchantId,
      publicKey: Buffer.from(publicKey),
      privateKey: Buffer.from(privateKey),
      key: this.v3Key,
      serial_no: certSerialNo
    });
  }

  /**
   * 创建微信支付订单
   * @param externalOrderId 外部订单ID
   * @param userId 用户ID
   * @param totalAmount 支付金额（分）
   * @param description 支付描述
   * @param openid 用户OpenID
   */
  async createPayment(
    externalOrderId: number,
    userId: number,
    totalAmount: number,
    description: string,
    openid: string
  ): Promise<PaymentCreateResponse> {
    // 检查是否已存在相同外部订单ID的支付记录
    const paymentRepository = this.dataSource.getRepository(PaymentEntity);
    const existingPayment = await paymentRepository.findOne({
      where: { externalOrderId }
    });

    if (existingPayment) {
      if (existingPayment.paymentStatus !== PaymentStatus.PENDING) {
        throw new Error('该订单已存在支付记录且状态不正确');
      }
      // 如果存在待支付的记录，可以更新或重新创建，这里选择重新创建
      await paymentRepository.remove(existingPayment);
    }

    if (!openid) {
      throw new Error('用户OpenID不能为空');
    }

    try {
      // 创建商户订单号
      const outTradeNo = `PAYMENT_${externalOrderId}_${Date.now()}`;

      // 使用微信支付SDK创建JSAPI支付
      const result = await this.wxPay.transactions_jsapi({
        appid: this.appId,
        mchid: this.merchantId,
        description,
        out_trade_no: outTradeNo,
        notify_url: this.notifyUrl,
        amount: {
          total: totalAmount,
        },
        payer: {
          openid
        }
      });

      console.debug('微信支付SDK返回结果:', result);

      // 从 package 字段中提取 prepay_id
      const prepayId = result.package ? result.package.replace('prepay_id=', '') : undefined;

      // 创建支付记录
      const payment = new PaymentEntity();
      payment.externalOrderId = externalOrderId;
      payment.userId = userId;
      payment.totalAmount = totalAmount;
      payment.description = description;
      payment.paymentStatus = PaymentStatus.PROCESSING;
      payment.outTradeNo = outTradeNo;
      payment.openid = openid;

      await paymentRepository.save(payment);

      // 直接返回微信支付SDK生成的参数
      return {
        paymentId: prepayId,
        timeStamp: result.timeStamp,
        nonceStr: result.nonceStr,
        package: result.package,
        signType: result.signType,
        paySign: result.paySign,
        totalAmount: totalAmount // 添加金额字段用于前端验证
      };
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : '未知错误';
      throw new Error(`微信支付创建失败: ${errorMessage}`);
    }
  }

  /**
   * 处理支付回调
   */
  async handlePaymentCallback(
    callbackData: any,
    headers: any,
    rawBody: string // 添加原始请求体参数
  ): Promise<void> {
    console.debug('收到支付回调请求:', {
      headers,
      callbackData,
      rawBody
    });

    // 验证回调签名
    const isValid = await this.wxPay.verifySign({
      timestamp: headers['wechatpay-timestamp'],
      nonce: headers['wechatpay-nonce'],
      body: rawBody, // 优先使用原始请求体
      serial: headers['wechatpay-serial'],
      signature: headers['wechatpay-signature']
    });

    console.debug('回调签名验证结果:', isValid);

    if (!isValid) {
      throw new Error('回调签名验证失败');
    }

    // 解密回调数据
    const decryptedData = this.wxPay.decipher_gcm(
      callbackData.resource.ciphertext,
      callbackData.resource.associated_data || '',
      callbackData.resource.nonce
    );

    console.log('解密回调数据', decryptedData)
    console.log('解密回调数据类型:', typeof decryptedData)

    // 处理解密后的数据，可能是字符串或对象
    let parsedData;
    if (typeof decryptedData === 'string') {
      parsedData = JSON.parse(decryptedData);
    } else {
      parsedData = decryptedData;
    }

    const paymentRepository = this.dataSource.getRepository(PaymentEntity);
    const outTradeNo = parsedData.out_trade_no;
    const payment = await paymentRepository.findOne({
      where: { outTradeNo }
    });

    if (!payment) {
      throw new Error('支付记录不存在');
    }

    // 根据回调结果更新支付状态
    if (parsedData.trade_state === 'SUCCESS') {
      payment.paymentStatus = PaymentStatus.PAID;
      payment.wechatTransactionId = parsedData.transaction_id;
    } else if (parsedData.trade_state === 'FAIL') {
      payment.paymentStatus = PaymentStatus.FAILED;
    } else if (parsedData.trade_state === 'REFUND') {
      payment.paymentStatus = PaymentStatus.REFUNDED;
    }

    await paymentRepository.save(payment);
  }

  /**
   * 查询支付状态
   */
  async getPaymentStatus(externalOrderId: number): Promise<PaymentStatus> {
    const paymentRepository = this.dataSource.getRepository(PaymentEntity);
    const payment = await paymentRepository.findOne({
      where: { externalOrderId }
    });

    if (!payment) {
      throw new Error('支付记录不存在');
    }

    return payment.paymentStatus;
  }

  /**
   * 生成随机字符串
   */
  private generateNonceStr(length: number = 32): string {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let result = '';
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return result;
  }

  /**
   * 生成回调签名（用于测试）
   */
  generateCallbackSignature(
    timestamp: string,
    nonce: string,
    callbackData: any
  ): string {
    return this.wxPay.getSignature(
      'POST',
      nonce,
      timestamp,
      '/v3/pay/transactions/jsapi',
      callbackData
    );
  }

  /**
   * 获取微信支付平台证书（用于测试）
   */
  async getPlatformCertificates(): Promise<any> {
    try {
      console.debug('开始获取微信支付平台证书...');
      const certificates = await this.wxPay.get_certificates(this.v3Key);
      console.debug('获取平台证书成功:', certificates);
      return certificates;
    } catch (error) {
      console.debug('获取平台证书失败:', error);
      throw error;
    }
  }
}