import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, DataSource } from 'typeorm';
import { UserWithdrawal } from '@/entities/user-withdrawal.entity';
import { MerchantWithdrawal } from '@/entities/merchant-withdrawal.entity';
import { PlatformWithdrawal } from '@/entities/platform-withdrawal.entity';
import { MerchantAccount } from '@/entities/merchant-account.entity';
import { PlatformAccount } from '@/entities/platform-account.entity';
import { AccountService } from './account.service';
import { TransactionService } from './transaction.service';

@Injectable()
export class WithdrawalService {
  constructor(
    @InjectRepository(UserWithdrawal)
    private userWithdrawalRepo: Repository<UserWithdrawal>,
    @InjectRepository(MerchantWithdrawal)
    private merchantWithdrawalRepo: Repository<MerchantWithdrawal>,
    @InjectRepository(PlatformWithdrawal)
    private platformWithdrawalRepo: Repository<PlatformWithdrawal>,
    private accountService: AccountService,
    private transactionService: TransactionService,
    private dataSource: DataSource,
  ) {}

  /**
   * 用户申请提现
   */
  async createUserWithdrawal(userId: number, dto: {
    amount: number;
    paymentChannel: 'wechat' | 'alipay';
  }) {
    const { amount, paymentChannel } = dto;

    if (amount < 10) {
      throw new BadRequestException('最低提现金额为10元');
    }

    const account = await this.accountService.getUserAccount(userId);

    if (Number(account.balance) < amount) {
      throw new BadRequestException('余额不足');
    }

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

    try {
      await this.accountService.freezeUserBalance(userId, amount);

      const withdrawal = this.userWithdrawalRepo.create({
        withdrawNo: this.generateWithdrawNo('U'),
        userId,
        accountId: account.id,
        amount,
        fee: 0,
        actualAmount: amount,
        paymentChannel,
        status: 'pending'
      });

      await queryRunner.manager.save(withdrawal);
      await queryRunner.commitTransaction();

      return withdrawal;
    } catch (error) {
      await queryRunner.rollbackTransaction();
      throw error;
    } finally {
      await queryRunner.release();
    }
  }

  /**
   * 商家申请提现
   */
  async createMerchantWithdrawal(merchantId: number, dto: {
    amount: number;
    bankName: string;
    bankAccount: string;
    accountName: string;
  }) {
    const { amount, bankName, bankAccount, accountName } = dto;

    if (amount < 100) {
      throw new BadRequestException('最低提现金额为100元');
    }

    const account = await this.accountService.getMerchantAccount(merchantId);

    if (Number(account.balance) < amount) {
      throw new BadRequestException('余额不足');
    }

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

    try {
      const lockedAccount = await queryRunner.manager.findOne(MerchantAccount, {
        where: { id: account.id },
        lock: { mode: 'pessimistic_write' }
      });

      if (!lockedAccount || Number(lockedAccount.balance) < amount) {
        throw new BadRequestException('余额不足');
      }

      lockedAccount.balance = Number(lockedAccount.balance) - amount;
      lockedAccount.frozen_balance = Number(lockedAccount.frozen_balance) + amount;
      lockedAccount.version += 1;

      await queryRunner.manager.save(lockedAccount);

      const withdrawal = this.merchantWithdrawalRepo.create({
        withdrawNo: this.generateWithdrawNo('M'),
        merchantId,
        accountId: account.id,
        amount,
        fee: 0,
        actualAmount: amount,
        bankName,
        bankAccount,
        accountName,
        status: 'pending'
      });

      await queryRunner.manager.save(withdrawal);
      await queryRunner.commitTransaction();

      return withdrawal;
    } catch (error) {
      await queryRunner.rollbackTransaction();
      throw error;
    } finally {
      await queryRunner.release();
    }
  }

