package com.ruoyi.system.service.impl;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.exception.ServiceException;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.system.domain.PromotionCouponBatch;
import com.ruoyi.system.domain.PromotionCouponRule;
import com.ruoyi.system.domain.PromotionUserCoupon;
import com.ruoyi.system.domain.vo.StoreCouponVO;
import com.ruoyi.system.domain.vo.MyCouponVO;
import com.ruoyi.system.mapper.PromotionCouponBatchMapper;
import com.ruoyi.system.mapper.PromotionCouponRuleMapper;
import com.ruoyi.system.mapper.PromotionUserCouponMapper;
import com.ruoyi.system.service.IPromotionUserCouponService;

/**
 * 用户优惠券Service业务层处理
 */
@Service
public class PromotionUserCouponServiceImpl extends ServiceImpl<PromotionUserCouponMapper, PromotionUserCoupon> implements IPromotionUserCouponService {

    @Autowired
    private PromotionUserCouponMapper userCouponMapper;

    @Autowired
    private PromotionCouponBatchMapper batchMapper;

    @Autowired
    private PromotionCouponRuleMapper ruleMapper;

    @Override
    @Transactional
    public PromotionUserCoupon receiveCoupon(Long userId, Long batchId, Long storeId) {
        // 1. 查询券批次，校验状态
        PromotionCouponBatch batch = batchMapper.selectById(batchId);
        if (batch == null || batch.getStatus() != 1) {
            throw new ServiceException("优惠券不可用");
        }
        if (batch.getRemainCount() <= 0) {
            throw new ServiceException("优惠券已领完");
        }
        if (batch.getEndTime().before(new Date())) {
            throw new ServiceException("优惠券已过期");
        }

        // 2. 检查是否已领取（每人每批次限领1张）
        LambdaQueryWrapper<PromotionUserCoupon> countWrapper = new LambdaQueryWrapper<>();
        countWrapper.eq(PromotionUserCoupon::getUserId, userId)
                .eq(PromotionUserCoupon::getBatchId, batchId);
        long count = userCouponMapper.selectCount(countWrapper);
        if (count > 0) {
            throw new ServiceException("您已领取过该优惠券");
        }

        // 3. 乐观锁扣减库存
        int updated = batchMapper.update(null,
            new LambdaUpdateWrapper<PromotionCouponBatch>()
                .eq(PromotionCouponBatch::getId, batchId)
                .gt(PromotionCouponBatch::getRemainCount, 0)
                .setSql("remain_count = remain_count - 1, received_count = received_count + 1")
        );
        if (updated == 0) {
            throw new ServiceException("优惠券已领完");
        }

        // 4. 计算过期时间：领取日期 + validDays天后的 23:59:59
        LocalDateTime expireTime = LocalDate.now().plusDays(batch.getValidDays()).atTime(LocalTime.of(23, 59, 59));

        // 5. 插入用户券记录
        PromotionUserCoupon coupon = new PromotionUserCoupon();
        coupon.setUserId(userId);
        coupon.setBatchId(batchId);
        coupon.setStoreId(storeId != null ? storeId : batch.getStoreId());
        coupon.setStatus(0);
        coupon.setReceiveTime(new Date());
        coupon.setExpireTime(java.sql.Timestamp.valueOf(expireTime));
        userCouponMapper.insert(coupon);

        return coupon;
    }

    @Override
    public List<StoreCouponVO> selectStoreCouponsForUser(Long userId, Long storeId) {
        // 查询门店进行中的券批次
        LambdaQueryWrapper<PromotionCouponBatch> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PromotionCouponBatch::getStoreId, storeId)
                .eq(PromotionCouponBatch::getStatus, 1)
                .le(PromotionCouponBatch::getStartTime, new Date())
                .ge(PromotionCouponBatch::getEndTime, new Date());
        List<PromotionCouponBatch> batches = batchMapper.selectList(wrapper);

