import { Injectable, BadRequestException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, DataSource } from 'typeorm';
import { ConfigService } from '@nestjs/config';
import { Order } from '@/entities/order.entity';
import { PlatformAccount } from '@/entities/platform-account.entity';
import { PlatformTransaction } from '@/entities/platform-transaction.entity';
import Wechatpay = require('wechatpay-node-v3');

@Injectable()
export class RefundService {
  private wechatpayClient: Wechatpay | null;

  constructor(
    @InjectRepository(Order)
    private orderRepo: Repository<Order>,
    @InjectRepository(PlatformAccount)
    private platformAccountRepo: Repository<PlatformAccount>,
    @InjectRepository(PlatformTransaction)
    private platformTransactionRepo: Repository<PlatformTransaction>,
    private dataSource: DataSource,
    private configService: ConfigService,
  ) {
    // 初始化微信支付客户端
    this.initWechatpayClient();
  }

  /**
   * 初始化微信支付客户端
   */
  private initWechatpayClient() {
    const appid = this.configService.get<string>('WECHAT_APPID');
    const mchid = this.configService.get<string>('WECHAT_MCHID');
    const privateKey = this.configService.get<string>('WECHAT_PRIVATE_KEY');
    const serialNo = this.configService.get<string>('WECHAT_SERIAL_NO');
    const apiv3Key = this.configService.get<string>('WECHAT_APIV3_KEY');

    if (!appid || !mchid || !privateKey || !serialNo || !apiv3Key) {
      console.warn('[微信支付] 配置不完整，退款功能将使用模拟模式');
      this.wechatpayClient = null;
      return;
    }

    try {
      this.wechatpayClient = new Wechatpay({
        appid,
        mchid,
        publicKey: Buffer.from(privateKey, 'utf-8'),
        privateKey: Buffer.from(privateKey, 'utf-8'),
        serial_no: serialNo,
        key: apiv3Key,
      });
      console.log('[微信支付] 客户端初始化成功');
    } catch (error) {
      console.error('[微信支付] 客户端初始化失败:', error.message);
      this.wechatpayClient = null;
    }
  }

  /**
   * 处理退款
   * @param order 订单信息
   * @param reason 退款原因
   */
  async processRefund(order: Order, reason: string): Promise<void> {
    const queryRunner = this.dataSource.createQueryRunner();
    await queryRunner.connect();
    await queryRunner.startTransaction();

    try {
      // 1. 更新订单状态为退款中
      await queryRunner.manager.update(Order, order.id, {
        status: 'refunding',
        cancelReason: reason,
      });

      await queryRunner.commitTransaction();

      // 2. 调用第三方支付退款API（在事务外执行，避免长时间锁表）
      try {
        await this.callThirdPartyRefund(order);
      } catch (error) {
        // 退款失败，保持 refunding 状态，等待重试
        console.error(`[退款失败] 订单号: ${order.orderNo}, 错误:`, error.message);
        throw new BadRequestException(`退款处理失败: ${error.message}，订单已标记为退款中，请稍后重试`);
      }

      // 3. 退款成功，更新订单状态和记录平台账户
      await queryRunner.connect();
      await queryRunner.startTransaction();

      try {
        await this.recordPlatformRefundExpense(order, queryRunner);

        await queryRunner.manager.update(Order, order.id, {
          status: 'refunded',
          refundAmount: order.payAmount,
          refundAt: new Date(),
          cancelledAt: new Date(),
        });

        await queryRunner.commitTransaction();
      } catch (error) {
        await queryRunner.rollbackTransaction();
        throw error;
      }
    } catch (error) {
      if (queryRunner.isTransactionActive) {
        await queryRunner.rollbackTransaction();
      }
      throw error;
    } finally {
      await queryRunner.release();
    }
  }

  /**
   * 调用第三方支付退款API
   * @param order 订单信息
   */
  private async callThirdPartyRefund(order: Order): Promise<void> {
    const paymentMethod = order.paymentMethod;

    if (paymentMethod === 'wechat') {
      await this.wechatRefund(order);
    } else if (paymentMethod === 'balance') {
      // 余额支付不需要调用第三方API，直接返回用户账户
      // 这部分逻辑在后续用户钱包模块中实现
      throw new BadRequestException('余额支付退款功能暂未实现');
    } else {
      throw new BadRequestException(`不支持的支付方式: ${paymentMethod}`);
    }
  }

