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 { AccountService } from './account.service';
import { TransactionService } from './transaction.service';
import { WechatPayService } from '@/modules/shared/payment/wechat-pay.service';

@Injectable()
export class RefundService {
  constructor(
    @InjectRepository(Order)
    private orderRepo: Repository<Order>,
    private accountService: AccountService,
    private transactionService: TransactionService,
    private dataSource: DataSource,
    private configService: ConfigService,
    private wechatPayService: WechatPayService,
  ) {}

  /**
   * 处理退款
   * @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 (!order.transactionId) {
      throw new BadRequestException('订单缺少微信支付交易号，无法退款');
    }

    try {
      const refundNo = `REFUND_${order.orderNo}_${Date.now()}`;
      const notifyUrl = this.configService.get<string>('WECHAT_REFUND_NOTIFY_URL') ||
                        `${this.configService.get<string>('API_BASE_URL')}/api/app/payment/wechat/refund-notify`;

      // 调用微信支付退款API
      const result = await this.wechatPayService.refund({
        orderNo: order.orderNo,
        refundNo,
        totalAmount: order.payAmount,
        refundAmount: order.payAmount,
        reason: '用户申请退款',
        notifyUrl,
      });

      console.log(`[微信退款成功] 订单号: ${order.orderNo}, 退款单号: ${refundNo}`);
    } 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 transactionNo = this.transactionService.generateTransactionNo();

    // 记录系统总账户退款
    await this.accountService.addSystemRefund(
      order.payAmount,
      transactionNo,
      'order_refund',
      order.id,
      order.orderNo,
      `订单退款 - ${order.orderNo}`,
    );
  }

  /**
   * 退款重试（用于处理退款失败的情况）
   * @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();
    }
  }
}