        List<StoreCouponVO> result = new ArrayList<>();
        for (PromotionCouponBatch batch : batches) {
            StoreCouponVO vo = new StoreCouponVO();
            vo.setId(batch.getId());
            vo.setName(batch.getName());
            vo.setCouponType(batch.getCouponType());
            vo.setTotalCount(batch.getTotalCount());
            vo.setRemainCount(batch.getRemainCount());
            vo.setEndTime(batch.getEndTime());

            // 查询券规则（商品券可含多条）
            List<PromotionCouponRule> rules = ruleMapper.selectList(
                new LambdaQueryWrapper<PromotionCouponRule>()
                    .eq(PromotionCouponRule::getBatchId, batch.getId()));
            vo.setRules(rules);
            if (!rules.isEmpty()) {
                PromotionCouponRule first = rules.get(0);
                vo.setThreshold(first.getThreshold());
                vo.setAmount(first.getAmount());
                vo.setDiscountRate(first.getDiscountRate());
                vo.setIsMutex(first.getIsMutex());
            }

            // 检查用户是否已领取
            long received = userCouponMapper.selectCount(
                new LambdaQueryWrapper<PromotionUserCoupon>()
                    .eq(PromotionUserCoupon::getUserId, userId)
                    .eq(PromotionUserCoupon::getBatchId, batch.getId()));
            vo.setHasReceived(received > 0);

            result.add(vo);
        }
        return result;
    }

    @Override
    public List<MyCouponVO> selectMyCoupons(Long userId, Integer status, Long storeId) {
        // 先把已过期的券标记为过期（expire_time < NOW() 且 status=0）
        userCouponMapper.update(null,
            new LambdaUpdateWrapper<PromotionUserCoupon>()
                .eq(PromotionUserCoupon::getUserId, userId)
                .eq(PromotionUserCoupon::getStatus, 0)
                .lt(PromotionUserCoupon::getExpireTime, new Date())
                .set(PromotionUserCoupon::getStatus, 2)
        );

        // 查询用户券
        LambdaQueryWrapper<PromotionUserCoupon> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PromotionUserCoupon::getUserId, userId);
        if (status != null) {
            wrapper.eq(PromotionUserCoupon::getStatus, status);
        }
        if (storeId != null) {
            wrapper.eq(PromotionUserCoupon::getStoreId, storeId);
        }
        wrapper.orderByDesc(PromotionUserCoupon::getReceiveTime);
        List<PromotionUserCoupon> coupons = userCouponMapper.selectList(wrapper);

        List<MyCouponVO> result = new ArrayList<>();
        for (PromotionUserCoupon coupon : coupons) {
            MyCouponVO vo = new MyCouponVO();
            vo.setId(coupon.getId());
            vo.setBatchId(coupon.getBatchId());
            vo.setStoreId(coupon.getStoreId());
            vo.setStatus(coupon.getStatus());
            vo.setExpireTime(coupon.getExpireTime());

            // 查询批次信息
            PromotionCouponBatch batch = batchMapper.selectById(coupon.getBatchId());
            if (batch != null) {
                vo.setName(batch.getName());
                vo.setCouponType(batch.getCouponType());
            }

            // 查询规则信息（商品券可含多条，取第一条用于列表展示）
            List<PromotionCouponRule> rules = ruleMapper.selectList(
                new LambdaQueryWrapper<PromotionCouponRule>()
                    .eq(PromotionCouponRule::getBatchId, coupon.getBatchId()));
            if (!rules.isEmpty()) {
                PromotionCouponRule first = rules.get(0);
                vo.setThreshold(first.getThreshold());
                vo.setAmount(first.getAmount());
                vo.setDiscountRate(first.getDiscountRate());
                vo.setIsMutex(first.getIsMutex());
            }

            result.add(vo);
        }
        return result;
    }

    @Override
    public void markAsUsed(Long couponId, Long orderId, Long userId) {
        PromotionUserCoupon coupon = userCouponMapper.selectById(couponId);
        if (coupon == null) {
            throw new ServiceException("优惠券不存在");
        }
        if (!coupon.getUserId().equals(userId)) {
            throw new ServiceException("优惠券不属于当前用户");
        }
        if (coupon.getStatus() == null || coupon.getStatus() != 0) {
            throw new ServiceException("优惠券状态异常，无法使用");
        }
        coupon.setStatus(1);
        coupon.setOrderId(orderId);
        coupon.setUseTime(new Date());
        userCouponMapper.updateById(coupon);
    }
}
