import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { SecretService } from '@/modules/shared/secret/secret.service';
import Wechatpay = require('wechatpay-node-v3');

@Injectable()
export class WechatPayService {
  private readonly logger = new Logger(WechatPayService.name);
  private pay: Wechatpay;
  private initialized = false;

  constructor(
    private configService: ConfigService,
    private secretService: SecretService,
  ) {
    this.initPayClient();
  }

  /**
   * 初始化微信支付客户端
   */
  private async initPayClient() {
    try {
      const appid = await this.secretService.getDecryptedValue('WECHAT_APPID');
      const mchid = await this.secretService.getDecryptedValue('WECHAT_MCHID');
      const privateKey = await this.secretService.getDecryptedValue('WECHAT_PRIVATE_KEY');
      const serialNo = await this.secretService.getDecryptedValue('WECHAT_SERIAL_NO');
      const apiv3Key = await this.secretService.getDecryptedValue('WECHAT_APIV3_KEY');

      if (!appid || !mchid || !privateKey || !serialNo || !apiv3Key) {
        this.logger.warn('微信支付配置不完整，支付功能将不可用');
        return;
      }

      this.pay = new Wechatpay({
        appid,
        mchid,
        publicKey: Buffer.from(privateKey.replace(/\\n/g, '\n')),
        privateKey: Buffer.from(privateKey.replace(/\\n/g, '\n')),
        serial_no: serialNo,
        key: apiv3Key,
      });

      this.initialized = true;
      this.logger.log('微信支付客户端初始化成功');
    } catch (error) {
      this.logger.error(`微信支付客户端初始化失败: ${error.message}`, error.stack);
    }
  }

  /**
   * JSAPI下单（小程序支付）
   */
  async createJsapiOrder(params: {
    orderNo: string;
    description: string;
    amount: number;
    openid: string;
    notifyUrl: string;
  }) {
    if (!this.initialized || !this.pay) {
      throw new Error('微信支付未配置');
    }

    try {
      const result = await this.pay.transactions_jsapi({
        appid: this.configService.get<string>('WECHAT_APPID'),
        mchid: this.configService.get<string>('WECHAT_MCHID'),
        description: params.description,
        out_trade_no: params.orderNo,
        notify_url: params.notifyUrl,
        amount: {
          total: Math.round(params.amount * 100), // 转换为分
          currency: 'CNY',
        },
        payer: {
          openid: params.openid,
        },
      });

      this.logger.log(`微信支付下单成功: ${params.orderNo}`);
      return result;
    } catch (error) {
      this.logger.error(`微信支付下单失败: ${error.message}`, error.stack);
      throw new Error(`微信支付下单失败: ${error.message}`);
    }
  }

  /**
   * 查询订单
   */
  async queryOrder(orderNo: string) {
    if (!this.initialized || !this.pay) {
      throw new Error('微信支付未配置');
    }

    try {
      const result = await this.pay.query({
        out_trade_no: orderNo,
      });
      return result;
    } catch (error) {
      this.logger.error(`查询微信支付订单失败: ${error.message}`, error.stack);
      throw new Error(`查询订单失败: ${error.message}`);
    }
  }

  /**
   * 关闭订单
   */
  async closeOrder(orderNo: string) {
    if (!this.initialized || !this.pay) {
      throw new Error('微信支付未配置');
    }

    try {
      await this.pay.close(orderNo);
      this.logger.log(`关闭微信支付订单: ${orderNo}`);
    } catch (error) {
      this.logger.error(`关闭微信支付订单失败: ${error.message}`, error.stack);
      throw new Error(`关闭订单失败: ${error.message}`);
    }
  }

  /**
   * 申请退款
   */
  async refund(params: {
    orderNo: string;
    refundNo: string;
    totalAmount: number;
    refundAmount: number;
    reason: string;
    notifyUrl?: string;
  }) {
    if (!this.initialized || !this.pay) {
      throw new Error('微信支付未配置');
    }

    try {
      const result = await this.pay.refunds({
        out_trade_no: params.orderNo,
        out_refund_no: params.refundNo,
        reason: params.reason,
        notify_url: params.notifyUrl,
        amount: {
          refund: Math.round(params.refundAmount * 100),
          total: Math.round(params.totalAmount * 100),
          currency: 'CNY',
        },
      });

      this.logger.log(`微信支付退款成功: ${params.refundNo}`);
      return result;
    } catch (error) {
      this.logger.error(`微信支付退款失败: ${error.message}`, error.stack);
      throw new Error(`退款失败: ${error.message}`);
    }
  }

  /**
   * 查询退款
   */
  async queryRefund(refundNo: string) {
    if (!this.initialized || !this.pay) {
      throw new Error('微信支付未配置');
    }

    try {
      const result = await this.pay.find_refunds(refundNo);
      return result;
    } catch (error) {
      this.logger.error(`查询微信退款失败: ${error.message}`, error.stack);
      throw new Error(`查询退款失败: ${error.message}`);
    }
  }

  /**
   * 验证回调签名
   */
  async verifySignature(params: {
    timestamp: string;
    nonce: string;
    body: string;
    signature: string;
    serial: string;
  }): Promise<boolean> {
    if (!this.initialized || !this.pay) {
      throw new Error('微信支付未配置');
    }

    try {
      return await this.pay.verifySign(params);
    } catch (error) {
      this.logger.error(`验证微信支付签名失败: ${error.message}`, error.stack);
      return false;
    }
  }

  /**
   * 解密回调数据
   */
  decryptData(ciphertext: string, nonce: string, associatedData: string): any {
    if (!this.initialized || !this.pay) {
      throw new Error('微信支付未配置');
    }

    try {
      return this.pay.decipher_gcm(ciphertext, associatedData, nonce);
    } catch (error) {
      this.logger.error(`解密微信支付数据失败: ${error.message}`, error.stack);
      throw new Error(`解密数据失败: ${error.message}`);
    }
  }
}