  /**
   * 平台申请提现
   */
  async createPlatformWithdrawal(dto: {
    amount: number;
    bankName: string;
    bankAccount: string;
    accountName: string;
  }) {
    const { amount, bankName, bankAccount, accountName } = dto;

    if (amount < 10) {
      throw new BadRequestException('最低提现金额为10元');
    }

    const account = await this.accountService.getPlatformAccount();

    // 计算可提现金额 = 累计服务费 - 冻结余额
    // 注意：这里使用 total_service_fee 是为了确保只提现平台收入
    // 未来如果有其他收入（广告费、会员费等），需要累加到可提现金额中
    const availableAmount = Number(account.total_service_fee) - Number(account.frozen_balance);

    if (availableAmount < amount) {
      throw new BadRequestException(`可提现金额不足，当前可提现：${availableAmount.toFixed(2)}元`);
    }

    if (Number(account.balance) < amount) {
      throw new BadRequestException('账户余额不足');
    }

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

    try {
      const lockedAccount = await queryRunner.manager.findOne(PlatformAccount, {
        where: { id: account.id },
        lock: { mode: 'pessimistic_write' }
      });

      if (!lockedAccount || Number(lockedAccount.balance) < amount) {
        throw new BadRequestException('账户余额不足');
      }

      lockedAccount.balance = Number(lockedAccount.balance) - amount;
      lockedAccount.frozen_balance = Number(lockedAccount.frozen_balance) + amount;
      lockedAccount.version += 1;

      await queryRunner.manager.save(lockedAccount);

      const withdrawal = this.platformWithdrawalRepo.create({
        withdrawNo: this.generateWithdrawNo('P'),
        accountId: account.id,
        amount,
        fee: 0,
        actualAmount: amount,
        bankName,
        bankAccount,
        accountName,
        status: 'pending'
      });

      await queryRunner.manager.save(withdrawal);
      await queryRunner.commitTransaction();

      return withdrawal;
    } catch (error) {
      await queryRunner.rollbackTransaction();
      throw error;
    } finally {
      await queryRunner.release();
    }
  }

  /**
   * 审核通过用户提现
   */
  async approveUserWithdrawal(id: number, reviewerId: number) {
    const withdrawal = await this.userWithdrawalRepo.findOne({ where: { id } });

    if (!withdrawal) {
      throw new NotFoundException('提现记录不存在');
    }

    if (withdrawal.status !== 'pending') {
      throw new BadRequestException('只能审核待审核的提现');
    }

    await this.userWithdrawalRepo.update(id, {
      status: 'approved',
      reviewerId,
      reviewedAt: new Date()
    });

    return { message: '审核通过' };
  }

  /**
   * 审核拒绝用户提现
   */
  async rejectUserWithdrawal(id: number, reviewerId: number, reason: string) {
    const withdrawal = await this.userWithdrawalRepo.findOne({ where: { id } });

    if (!withdrawal) {
      throw new NotFoundException('提现记录不存在');
    }

    if (withdrawal.status !== 'pending') {
      throw new BadRequestException('只能审核待审核的提现');
    }

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

    try {
      await this.accountService.unfreezeUserBalance(withdrawal.userId, Number(withdrawal.amount));

      await queryRunner.manager.update(UserWithdrawal, id, {
        status: 'rejected',
        rejectReason: reason,
        reviewerId,
        reviewedAt: new Date()
      });

      await queryRunner.commitTransaction();
      return { message: '已拒绝' };
    } catch (error) {
      await queryRunner.rollbackTransaction();
      throw error;
    } finally {
      await queryRunner.release();
    }
  }

  /**
   * 确认打款用户提现
   */
  async payUserWithdrawal(id: number, paymentNo?: string) {
    const withdrawal = await this.userWithdrawalRepo.findOne({ where: { id } });

    if (!withdrawal) {
      throw new NotFoundException('提现记录不存在');
    }

    if (withdrawal.status !== 'approved') {
      throw new BadRequestException('只能对已审核通过的提现进行打款');
    }

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

    try {
      const transactionNo = this.transactionService.generateTransactionNo();

      await this.accountService.deductUserBalance(
        withdrawal.userId,
        Number(withdrawal.actualAmount),
        transactionNo,
        'withdraw',
        withdrawal.id,
        withdrawal.withdrawNo,
        `用户提现 - ${withdrawal.paymentChannel}`
      );

      await queryRunner.manager.update(UserWithdrawal, id, {
        status: 'paid',
        paymentNo,
        paidAt: new Date()
      });

      await queryRunner.commitTransaction();
      return { message: '打款成功' };
    } catch (error) {
      await queryRunner.rollbackTransaction();
      throw error;
    } finally {
      await queryRunner.release();
    }
  }

