package com.ylx.massage.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ylx.common.core.domain.R;
import com.ylx.common.core.domain.model.WxLoginUser;
import com.ylx.massage.domain.Coupon;
import com.ylx.massage.domain.UserCouponRelation;
import com.ylx.massage.domain.vo.ClaimCouponRequestVO;
import com.ylx.massage.domain.vo.CouponReceiveVo;
import com.ylx.massage.domain.vo.CouponReceivesVO;
import com.ylx.massage.mapper.CouponReceiveMapper;
import com.ylx.massage.domain.CouponReceive;
import com.ylx.massage.mapper.UserCouponRelationMapper;
import com.ylx.massage.service.CouponReceiveService;
import com.ylx.massage.service.CouponService;
import com.ylx.massage.utils.DateTimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.ylx.common.utils.SecurityUtils.getWxLoginUser;

/**
 * 优惠券领取表(CouponReceive)表服务实现类
 *
 * @author makejava
 * @since 2024-05-14 11:25:45
 */
@Slf4j
@Service("couponReceiveService")
public class CouponReceiveServiceImpl extends ServiceImpl<CouponReceiveMapper, CouponReceive> implements CouponReceiveService {

    private static final String SHARE_LOCK_KEY = "coupon_center:receiveCoupon:lock:";

    private static final long LOCK_EXPIRE_TIME = 2L; // 锁过期时间2秒

    @Resource
    private CouponService couponService;

    @Resource
    private CouponReceiveMapper couponReceiveMapper;

    @Resource
    private UserCouponRelationMapper userCouponRelationMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public Coupon submit(CouponReceive couponReceive) {
        Coupon coupon = couponService.getById(couponReceive.getCouponId());
        if (coupon == null) {
            return null;
        }
        LambdaQueryWrapper<CouponReceive> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CouponReceive::getReceiveOpenId, couponReceive.getReceiveOpenId()).eq(CouponReceive::getCouponId, couponReceive.getCouponId());
        //限制领取数量
        List<CouponReceive> one = this.list(queryWrapper);
        if (coupon.getUserLimit() <= one.size()) {
            return null;
        }
        couponReceive.setExpirationTime(DateTimeUtils.addDays(new Date(), coupon.getTermDays()));
        this.save(couponReceive);
        return coupon;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer submits(CouponReceivesVO couponReceive) {
        LambdaQueryWrapper<Coupon> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Coupon::getId, couponReceive.getCouponIds());

