import { AppDataSource } from '../../data-source';
import { Order } from '../orders/order.entity';
import { PaymentStatus, OrderStatus } from '../../share/order.types';
import WxPay from 'wechatpay-node-v3';
import { Buffer } from 'buffer';

/**
 * 微信支付服务
 * 使用微信支付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() {
    // 从环境变量获取支付配置
    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 orderId 订单ID
   * @param totalAmount 支付金额（分）
   * @param description 支付描述
   * @param openid 用户OpenID
   */
  async createPayment(
    orderId: number,
    totalAmount: number,
    description: string,
    openid: string
  ): Promise<{
    paymentId: string;
    timeStamp: string;
    nonceStr: string;
    package: string;
    signType: string;
    paySign: string;
  }> {
    // 验证订单是否存在且状态正确
    const orderRepository = AppDataSource.getRepository(Order);
    const order = await orderRepository.findOne({
      where: { id: orderId }
    });

    if (!order) {
      throw new Error('订单不存在');
    }

    if (order.paymentStatus !== PaymentStatus.PENDING) {
      throw new Error('订单支付状态不正确');
    }

    // 订单金额是元，支付金额是分，需要转换比较
    const orderAmountInCents = Math.round(order.totalAmount * 100);
    if (orderAmountInCents !== totalAmount) {
      throw new Error('支付金额与订单金额不匹配');
    }

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

    try {
      // 使用微信支付SDK创建JSAPI支付
      const result = await this.wxPay.transactions_jsapi({
        appid: this.appId,
        mchid: this.merchantId,
        description,
        out_trade_no: `ORDER_${orderId}_${Date.now()}`,
        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;

      // 更新订单支付状态为处理中
      order.paymentStatus = PaymentStatus.PROCESSING;
      await orderRepository.save(order);

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

  /**
   * 处理支付回调
   */
  async handlePaymentCallback(
    callbackData: {
      id: string;
      create_time: string;
      event_type: string;
      resource_type: string;
      resource: {
        algorithm: string;
        ciphertext: string;
        associated_data?: string;
        nonce: string;
      };
      summary: string;
    },
    headers: {
      'wechatpay-timestamp': string;
      'wechatpay-nonce': string;
      'wechatpay-signature': string;
      'wechatpay-serial': string;
    }
  ): Promise<void> {
    console.debug('收到支付回调请求:', {
      headers,
      callbackData
    });

    // 验证回调签名
    const isValid = await this.wxPay.verifySign({
      timestamp: headers['wechatpay-timestamp'],
      nonce: headers['wechatpay-nonce'],
      body: JSON.stringify(callbackData),
      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
    );

    const parsedData = JSON.parse(decryptedData as string);

    const orderRepository = AppDataSource.getRepository(Order);
    const orderId = parseInt(parsedData.out_trade_no.split('_')[1]);
    const order = await orderRepository.findOne({
      where: { id: orderId }
    });

    if (!order) {
      throw new Error('订单不存在');
    }

    // 根据回调结果更新订单状态
    if (parsedData.trade_state === 'SUCCESS') {
      order.paymentStatus = PaymentStatus.PAID;
      order.status = OrderStatus.WAITING_DEPARTURE;
    } else if (parsedData.trade_state === 'FAIL') {
      order.paymentStatus = PaymentStatus.FAILED;
    } else if (parsedData.trade_state === 'REFUND') {
      order.paymentStatus = PaymentStatus.REFUNDED;
    }

    await orderRepository.save(order);
  }

  /**
   * 生成随机字符串
   */
  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;
  }


  /**
   * 查询支付状态
   */
  async getPaymentStatus(orderId: number): Promise<PaymentStatus> {
    const orderRepository = AppDataSource.getRepository(Order);
    const order = await orderRepository.findOne({
      where: { id: orderId }
    });

    if (!order) {
      throw new Error('订单不存在');
    }

    return order.paymentStatus;
  }

  /**
   * 生成回调签名（用于测试）
   */
  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;
    }
  }
}