  /**
   * 审核通过商家提现
   */
  async approveMerchantWithdrawal(id: number, reviewerId: number) {
    const withdrawal = await this.merchantWithdrawalRepo.findOne({ where: { id } });

    if (!withdrawal) {
      throw new NotFoundException('提现记录不存在');
    }

    if (withdrawal.status !== 'pending') {
      throw new BadRequestException('只能审核待审核的提现');
    }

    await this.merchantWithdrawalRepo.update(id, {
      status: 'approved',
      reviewerId,
      reviewedAt: new Date()
    });

    return { message: '审核通过' };
  }

  /**
   * 审核拒绝商家提现
   */
  async rejectMerchantWithdrawal(id: number, reviewerId: number, reason: string) {
    const withdrawal = await this.merchantWithdrawalRepo.findOne({ where: { id } });

    if (!withdrawal) {
      throw new NotFoundException('提现记录不存在');
    }

    if (withdrawal.status !== 'pending') {
      throw new BadRequestException('只能审核待审核的提现');
    }

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

    try {
      const account = await queryRunner.manager.findOne(MerchantAccount, {
        where: { id: withdrawal.accountId },
        lock: { mode: 'pessimistic_write' }
      });

      if (!account) {
        throw new NotFoundException('账户不存在');
      }

      account.balance = Number(account.balance) + Number(withdrawal.amount);
      account.frozen_balance = Number(account.frozen_balance) - Number(withdrawal.amount);
      account.version += 1;

      await queryRunner.manager.save(account);

      await queryRunner.manager.update(MerchantWithdrawal, id, {
        status: 'rejected',
        rejectReason: reason,
        reviewerId,
        reviewedAt: new Date()
      });

      await queryRunner.commitTransaction();
      return { message: '已拒绝' };
    } catch (error) {
      await queryRunner.rollbackTransaction();
      throw error;
    } finally {
      await queryRunner.release();
    }
  }

  /**
   * 确认打款商家提现
   */
  async payMerchantWithdrawal(id: number, paymentNo?: string) {
    const withdrawal = await this.merchantWithdrawalRepo.findOne({ where: { id } });

    if (!withdrawal) {
      throw new NotFoundException('提现记录不存在');
    }

    if (withdrawal.status !== 'approved') {
      throw new BadRequestException('只能对已审核通过的提现进行打款');
    }

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

    try {
      const transactionNo = this.transactionService.generateTransactionNo();

      await this.accountService.deductMerchantBalance(
        withdrawal.merchantId,
        Number(withdrawal.actualAmount),
        transactionNo,
        'withdraw',
        withdrawal.id,
        withdrawal.withdrawNo,
        `商家提现 - ${withdrawal.bankName}`
      );

      await queryRunner.manager.update(MerchantWithdrawal, id, {
        status: 'paid',
        paymentNo,
        paidAt: new Date()
      });

      await queryRunner.commitTransaction();
      return { message: '打款成功' };
    } catch (error) {
      await queryRunner.rollbackTransaction();
      throw error;
    } finally {
      await queryRunner.release();
    }
  }

  /**
   * 审核通过平台提现
   */
  async approvePlatformWithdrawal(id: number, reviewerId: number) {
    const withdrawal = await this.platformWithdrawalRepo.findOne({ where: { id } });

    if (!withdrawal) {
      throw new NotFoundException('提现记录不存在');
    }

    if (withdrawal.status !== 'pending') {
      throw new BadRequestException('只能审核待审核的提现');
    }

    await this.platformWithdrawalRepo.update(id, {
      status: 'approved',
      reviewerId,
      reviewedAt: new Date()
    });

    return { message: '审核通过' };
  }

  /**
   * 审核拒绝平台提现
   */
  async rejectPlatformWithdrawal(id: number, reviewerId: number, reason: string) {
    const withdrawal = await this.platformWithdrawalRepo.findOne({ where: { id } });

    if (!withdrawal) {
      throw new NotFoundException('提现记录不存在');
    }

    if (withdrawal.status !== 'pending') {
      throw new BadRequestException('只能审核待审核的提现');
    }

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

    try {
      const account = await queryRunner.manager.findOne(PlatformAccount, {
        where: { id: withdrawal.accountId },
        lock: { mode: 'pessimistic_write' }
      });

      if (!account) {
        throw new NotFoundException('账户不存在');
      }

      account.balance = Number(account.balance) + Number(withdrawal.amount);
      account.frozen_balance = Number(account.frozen_balance) - Number(withdrawal.amount);
      account.version += 1;

      await queryRunner.manager.save(account);

      await queryRunner.manager.update(PlatformWithdrawal, id, {
        status: 'rejected',
        rejectReason: reason,
        reviewerId,
        reviewedAt: new Date()
      });

      await queryRunner.commitTransaction();
      return { message: '已拒绝' };
    } catch (error) {
      await queryRunner.rollbackTransaction();
      throw error;
    } finally {
      await queryRunner.release();
    }
  }

