import { Injectable, BadRequestException, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, LessThan, MoreThan } from 'typeorm';
import { Coupon } from '@/entities/coupon.entity';
import { UserCoupon } from '@/entities/user-coupon.entity';
import { CreateCouponDto, UpdateCouponDto, QueryCouponDto, QueryUserCouponDto } from './dto/coupon.dto';
import dayjs from 'dayjs';

@Injectable()
export class CouponService {
  constructor(
    @InjectRepository(Coupon)
    private couponRepo: Repository<Coupon>,
    @InjectRepository(UserCoupon)
    private userCouponRepo: Repository<UserCoupon>,
  ) {}

  /**
   * 创建优惠券
   */
  async create(dto: CreateCouponDto, adminId: number): Promise<Coupon> {
    // 验证日期
    if (dayjs(dto.endDate).isBefore(dayjs(dto.startDate))) {
      throw new BadRequestException('失效日期不能早于生效日期');
    }

    // 验证折扣比例
    if (dto.type === 'percent' && (dto.value < 0 || dto.value > 100)) {
      throw new BadRequestException('折扣比例必须在0-100之间');
    }

    const coupon = this.couponRepo.create({
      ...dto,
      remainCount: dto.totalCount,
      usedCount: 0,
      createdBy: adminId,
    });

    return this.couponRepo.save(coupon);
  }

  /**
   * 更新优惠券
   */
  async update(id: number, dto: UpdateCouponDto): Promise<Coupon> {
    const coupon = await this.couponRepo.findOne({ where: { id } });
    if (!coupon) {
      throw new NotFoundException('优惠券不存在');
    }

    // 如果修改总量，需要同步更新剩余数量
    if (dto.totalCount !== undefined) {
      const diff = dto.totalCount - coupon.totalCount;
      coupon.remainCount = Math.max(0, coupon.remainCount + diff);
      coupon.totalCount = dto.totalCount;
    }

    if (dto.name) coupon.name = dto.name;
    if (dto.status) coupon.status = dto.status;

    return this.couponRepo.save(coupon);
  }

  /**
   * 删除优惠券
   */
  async delete(id: number): Promise<void> {
    const coupon = await this.couponRepo.findOne({ where: { id } });
    if (!coupon) {
      throw new NotFoundException('优惠券不存在');
    }

    // 检查是否有用户已领取
    const userCouponCount = await this.userCouponRepo.count({
      where: { couponId: id },
    });

    if (userCouponCount > 0) {
      throw new BadRequestException('该优惠券已被用户领取，无法删除');
    }

    await this.couponRepo.remove(coupon);
  }

