import { Injectable, BadRequestException, NotFoundException, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, DataSource } from 'typeorm';
import { MktActivity } from '@/entities/mkt-activity.entity';
import { MktInvitation } from '@/entities/mkt-invitation.entity';
import { MktCashback } from '@/entities/mkt-cashback.entity';
import { MktUserInviteStats } from '@/entities/mkt-user-invite-stats.entity';
import { MktInviteWithdrawal } from '@/entities/mkt-invite-withdrawal.entity';
import {
  CreateActivityDto,
  UpdateActivityDto,
  QueryActivityDto,
  QueryAdminInviteWithdrawalsDto,
  QueryAdminCashbacksDto,
  RejectInviteWithdrawalDto,
} from './dto/activity.dto';

@Injectable()
export class ActivityService {
  private readonly logger = new Logger(ActivityService.name);

  constructor(
    @InjectRepository(MktActivity)
    private activityRepo: Repository<MktActivity>,
    @InjectRepository(MktInvitation)
    private invitationRepo: Repository<MktInvitation>,
    @InjectRepository(MktCashback)
    private cashbackRepo: Repository<MktCashback>,
    @InjectRepository(MktUserInviteStats)
    private statsRepo: Repository<MktUserInviteStats>,
    @InjectRepository(MktInviteWithdrawal)
    private withdrawalRepo: Repository<MktInviteWithdrawal>,
    private dataSource: DataSource,
  ) {}

  // ===== 活动管理 =====

  async createActivity(dto: CreateActivityDto) {
    const nameMap: Record<string, string> = { invite_cashback: '邀请返现' };
    const activity = this.activityRepo.create({
      ...dto,
      name: nameMap[dto.type] || dto.name,
    });
    return this.activityRepo.save(activity);
  }

  async updateActivity(id: number, dto: UpdateActivityDto) {
    const activity = await this.activityRepo.findOne({ where: { id } });
    if (!activity) throw new NotFoundException('活动不存在');
    Object.assign(activity, dto);
    return this.activityRepo.save(activity);
  }

  async toggleActivity(id: number) {
    const activity = await this.activityRepo.findOne({ where: { id } });
    if (!activity) throw new NotFoundException('活动不存在');
    activity.enabled = !activity.enabled;
    return this.activityRepo.save(activity);
  }

  async getActivities(dto: QueryActivityDto) {
    const page = dto.page ?? 1;
    const pageSize = dto.pageSize ?? 10;
    const where: any = {};
    if (dto.type) where.type = dto.type;
    if (dto.enabled !== undefined) where.enabled = dto.enabled;

    const [list, total] = await this.activityRepo.findAndCount({
      where,
      order: { createdAt: 'DESC' },
      skip: (page - 1) * pageSize,
      take: pageSize,
    });

    return { list, total, page, pageSize };
  }

  async getActivityById(id: number) {
    const activity = await this.activityRepo.findOne({ where: { id } });
    if (!activity) throw new NotFoundException('活动不存在');
    return activity;
  }

  async getEnabledInviteCashbackActivity(): Promise<MktActivity | null> {
    return this.activityRepo.findOne({
      where: { type: 'invite_cashback', enabled: true },
    });
  }

  // ===== 管理端功能 =====

  async getInviteCashbackConfig() {
    let activity = await this.activityRepo.findOne({
      where: { type: 'invite_cashback' },
    });
    if (!activity) {
      activity = this.activityRepo.create({
        name: '邀请返现',
        type: 'invite_cashback',
        enabled: true,
        config: {
          firstOrderRate: 0.05,
          secondOrderRate: 0.005,
          minCashback: 0.01,
          maxCashback: 50,
          withdrawThreshold: 10,
          maxOrderIndex: 2,
        },
      });
      await this.activityRepo.save(activity);
    }
    return activity;
  }

  async updateInviteCashbackConfig(dto: UpdateActivityDto) {
    const activity = await this.getInviteCashbackConfig();

    if (dto.config) {
      const newConfig = { ...activity.config, ...dto.config };

      // 校验：最低返现金额不能大于最高返现金额
      if (newConfig.minCashback > newConfig.maxCashback) {
        throw new BadRequestException('最低返现金额不能大于最高返现金额');
      }

      // 校验：首单返现比例应大于等于二单返现比例
      if (newConfig.firstOrderRate < newConfig.secondOrderRate) {
        throw new BadRequestException('首单返现比例应大于等于二单返现比例');
      }

      activity.config = newConfig;
    }

    if (dto.enabled !== undefined) {
      activity.enabled = dto.enabled;
    }

    return this.activityRepo.save(activity);
  }