  /**
   * 微信支付退款
   * @param order 订单信息
   */
  private async wechatRefund(order: Order): Promise<void> {
    // 如果没有配置微信支付客户端，使用模拟模式
    if (!this.wechatpayClient) {
      console.log(`[微信退款-模拟] 订单号: ${order.orderNo}, 金额: ${order.payAmount}`);
      return;
    }

    // 检查必要字段
    if (!order.transactionId) {
      throw new BadRequestException('订单缺少微信支付交易号，无法退款');
    }

    try {
      const refundNo = `REFUND_${order.orderNo}_${Date.now()}`;
      const refundAmount = Math.round(order.payAmount * 100); // 转换为分
      const totalAmount = Math.round(order.payAmount * 100);

      // 调用微信支付退款API
      const result: any = await this.wechatpayClient.refunds({
        transaction_id: order.transactionId,
        out_refund_no: refundNo,
        reason: '用户申请退款',
        amount: {
          refund: refundAmount,
          total: totalAmount,
          currency: 'CNY',
        },
        notify_url: this.configService.get<string>('WECHAT_REFUND_NOTIFY_URL'),
      });

      // 检查退款结果
      if (result.status === 'SUCCESS' || result.status === 'PROCESSING') {
        console.log(`[微信退款成功] 订单号: ${order.orderNo}, 退款单号: ${refundNo}, 状态: ${result.status}`);
      } else {
        throw new BadRequestException(`微信退款失败: ${result.status}`);
      }
    } catch (error) {
      console.error(`[微信退款失败] 订单号: ${order.orderNo}, 错误:`, error);
      throw new BadRequestException(`微信退款失败: ${error.message || '未知错误'}`);
    }
  }

  /**
   * 平台账户记录退款支出（仅用于记账）
   * @param order 订单信息
   * @param queryRunner 事务查询器
   */
  private async recordPlatformRefundExpense(
    order: Order,
    queryRunner: any,
  ): Promise<void> {
    // 获取平台主账户
    const platformAccount = await queryRunner.manager.findOne(PlatformAccount, {
      where: { accountType: 'main' },
    });

    if (!platformAccount) {
      throw new BadRequestException('平台账户不存在');
    }

    // 创建退款支出交易记录（仅记账，实际退款通过第三方支付）
    const transaction = queryRunner.manager.create(PlatformTransaction, {
      accountId: platformAccount.id,
      type: 'refund_expense',
      amount: order.payAmount,
      balance: platformAccount.balance, // 余额不变，仅记录
      relatedType: 'order',
      relatedId: order.id,
      description: `订单退款 - ${order.orderNo}`,
      metadata: {
        orderId: order.id,
        orderNo: order.orderNo,
        userId: order.userId,
        paymentMethod: order.paymentMethod,
        refundAmount: order.payAmount,
      },
    });

    await queryRunner.manager.save(transaction);
  }

  /**
   * 退款重试（用于处理退款失败的情况）
   * @param orderId 订单ID
   */
  async retryRefund(orderId: number): Promise<void> {
    const order = await this.orderRepo.findOne({ where: { id: orderId } });
    if (!order) {
      throw new BadRequestException('订单不存在');
    }

    if (order.status !== 'refunding') {
      throw new BadRequestException('订单状态不支持重试退款，当前状态: ' + order.status);
    }

    const queryRunner = this.dataSource.createQueryRunner();
    await queryRunner.connect();

    try {
      // 重新调用第三方退款API
      await this.callThirdPartyRefund(order);

      // 退款成功，更新订单状态和记录平台账户
      await queryRunner.startTransaction();

      await this.recordPlatformRefundExpense(order, queryRunner);

      await queryRunner.manager.update(Order, order.id, {
        status: 'refunded',
        refundAmount: order.payAmount,
        refundAt: new Date(),
        cancelledAt: new Date(),
      });

      await queryRunner.commitTransaction();
      console.log(`[退款重试成功] 订单号: ${order.orderNo}`);
    } catch (error) {
      if (queryRunner.isTransactionActive) {
        await queryRunner.rollbackTransaction();
      }
      console.error(`[退款重试失败] 订单号: ${order.orderNo}, 错误:`, error.message);
      throw new BadRequestException(`退款重试失败: ${error.message}`);
    } finally {
      await queryRunner.release();
    }
  }
}