  /**
   * 查询优惠券列表
   */
  async findAll(dto: QueryCouponDto) {
    const { page = 1, pageSize = 10, status, scope } = dto;

    const qb = this.couponRepo.createQueryBuilder('c');

    if (status) {
      qb.andWhere('c.status = :status', { status });
    }

    if (scope) {
      qb.andWhere('c.scope = :scope', { scope });
    }

    qb.orderBy('c.createdAt', 'DESC');
    qb.skip((page - 1) * pageSize).take(pageSize);

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

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

  /**
   * 获取优惠券详情
   */
  async findOne(id: number): Promise<Coupon> {
    const coupon = await this.couponRepo.findOne({ where: { id } });
    if (!coupon) {
      throw new NotFoundException('优惠券不存在');
    }
    return coupon;
  }

  /**
   * 用户领取优惠券
   */
  async receive(userId: number, couponId: number): Promise<UserCoupon> {
    const coupon = await this.couponRepo.findOne({ where: { id: couponId } });
    if (!coupon) {
      throw new NotFoundException('优惠券不存在');
    }

    // 检查优惠券状态
    if (coupon.status !== 'active') {
      throw new BadRequestException('优惠券已暂停或结束');
    }

    // 检查是否在有效期内
    const now = dayjs();
    if (now.isBefore(dayjs(coupon.startDate)) || now.isAfter(dayjs(coupon.endDate))) {
      throw new BadRequestException('优惠券不在有效期内');
    }

    // 检查库存
    if (coupon.remainCount <= 0) {
      throw new BadRequestException('优惠券已被领完');
    }

    // 检查用户是否已领取
    const existingUserCoupon = await this.userCouponRepo.findOne({
      where: { userId, couponId },
    });

    if (existingUserCoupon) {
      throw new BadRequestException('您已领取过该优惠券');
    }

    // 创建用户优惠券
    const userCoupon = this.userCouponRepo.create({
      userId,
      couponId,
      status: 'unused',
      expireAt: dayjs(coupon.endDate).toDate(),
    });

    // 扣减库存
    coupon.remainCount -= 1;

    await this.couponRepo.save(coupon);
    return this.userCouponRepo.save(userCoupon);
  }

  /**
   * 查询用户优惠券列表
   */
  async findUserCoupons(userId: number, dto: QueryUserCouponDto) {
    const { page = 1, pageSize = 10, status } = dto;

    const qb = this.userCouponRepo
      .createQueryBuilder('uc')
      .leftJoinAndSelect('uc.coupon', 'c')
      .where('uc.userId = :userId', { userId });

    if (status) {
      qb.andWhere('uc.status = :status', { status });
    }

    qb.orderBy('uc.receivedAt', 'DESC');
    qb.skip((page - 1) * pageSize).take(pageSize);

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

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

  /**
   * 查询用户可用优惠券（用于订单创建）
   */
  async findAvailableCoupons(userId: number, orderAmount: number, merchantId?: number, roomId?: number) {
    const now = new Date();

    const qb = this.userCouponRepo
      .createQueryBuilder('uc')
      .leftJoinAndSelect('uc.coupon', 'c')
      .where('uc.userId = :userId', { userId })
      .andWhere('uc.status = :status', { status: 'unused' })
      .andWhere('uc.expireAt > :now', { now })
      .andWhere('c.status = :couponStatus', { couponStatus: 'active' })
      .andWhere('c.minAmount <= :orderAmount', { orderAmount });

    // 根据适用范围筛选
    qb.andWhere(
      '(c.scope = :platform OR (c.scope = :merchant AND c.scopeId = :merchantId) OR (c.scope = :room AND c.scopeId = :roomId))',
      {
        platform: 'platform',
        merchant: 'merchant',
        room: 'room',
        merchantId: merchantId || 0,
        roomId: roomId || 0,
      },
    );

    const userCoupons = await qb.getMany();

    return userCoupons;
  }

  /**
   * 使用优惠券
   */
  async useCoupon(userCouponId: number, orderId: number): Promise<void> {
    const userCoupon = await this.userCouponRepo.findOne({
      where: { id: userCouponId },
      relations: ['coupon'],
    });

    if (!userCoupon) {
      throw new NotFoundException('用户优惠券不存在');
    }

    if (userCoupon.status !== 'unused') {
      throw new BadRequestException('优惠券已使用或已过期');
    }

    // 更新用户优惠券状态
    userCoupon.status = 'used';
    userCoupon.orderId = orderId;
    userCoupon.usedAt = new Date();

    // 更新优惠券使用数量
    const coupon = userCoupon.coupon;
    coupon.usedCount += 1;

    await this.userCouponRepo.save(userCoupon);
    await this.couponRepo.save(coupon);
  }

  /**
   * 计算优惠金额
   */
  calculateDiscount(coupon: Coupon, orderAmount: number): number {
    if (coupon.type === 'fixed') {
      return Math.min(Number(coupon.value), orderAmount);
    } else {
      // percent
      return Math.floor((orderAmount * Number(coupon.value)) / 100);
    }
  }

  /**
   * 定时任务：标记过期优惠券
   */
  async markExpiredCoupons(): Promise<void> {
    const now = new Date();

    await this.userCouponRepo
      .createQueryBuilder()
      .update(UserCoupon)
      .set({ status: 'expired' })
      .where('status = :status', { status: 'unused' })
      .andWhere('expireAt < :now', { now })
      .execute();
  }
}