  async getAdminStats(activityId?: number) {
    const where: any = {};
    if (activityId) where.activityId = activityId;

    const [totalInvitations, totalCashbacks, totalWithdrawals, pendingWithdrawals] =
      await Promise.all([
        this.invitationRepo.count({ where }),
        this.cashbackRepo.count({ where }),
        this.withdrawalRepo.count({ where }),
        this.withdrawalRepo.count({ where: { ...where, status: 'pending' } }),
      ]);

    const cashbackSum = await this.cashbackRepo
      .createQueryBuilder('cb')
      .select('SUM(cb.amount)', 'total')
      .getRawOne();

    return {
      totalInvitations,
      totalCashbacks,
      totalWithdrawals,
      pendingWithdrawals,
      totalCashbackAmount: cashbackSum?.total || 0,
    };
  }

  async getAdminInvitations(dto: any) {
    const page = dto.page ?? 1;
    const pageSize = dto.pageSize ?? 20;

    const [list, total] = await this.invitationRepo.findAndCount({
      relations: ['inviter', 'invitee'],
      order: { createdAt: 'DESC' },
      skip: (page - 1) * pageSize,
      take: pageSize,
    });

    return { list, total };
  }

  async getAdminCashbacks(dto: QueryAdminCashbacksDto) {
    const page = dto.page ?? 1;
    const pageSize = dto.pageSize ?? 20;

    const [list, total] = await this.cashbackRepo.findAndCount({
      relations: ['inviter', 'invitee', 'order'],
      order: { createdAt: 'DESC' },
      skip: (page - 1) * pageSize,
      take: pageSize,
    });

    return { list, total };
  }

  async getAdminWithdrawals(dto: QueryAdminInviteWithdrawalsDto) {
    const page = dto.page ?? 1;
    const pageSize = dto.pageSize ?? 20;
    const where: any = {};
    if (dto.status) where.status = dto.status;

    const [list, total] = await this.withdrawalRepo.findAndCount({
      where,
      relations: ['user'],
      order: { created_at: 'DESC' },
      skip: (page - 1) * pageSize,
      take: pageSize,
    });

    return { list, total };
  }

  async approveWithdrawal(id: number, reviewerId: number) {
    const withdrawal = await this.withdrawalRepo.findOne({ where: { id } });
    if (!withdrawal) throw new NotFoundException('提现申请不存在');
    if (withdrawal.status !== 'pending') {
      throw new BadRequestException('当前状态不可审核');
    }

    withdrawal.status = 'approved';
    withdrawal.reviewer_id = reviewerId;
    withdrawal.reviewed_at = new Date();
    return this.withdrawalRepo.save(withdrawal);
  }

  async rejectWithdrawal(id: number, reviewerId: number, dto: RejectInviteWithdrawalDto) {
    const withdrawal = await this.withdrawalRepo.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 {
      withdrawal.status = 'rejected';
      withdrawal.reviewer_id = reviewerId;
      withdrawal.reviewed_at = new Date();
      withdrawal.reject_reason = dto.reason;
      await queryRunner.manager.save(withdrawal);

      // 返还余额
      await queryRunner.manager.increment(
        MktUserInviteStats,
        { activityId: withdrawal.activity_id, userId: withdrawal.user_id },
        'availableBalance',
        withdrawal.amount,
      );

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

  async payWithdrawal(id: number) {
    const withdrawal = await this.withdrawalRepo.findOne({ where: { id } });
    if (!withdrawal) throw new NotFoundException('提现申请不存在');
    if (withdrawal.status !== 'approved') {
      throw new BadRequestException('当前状态不可打款');
    }

    withdrawal.status = 'paid';
    withdrawal.paid_at = new Date();

    // 更新已提现金额
    await this.statsRepo.increment(
      { activityId: withdrawal.activity_id, userId: withdrawal.user_id },
      'withdrawnAmount',
      withdrawal.amount,
    );

    return this.withdrawalRepo.save(withdrawal);
  }
}