  /**
   * 确认打款平台提现
   */
  async payPlatformWithdrawal(id: number, paymentNo?: string) {
    const withdrawal = await this.platformWithdrawalRepo.findOne({ where: { id } });

    if (!withdrawal) {
      throw new NotFoundException('提现记录不存在');
    }

    if (withdrawal.status !== 'approved') {
      throw new BadRequestException('只能对已审核通过的提现进行打款');
    }

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

    try {
      const transactionNo = this.transactionService.generateTransactionNo();

      await this.accountService.deductPlatformBalance(
        Number(withdrawal.actualAmount),
        transactionNo,
        '提现',
        'withdraw',
        withdrawal.id,
        withdrawal.withdrawNo,
        `平台提现 - ${withdrawal.bankName}`
      );

      await queryRunner.manager.update(PlatformWithdrawal, id, {
        status: 'paid',
        paymentNo,
        paidAt: new Date()
      });

      await queryRunner.commitTransaction();
      return { message: '打款成功' };
    } catch (error) {
      await queryRunner.rollbackTransaction();
      throw error;
    } finally {
      await queryRunner.release();
    }
  }

  /**
   * 获取用户提现列表
   */
  async getUserWithdrawals(params: {
    userId?: number;
    status?: string;
    page?: number;
    pageSize?: number;
  }) {
    const { userId, status, page = 1, pageSize = 20 } = params;

    const queryBuilder = this.userWithdrawalRepo.createQueryBuilder('w');

    if (userId !== undefined) {
      queryBuilder.andWhere('w.userId = :userId', { userId });
    }

    if (status) {
      queryBuilder.andWhere('w.status = :status', { status });
    }

    queryBuilder.orderBy('w.createdAt', 'DESC');

    const skip = (page - 1) * pageSize;
    queryBuilder.skip(skip).take(pageSize);

    const [list, total] = await queryBuilder.getManyAndCount();

    return {
      list,
      total,
      page,
      pageSize,
      totalPages: Math.ceil(total / pageSize)
    };
  }

  /**
   * 获取商家提现列表
   */
  async getMerchantWithdrawals(params: {
    merchantId?: number;
    status?: string;
    page?: number;
    pageSize?: number;
  }) {
    const { merchantId, status, page = 1, pageSize = 20 } = params;

    const queryBuilder = this.merchantWithdrawalRepo.createQueryBuilder('w');

    if (merchantId !== undefined) {
      queryBuilder.andWhere('w.merchantId = :merchantId', { merchantId });
    }

    if (status) {
      queryBuilder.andWhere('w.status = :status', { status });
    }

    queryBuilder.orderBy('w.createdAt', 'DESC');

    const skip = (page - 1) * pageSize;
    queryBuilder.skip(skip).take(pageSize);

    const [list, total] = await queryBuilder.getManyAndCount();

    return {
      list,
      total,
      page,
      pageSize,
      totalPages: Math.ceil(total / pageSize)
    };
  }

  /**
   * 获取平台提现列表
   */
  async getPlatformWithdrawals(params: {
    status?: string;
    page?: number;
    pageSize?: number;
  }) {
    const { status, page = 1, pageSize = 20 } = params;

    const queryBuilder = this.platformWithdrawalRepo.createQueryBuilder('w');

    if (status) {
      queryBuilder.andWhere('w.status = :status', { status });
    }

    queryBuilder.orderBy('w.createdAt', 'DESC');

    const skip = (page - 1) * pageSize;
    queryBuilder.skip(skip).take(pageSize);

    const [list, total] = await queryBuilder.getManyAndCount();

    return {
      list,
      total,
      page,
      pageSize,
      totalPages: Math.ceil(total / pageSize)
    };
  }

  /**
   * 生成提现单号
   */
  private generateWithdrawNo(prefix: string): string {
    const timestamp = Date.now();
    const random = Math.floor(Math.random() * 10000).toString().padStart(4, '0');
    return `WD${prefix}${timestamp}${random}`;
  }
}