        List<Coupon> list = couponService.list(queryWrapper);
        if (CollectionUtil.isEmpty(list)) {
            log.info("优惠卷不存在");
            return null;
        }
        ArrayList<CouponReceive> couponReceives = Lists.newArrayList();
        list.forEach(coupon -> {
            CouponReceive couponRec = new CouponReceive();
            couponRec.setId(Long.toString(IdWorker.getId(couponRec)));
            couponRec.setCouponId(coupon.getId());
            couponRec.setReceiveOpenId(couponReceive.getOpenId());
            /*couponRec.setDeptId(coupon.getDeptId());
            couponRec.setDeptName(coupon.getDeptName());*/
            couponRec.setCouponStatus(0);
            couponRec.setExpirationTime(DateTimeUtils.addDays(new Date(), coupon.getTermDays()));
            couponReceives.add(couponRec);
        });
        return couponReceiveMapper.insertBatch(couponReceives);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<?> receiveVolution(ClaimCouponRequestVO claimCouponRequestVO) {
        // 1、查询用户信息
        WxLoginUser wxLoginUser = getWxLoginUser();
        log.info("当前用户的openId:{}", wxLoginUser.getCOpenid());
        //2、保存优惠券信息到coupon_receive表
        // 构建防重复提交的key：用户openId + 优惠卷id
        String lockKey = SHARE_LOCK_KEY + wxLoginUser.getCOpenid() + ":" + claimCouponRequestVO.getTemplateId();
        // 尝试获取锁，防止重复提交
        Boolean lockResult = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", LOCK_EXPIRE_TIME, TimeUnit.SECONDS);
        if (Boolean.FALSE.equals(lockResult)) {
            return R.fail("操作过于频繁，请稍后再试");
        }

        CouponReceive couponReceive = new CouponReceive();
        couponReceive.setIssuerCouponId(claimCouponRequestVO.getUserId());
        couponReceive.setCouponId(claimCouponRequestVO.getTemplateId());
        couponReceive.setCouponType(Integer.parseInt(claimCouponRequestVO.getType()));
        couponReceive.setReceiveOpenId(wxLoginUser.getCOpenid());
        couponReceive.setReceiveTime(LocalDateTime.now());
        //设置领取人手机号
        couponReceive.setReceiveUserPhone(wxLoginUser.getCPhone());
        //获取当前有效期类型
        String validityType = claimCouponRequestVO.getValidityType();
        switch (validityType) {
            // 固定日期范围
            case "1":
                couponReceive.setValidityType(1);
                couponReceive.setValidStartTime(claimCouponRequestVO.getValidStartTime());
                couponReceive.setExpirationTime(claimCouponRequestVO.getValidEndTime());
                break;
            //领券后N天有效
            case "2":
                couponReceive.setValidityType(2);
                couponReceive.setValidDays(Integer.parseInt(claimCouponRequestVO.getValidDays()));
                break;
            //长期有效
            case "3":
                couponReceive.setValidityType(3);
                break;
            default:
                throw new IllegalArgumentException("有效期类型错误");
        }
        // 设置使用状态：待使用
        couponReceive.setCouponStatus(0);
        int insert = couponReceiveMapper.insert(couponReceive);
        if (insert == 0) {
            return R.fail("优惠券领取失败");
        }

        // 3、将优惠券id和用户id做绑定插入用户优惠券关联表
        UserCouponRelation userCouponRelation = new UserCouponRelation();
        userCouponRelation.setOpenId(wxLoginUser.getCOpenid());
        userCouponRelation.setCouponId(claimCouponRequestVO.getTemplateId());
        userCouponRelation.setCouponName(claimCouponRequestVO.getName());
        userCouponRelation.setImageUrl(claimCouponRequestVO.getImageUrl());
        userCouponRelation.setCouponType(Integer.parseInt(claimCouponRequestVO.getType()));
        //设置状态为未使用
        userCouponRelation.setCouponStatus(0);
        switch (validityType) {
            // 固定日期范围
            case "1":
                userCouponRelation.setValidityType(Integer.parseInt(validityType));
                couponReceive.setValidStartTime(claimCouponRequestVO.getValidStartTime());
                couponReceive.setExpirationTime(claimCouponRequestVO.getValidEndTime());
                break;
            //领券后N天有效
            case "2":
                userCouponRelation.setValidityType(Integer.parseInt(validityType));
                couponReceive.setValidDays(Integer.parseInt(claimCouponRequestVO.getValidDays()));
                break;
            //长期有效
            case "3":
                userCouponRelation.setValidityType(Integer.parseInt(validityType));
                break;
            default:
                throw new IllegalArgumentException("有效期类型错误");
        }
        //市场售价
        BigDecimal marketPrice = BigDecimal.ZERO;
        //2-折扣券
        if ("2".equals(claimCouponRequestVO.getType())) {
            marketPrice = claimCouponRequestVO.getRuleMinSpendAmount().multiply(claimCouponRequestVO.getRuleDiscountRate())
                    .divide(new BigDecimal("10")).setScale(2, RoundingMode.HALF_UP);
        } else if ("3".equals(claimCouponRequestVO.getType())) {
            //满减券
            marketPrice = claimCouponRequestVO.getRuleReductionAmount();
        } else if ("1".equals(claimCouponRequestVO.getType())) {
            //兑换券
            marketPrice = claimCouponRequestVO.getCostPrice();
        }
        userCouponRelation.setMarketPrice(marketPrice);
        // 设置券来源 0:券中心
        userCouponRelation.setTicketSource(0);
        userCouponRelation.setCountry(claimCouponRequestVO.getCountry());
        userCouponRelation.setCountryAll(claimCouponRequestVO.getCountryAll());
        userCouponRelation.setLocality(claimCouponRequestVO.getLocality());
        userCouponRelation.setMerchantId(claimCouponRequestVO.getMerchantId());
        userCouponRelation.setStoreName(claimCouponRequestVO.getStoreName());
        userCouponRelation.setCenterShareUserId(claimCouponRequestVO.getUserId());
        userCouponRelation.setRuleMinSpendAmount(claimCouponRequestVO.getRuleMinSpendAmount());
        userCouponRelation.setRuleDiscountRate(claimCouponRequestVO.getRuleDiscountRate());
        userCouponRelation.setRuleDiscountCapAmount(claimCouponRequestVO.getRuleDiscountCapAmount());
        userCouponRelation.setRuleReductionAmount(claimCouponRequestVO.getRuleReductionAmount());
        userCouponRelation.setReceiveTime(LocalDateTime.now());
        userCouponRelationMapper.insert(userCouponRelation);
        return R.ok("领取成功");
    }

    @Override
    public List<CouponReceiveVo> getByOpenId(String openid) {
        List<CouponReceiveVo> CouponReceiveVos = couponReceiveMapper.getByOpenId(openid);
        CouponReceiveVos.forEach(couponReceiveVo -> {
            if(couponReceiveVo.getExpirationTime() == null){
                couponReceiveVo.setExpirationTimeString("长期有效");
            }else{
                couponReceiveVo.setExpirationTimeString(DateTimeUtils.formatDate(couponReceiveVo.getExpirationTime(), DateTimeUtils.DATE_FORMAT));
            }
        });
        return CouponReceiveVos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeCoupons(List<CouponReceiveVo> coupons) {

        boolean b = this.removeByIds(coupons.stream().map(CouponReceiveVo::getId).collect(Collectors.toList()));
        //使用数量+1
        coupons.forEach(coup -> {
            UpdateWrapper<Coupon> wrapper = new UpdateWrapper<>();
            wrapper.lambda().eq(Coupon::getId, coup.getCouponId());
            wrapper.setSql(" used_num = used_num + " + 1);
            couponService.update(wrapper);
        });
    }

    @Override
    public List<Coupon> couponWindows(CouponReceive couponReceive) {
        //判断是否领过优惠卷
        //查询领取优惠卷
        LambdaQueryWrapper<CouponReceive> query = new LambdaQueryWrapper<>();
        query.eq(CouponReceive::getReceiveOpenId, couponReceive.getReceiveOpenId());
        List<CouponReceive> couponReceive1 = this.list(query);
        //如果没有领取优惠卷
        if (CollectionUtil.isEmpty(couponReceive1)) {
            //查询优惠卷
            LambdaQueryWrapper<Coupon> couponLambdaQueryWrapper = new LambdaQueryWrapper<>();
            couponLambdaQueryWrapper.eq(Coupon::getStatus, 1);
            //couponLambdaQueryWrapper.eq(Coupon::getStatus, 1).like(Coupon::getDeptName, couponReceive.getDeptName());
            //返回新人优惠卷列表
            return couponService.list(couponLambdaQueryWrapper);
        } else {
            return Collections.emptyList();
        }
    }
}

