import { Injectable, BadRequestException, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Coupon } from '@/entities/coupon.entity';
import { UserCoupon } from '@/entities/user-coupon.entity';
import { 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 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);
  }

  /**
   * 查询所有可领取的优惠券
   */
  async findAll(dto: any) {
    const { page = 1, pageSize = 10, status } = dto;
    const now = new Date();

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

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

    // 只返回有效期内的优惠券
    qb.andWhere('c.startDate <= :now', { now });
    qb.andWhere('c.endDate >= :now', { now });
    qb.andWhere('c.remainCount > 0');

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

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

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

  /**
   * 计算优惠金额
   */
  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);
    }
  }
}
