package com.qs.mp.admin.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.qs.mp.admin.domain.*;
import com.qs.mp.admin.domain.param.*;
import com.qs.mp.admin.domain.vo.MarketingListVO;
import com.qs.mp.admin.mapper.MarketingMapper;
import com.qs.mp.admin.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qs.mp.common.constant.Constants;
import com.qs.mp.common.core.domain.AjaxResult;
import com.qs.mp.common.core.redis.DistributedLocker;
import com.qs.mp.common.core.redis.RedisCache;
import com.qs.mp.common.enums.*;
import com.qs.mp.common.exception.ServiceException;
import com.qs.mp.common.utils.DateUtils;
import com.qs.mp.common.utils.LogUtil;
import com.qs.mp.common.utils.bean.BeanUtils;
import com.qs.mp.framework.redis.RedisKey;
import com.qs.mp.framework.service.IWxSubscribeMessage;
import com.qs.mp.system.domain.SysUser;
import com.qs.mp.system.service.ISysUserService;
import com.qs.mp.system.service.id.BizIdGenerator;
import com.qs.mp.user.domain.MarketingHitPrize;
import com.qs.mp.user.domain.MarketingUserCode;
import com.qs.mp.user.domain.param.MarketingHelpParam;
import com.qs.mp.user.service.IMarketingHitPrizeService;
import com.qs.mp.user.service.IMarketingUserCodeService;
import com.qs.mp.user.service.IUserCoinService;
import com.qs.mp.user.service.IUserPrizeStorageService;
import com.qs.mp.utils.MarketingUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.net.URLDecoder;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 营销活动表 服务实现类
 * </p>
 *
 * @author quanshu
 * @since 2022-05-16
 */
@Service
public class MarketingServiceImpl extends ServiceImpl<MarketingMapper, Marketing> implements IMarketingService {

    // 内部奖池
    public static final String MARKETING_LOTTERY_INSIDE_POOL = "MARKETING_LOTTERY_INSIDE_POOL:%s";

    // 普通奖池
    public static final String MARKETING_LOTTERY_ORDINARY_POOL = "MARKETING_LOTTERY_ORDINARY_POOL:%s";

    // 普通用户低阶奖池
    public static final String MARKETING_LOW_LOTTERY_ORDINARY_POOL = "MARKETING_LOW_LOTTERY_ORDINARY_POOL:%s";


    protected final Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());

    @Autowired
    private IGoodsService goodsService;

    @Autowired
    private ICouponService couponService;

    @Autowired
    private ICouponPkgService couponPkgService;

    @Autowired
    private IMarketingAwardsService marketingAwardsService;

    @Autowired
    private IMarketingAwardsPrizeService marketingAwardsPrizeService;

    @Autowired
    private IMarketingUserCodeService marketingUserCodeService;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IMarketingHitPrizeService marketingHitPrizeService;

    @Autowired
    private IUserCoinService userCoinService;

    @Autowired
    private IUserPrizeStorageService userPrizeStorageService;

    @Autowired
    private BizIdGenerator bizIdGenerator;


    @Autowired
    private IWxSubscribeMessage wxSubscribeMessage;

    @Autowired
    private DistributedLocker distributedLocker;

    @Autowired
    private IMarketingMsgService marketingMsgService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void copyById(Long marketingId) {
        Marketing marketing = this.getById(marketingId);
        if (Objects.isNull(marketing)) {
            throw new ServiceException("活动不存在");
        }
        // 初始化活动
        marketing.setId(null);
        marketing.setFakeNum(0);
        marketing.setRealNum(0);
        marketing.setIsOn(MarketingStatusEnum.OFF.getValue());
        marketing.setIsSend(0);
        marketing.setIsSendLottery(0);
        marketing.setTriggerStatus(0);
        marketing.setCreatedTime(null);
        Assert.isTrue(this.save(marketing), "复制营销活动失败");

        List<MarketingAwards> marketingAwardsList = marketingAwardsService.list(new LambdaQueryWrapper<MarketingAwards>().eq(MarketingAwards::getMarketingId, marketingId));
        if (CollectionUtils.isEmpty(marketingAwardsList)) {
            throw new ServiceException("活动奖级信息不存在");
        }
        for (MarketingAwards marketingAwards : marketingAwardsList) {
            List<MarketingAwardsPrize> marketingAwardsPrizeList = marketingAwardsPrizeService.list(new LambdaQueryWrapper<MarketingAwardsPrize>()
                    .eq(MarketingAwardsPrize::getMarketingId, marketingId)
                    .eq(MarketingAwardsPrize::getAwardsId, marketingAwards.getId()));
            marketingAwards.setId(null);
            marketingAwards.setMarketingId(marketing.getId());
            Assert.isTrue(marketingAwardsService.save(marketingAwards),"复制营销活动奖级失败");
            for (MarketingAwardsPrize marketingAwardsPrize : marketingAwardsPrizeList) {
                marketingAwardsPrize.setId(null);
                marketingAwardsPrize.setAwardsId(marketingAwards.getId());
                marketingAwardsPrize.setMarketingId(marketing.getId());
            }
            Assert.isTrue(marketingAwardsPrizeService.saveBatch(marketingAwardsPrizeList),"复制营销活动奖品失败");
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void generateCode(Long marketingId, Long userId) {

        // 判断是否已经获取过
        int count = marketingUserCodeService.count(new LambdaQueryWrapper<MarketingUserCode>()
                .eq(MarketingUserCode::getUserId, userId)
                .eq(MarketingUserCode::getMarketingId, marketingId)
                .eq(MarketingUserCode::getHelpUserId, -1L));
        if (count > 0) {
            throw new ServiceException("您已经获取过抽奖码了");
        }


        // 生成唯一抽奖码
        String code = getOnlyCode(marketingId);

        MarketingUserCode marketingUserCode = new MarketingUserCode();
        // 设置活动id
        marketingUserCode.setMarketingId(marketingId);
        // 设置抽奖码
        marketingUserCode.setCode(code);
        // 设置用户
        marketingUserCode.setUserId(userId);
        // -1为无人助力获取抽奖码
        marketingUserCode.setHelpUserId(-1L);
        // 设置用户类型
        marketingUserCode.setUserType(UserTypeEnum.ORDINARY.getValue());

        // 保存助力信息
        marketingUserCodeService.save(marketingUserCode);


        // 设置更新虚拟参与人数
        int randomNum = (int) 1 + (int) (Math.random() * 3);
        String fakeNumKey = RedisKey.build(RedisKey.MARKETING_FAKE_NUM, marketingId);
        Integer fakeNum = redisCache.getCacheObject(fakeNumKey);
        if (fakeNum == null) {
            fakeNum = marketingUserCodeService.countRealUserNumByMarketingId(marketingId);
            redisCache.setCacheObject(fakeNumKey, fakeNum * 2 + randomNum, 30, TimeUnit.HOURS);
        } else {
            redisCache.setCacheObject(fakeNumKey, fakeNum + randomNum, 30, TimeUnit.HOURS);
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void lottery(Marketing marketing) {

        // 用户抽奖池
        String userLotteryPool = String.format(MARKETING_LOTTERY_ORDINARY_POOL, marketing.getId());
        // 用户低阶奖池
        String userLowLotteryPool = String.format(MARKETING_LOW_LOTTERY_ORDINARY_POOL, marketing.getId());
        // 内部抽奖池
        String insideLotteryPool = String.format(MARKETING_LOTTERY_INSIDE_POOL, marketing.getId());

        // 获取奖级信息
        List<MarketingAwards> marketingAwardsList = marketingAwardsService.list(new LambdaQueryWrapper<MarketingAwards>()
                .eq(MarketingAwards::getMarketingId, marketing.getId()));

        // 奖品总数
        int prizeQuantity = marketingAwardsList.stream().mapToInt(MarketingAwards::getQuantity).sum();

        // 校准并获取真实参与人数
        int realNum = marketingUserCodeService.countRealUserNumByMarketingId(marketing.getId());

        // 设置需要的内定人数
        int insideNum = 0;

        boolean isInside = false;

        // 参与人数不足,全部采用内定人员开奖
//        if (prizeQuantity >= realNum) {
//            insideNum = prizeQuantity;
//            isInside = true;
//        } else {
            insideNum = marketingAwardsList.stream().mapToInt(MarketingAwards::getInsideNum).sum();
//        }

        // 获取一定数量的内定人员设置抽奖码加入抽奖关系表和抽奖池
        List<SysUser> insideUserList = sysUserService.selectUserListByRand(UserTypeEnum.INSIDE.getValue(), insideNum);

        Set<String> insideCodes = new HashSet<>();
        for (SysUser sysUser : insideUserList) {
            // 生成抽奖码
            String code = MarketingUtils.generatePrizeCode();
            while (true) {
                // 判断抽奖码是否已经存在
                int codeCount = marketingUserCodeService.count(new LambdaQueryWrapper<MarketingUserCode>()
                        .eq(MarketingUserCode::getMarketingId, marketing.getId())
                        .eq(MarketingUserCode::getCode, code));
                if (codeCount > 0) {
                    code = MarketingUtils.generatePrizeCode();
                    continue;
                }
                break;
            }
            insideCodes.add(code);
            MarketingUserCode marketingUserCode = new MarketingUserCode();
            marketingUserCode.setMarketingId(marketing.getId());
            marketingUserCode.setUserId(sysUser.getUserId());
            marketingUserCode.setUserType(UserTypeEnum.INSIDE.getValue());
            marketingUserCode.setCode(code);
            marketingUserCode.setHelpUserId(0L);
            // 设置中奖
            marketingUserCode.setIsHit(1);
            marketingUserCodeService.save(marketingUserCode);
        }
        // 将抽奖码放入内部抽奖池
        redisCache.setCacheSet(insideLotteryPool, insideCodes);


        // 获取普通用户拉新所获得的所有的抽奖码
        List<MarketingUserCode> userCodeList = marketingUserCodeService.list(new LambdaQueryWrapper<MarketingUserCode>()
                .eq(MarketingUserCode::getMarketingId, marketing.getId())
                .eq(MarketingUserCode::getUserType, UserTypeEnum.ORDINARY.getValue()));
        if (CollectionUtils.isNotEmpty(userCodeList)) {
            // 用户普通抽奖码
            Set<String> userCodes = new HashSet<>();
            // 用户低阶抽奖码
            Set<String> userLowCodes = new HashSet<>();
            for (MarketingUserCode marketingUserCode : userCodeList) {
                if (marketingUserCode.getHelpUserId() == -1L) {
                    userLowCodes.add(marketingUserCode.getCode());
                } else {
                    userCodes.add(marketingUserCode.getCode());
                }
            }
            if (CollectionUtils.isNotEmpty(userCodes)) {
                // 将抽奖码放入普通抽奖池
                redisCache.setCacheSet(userLotteryPool, userCodes);
            }
            if (CollectionUtils.isNotEmpty(userLowCodes)) {
                // 将抽奖码放入低阶抽奖池
                redisCache.setCacheSet(userLowLotteryPool, userLowCodes);
            }
        }


        // 所有中奖名单
        List<MarketingHitPrize> allHitPrizeList = new ArrayList<>();

        // 普通用户中奖名单
        List<MarketingHitPrize> userHitPrizeList = new ArrayList<>();

        // 抽奖码中奖状态更新列表
        List<MarketingUserCode> userCodeUpdateList = new ArrayList<>();

        // 遍历奖级进行抽奖
        for (MarketingAwards marketingAwards : marketingAwardsList) {
            // 获取内部人数
            if (isInside) {
                insideNum = marketingAwards.getQuantity();
            } else {
                insideNum = marketingAwards.getInsideNum();
            }

            List<MarketingAwardsPrize> marketingAwardsPrizeList = marketingAwardsPrizeService.list(new LambdaQueryWrapper<MarketingAwardsPrize>()
                    .eq(MarketingAwardsPrize::getMarketingId, marketing.getId())
                    .eq(MarketingAwardsPrize::getAwardsId, marketingAwards.getId()));

            if (insideNum != 0) {
                // 设置内部用户抽奖信息
                List<String> insideCodeList = redisCache.popCacheSet(insideLotteryPool, insideNum);
                for (String code : insideCodeList) {
                    MarketingUserCode marketingUserCode = marketingUserCodeService.getOne(new LambdaQueryWrapper<MarketingUserCode>()
                            .eq(MarketingUserCode::getMarketingId, marketing.getId())
                            .eq(MarketingUserCode::getCode, code));

                    // 设置中奖信息
                    exchangeMarketingHitPrize(marketing, allHitPrizeList, marketingAwards, marketingAwardsPrizeList, marketingUserCode);
                }
            }

            // 用户中奖数量为 名额 - 内定人数
            int userNum = marketingAwards.getQuantity() - insideNum;
            if (userNum > 0) {
                // 设置普通用户抽奖信息
                for (int i = 0; i < userNum; i++) {
                    List<String> hitCodeList = redisCache.popCacheSet(userLotteryPool, 1);
                    if (CollectionUtils.isEmpty(hitCodeList)) {
                        hitCodeList = redisCache.popCacheSet(userLowLotteryPool, 1);
                    }
                    if (CollectionUtils.isEmpty(hitCodeList)) {
                        break;
                    }
                    MarketingUserCode marketingUserCode = marketingUserCodeService.getOne(new LambdaQueryWrapper<MarketingUserCode>()
                            .eq(MarketingUserCode::getMarketingId, marketing.getId())
                            .eq(MarketingUserCode::getCode, hitCodeList.get(0)));

                    // 删除redis中该用户所有的抽奖码
                    List<MarketingUserCode> list = marketingUserCodeService.list(new LambdaQueryWrapper<MarketingUserCode>()
                            .eq(MarketingUserCode::getMarketingId, marketing.getId())
                            .eq(MarketingUserCode::getUserId, marketingUserCode.getUserId()));
                    List<Object> delUserCodeList = list.stream().map(MarketingUserCode::getCode).collect(Collectors.toList());
                    redisCache.removeSetValueByKey(userLotteryPool, delUserCodeList);
                    redisCache.removeSetValueByKey(userLowLotteryPool, delUserCodeList);
                    MarketingHitPrize marketingHitPrize = exchangeMarketingHitPrize(marketing, allHitPrizeList, marketingAwards, marketingAwardsPrizeList, marketingUserCode);

                    userHitPrizeList.add(marketingHitPrize);

                    // 更新用户中奖状态
                    marketingUserCode.setIsHit(1);
                    userCodeUpdateList.add(marketingUserCode);
                }
            }
        }
        // 保存中奖信息
        Assert.isTrue(marketingHitPrizeService.saveBatch(allHitPrizeList), "保存中奖信息失败。marketingId:" + marketing.getId());

        // 更新抽奖码中奖状态
        if (CollectionUtils.isNotEmpty(userCodeUpdateList)) {
            boolean rtn = marketingUserCodeService.updateBatchById(userCodeUpdateList);
            Assert.isTrue(rtn, "更新抽奖码中奖状态失败。marketingId:" + marketing.getId());
        }

        // 发奖品
        if (CollectionUtils.isNotEmpty(userHitPrizeList)) {
            for (MarketingHitPrize marketingHitPrize : userHitPrizeList) {
                MarketingAwardsPrize marketingAwardsPrize = marketingAwardsPrizeService.getById(marketingHitPrize.getPrizeId());

                // 放入仓库
                if (marketingAwardsPrize.getPrizeType() == TicketPrizeTypeEnum.COIN) {
                    userCoinService.produce(marketingHitPrize.getUserId(), marketingAwardsPrize.getValue(), String.valueOf(marketingHitPrize.getId()), CoinLogTypeEnum.MARKETING);
                } else if (marketingAwardsPrize.getPrizeType() == TicketPrizeTypeEnum.COUPON) {
                    couponService.distributeByMarketing(marketingHitPrize.getUserId(), marketingAwardsPrize.getRefId());
                } else if (marketingAwardsPrize.getPrizeType() == TicketPrizeTypeEnum.COUPON_PKG) {
                    couponPkgService.distributeByMarketing(marketingHitPrize.getUserId(), marketingAwardsPrize.getRefId());
                } else {
                    // 实物奖品
                    userPrizeStorageService.takeInStorage(marketingHitPrize.getUserId(), marketingAwardsPrize.getTitle(), marketingAwardsPrize.getPicUrl(), marketingAwardsPrize.getRefId(), PrizeStorageInTypeEnum.MARKETING, marketingHitPrize.getId());
                }
            }
        }

        // 更新活动状态
        boolean rtn = this.update(new LambdaUpdateWrapper<Marketing>().set(Marketing::getTriggerStatus, 1)
                .eq(Marketing::getId, marketing.getId())
                .eq(Marketing::getTriggerStatus, 0));
        Assert.isTrue(rtn, "更新活动开奖状态失败。marketingId:" + marketing.getId());

        // 删除抽奖池
        redisCache.deleteObject(userLotteryPool);
        redisCache.deleteObject(userLowLotteryPool);
        redisCache.deleteObject(insideLotteryPool);

    }

    private MarketingHitPrize exchangeMarketingHitPrize(Marketing marketing, List<MarketingHitPrize> allHitPrizeList, MarketingAwards marketingAwards, List<MarketingAwardsPrize> marketingAwardsPrizeList, MarketingUserCode marketingUserCode) {
        // 设置中奖信息
        MarketingHitPrize marketingHitPrize = new MarketingHitPrize();
        marketingHitPrize.setId(bizIdGenerator.newId());
        marketingHitPrize.setMarketingId(marketing.getId());
        marketingHitPrize.setAwardsId(marketingAwards.getId());
        marketingHitPrize.setMarketingUserCodeId(marketingUserCode.getId());
        marketingHitPrize.setUserId(marketingUserCode.getUserId());
        marketingHitPrize.setUserType(marketingUserCode.getUserType());

        // 随机抽取奖品,[0, list.size)  左闭右开
        int randomIndex = RandomUtil.randomInt(0, marketingAwardsPrizeList.size());
        marketingHitPrize.setPrizeId(marketingAwardsPrizeList.get(randomIndex).getId());

        allHitPrizeList.add(marketingHitPrize);
        return marketingHitPrize;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void help(MarketingHelpParam marketingHelpParam, Long userId) {
        String inviteCode = marketingHelpParam.getInviteCode();
        // 邀请码解码,被助力人id
        Long helpedUserId = MarketingUtils.decodeInviteCode(inviteCode);

        Marketing marketing = this.getById(marketingHelpParam.getMarketingId());

        // 处理助力信息
        // 判断是否已经助力过
        int count = marketingUserCodeService.count(new LambdaQueryWrapper<MarketingUserCode>()
                .eq(MarketingUserCode::getHelpUserId, userId));
        if (count > 0) {
            throw new ServiceException("您已经助力过了");
        }
        // 生成唯一抽奖码
        String code = getOnlyCode(marketing.getId());

        MarketingUserCode marketingUserCode = new MarketingUserCode();
        // 设置活动id
        marketingUserCode.setMarketingId(marketingHelpParam.getMarketingId());
        // 设置抽奖码
        marketingUserCode.setCode(code);
        // 设置被助力人
        marketingUserCode.setUserId(helpedUserId);
        // 设置助力人
        marketingUserCode.setHelpUserId(userId);
        marketingUserCode.setUserType(UserTypeEnum.ORDINARY.getValue());

        // 保存助力信息
        marketingUserCodeService.save(marketingUserCode);


        // 自己获得一个普通抽奖码
        MarketingUserCode myCode= new MarketingUserCode();
        myCode.setMarketingId(marketing.getId());
        // 设置抽奖码
        myCode.setCode(getOnlyCode(marketing.getId()));
        // 设置被助力人
        myCode.setUserId(userId);
        myCode.setHelpUserId(-1L);
        myCode.setUserType(UserTypeEnum.ORDINARY.getValue());

        // 保存抽奖码
        marketingUserCodeService.save(myCode);


        // 设置更新虚拟参与人数
        int randomNum = (int) 1 + (int) (Math.random() * 3);
        String fakeNumKey = RedisKey.build(RedisKey.MARKETING_FAKE_NUM, marketing.getId());
        Integer fakeNum = redisCache.getCacheObject(fakeNumKey);
        if (fakeNum == null) {
            fakeNum = marketingUserCodeService.countRealUserNumByMarketingId(marketing.getId());
            redisCache.setCacheObject(fakeNumKey, fakeNum * 2 + randomNum, 30, TimeUnit.HOURS);
        } else {
            redisCache.setCacheObject(fakeNumKey, fakeNum + randomNum, 30, TimeUnit.HOURS);
        }

    }

    /**
     * 获取当前活动用户唯一的抽奖码
     * @param marketingId
     * @return
     */
    private String getOnlyCode(Long marketingId) {
        String code = "";
        while (true) {
            code = MarketingUtils.generatePrizeCode();
            // 判断抽奖码是否已经存在
            int codeCount = marketingUserCodeService.count(new LambdaQueryWrapper<MarketingUserCode>()
                    .eq(MarketingUserCode::getMarketingId, marketingId)
                    .eq(MarketingUserCode::getCode, code));
            if (codeCount > 0) {
                continue;
            }
            break;
        }
        return code;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteById(Long id) {
        this.removeById(id);

        // 删除奖级和奖品信息
        marketingAwardsService.remove(new LambdaQueryWrapper<MarketingAwards>().eq(MarketingAwards::getMarketingId, id));

        marketingAwardsPrizeService.remove(new LambdaQueryWrapper<MarketingAwardsPrize>().eq(MarketingAwardsPrize::getMarketingId, id));

    }

    @Override
    public List<Marketing> listMarketing(MarketingQueryParam marketingQueryParam) {
        LambdaQueryWrapper<Marketing> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(marketingQueryParam.getTitle())) {
            queryWrapper.like(Marketing::getTitle, marketingQueryParam.getTitle());
        }

        if (Objects.nonNull(marketingQueryParam.getStatus())) {
            if (MarketingStatusEnum.CLOSE.getValue().equals(marketingQueryParam.getStatus()) ||
                    MarketingStatusEnum.OFF.getValue().equals(marketingQueryParam.getStatus()) ||
                    MarketingStatusEnum.ON.getValue().equals(marketingQueryParam.getStatus())) {
                queryWrapper.eq(Marketing::getIsOn, marketingQueryParam.getStatus());
            } else if (MarketingStatusEnum.UNSTART.getValue().equals(marketingQueryParam.getStatus())) {
                queryWrapper.gt(Marketing::getStartTime, new Date());
                queryWrapper.eq(Marketing::getIsOn, MarketingStatusEnum.ON.getValue());
            } else if (MarketingStatusEnum.START.getValue().equals(marketingQueryParam.getStatus())) {
                queryWrapper.le(Marketing::getStartTime, new Date());
                queryWrapper.ge(Marketing::getEndTime, new Date());
                queryWrapper.eq(Marketing::getIsOn, MarketingStatusEnum.ON.getValue());
            } else if (MarketingStatusEnum.END.getValue().equals(marketingQueryParam.getStatus())) {
                queryWrapper.lt(Marketing::getEndTime, new Date());
                queryWrapper.eq(Marketing::getIsOn, MarketingStatusEnum.ON.getValue());
            }
        }

        queryWrapper.orderByDesc(Marketing::getCreatedTime);


        return this.list(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createMarketing(MarketingCreateParam marketingCreateParam) {
        // 保存营销活动
        Marketing marketing = new Marketing();
        BeanUtils.copyProperties(marketingCreateParam, marketing);

        if (StringUtils.isNotBlank(marketingCreateParam.getDescription())) {
            marketing.setDescription(URLDecoder.decode(marketingCreateParam.getDescription()));
        }

        this.save(marketing);

        // 创建奖级和奖品信息
        createAwardsAndPrize(marketingCreateParam.getAwardsList(), marketing);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateMarketing(MarketingUpdateParam marketingUpdateParam) {
        Marketing marketing = this.getById(marketingUpdateParam.getId());
        if (Objects.isNull(marketing)) {
            throw new ServiceException("营销活动不存在");
        }

        if (MarketingStatusEnum.CLOSE.getValue().equals(marketing.getIsOn())) {
            throw new ServiceException("活动当前状态不支持修改");
        }

        Date now = DateUtils.getNowDate();
        if (MarketingStatusEnum.ON.getValue().equals(marketing.getIsOn()) && now.after(marketing.getEndTime())) {
            throw new ServiceException("活动当前状态不支持修改");
        }


        // 更新营销活动
        BeanUtils.copyProperties(marketingUpdateParam, marketing);

        if (StringUtils.isNotBlank(marketingUpdateParam.getDescription())) {
            marketing.setDescription(URLDecoder.decode(marketingUpdateParam.getDescription()));
        }

        this.updateById(marketing);

        // 删除奖级和奖品信息
        marketingAwardsService.remove(new LambdaUpdateWrapper<MarketingAwards>().eq(MarketingAwards::getMarketingId, marketing.getId()));
        marketingAwardsPrizeService.remove(new LambdaUpdateWrapper<MarketingAwardsPrize>().eq(MarketingAwardsPrize::getMarketingId, marketing.getId()));

        // 创建奖级和奖品信息
        createAwardsAndPrize(marketingUpdateParam.getAwardsList(), marketing);
    }

    /**
     * 创建奖级和奖品信息
     *
     * @param awardsList
     * @param marketing
     */
    private void createAwardsAndPrize(List<MarketingAwardsParam> awardsList, Marketing marketing) {

        int insideNum = 0;
        // 创建奖级
        List<MarketingAwardsPrize> marketingAwardsPrizeList = new ArrayList<>();
        for (MarketingAwardsParam awardsParam : awardsList) {
            insideNum += awardsParam.getInsideNum();
            if (awardsParam.getInsideNum() > awardsParam.getQuantity()) {
                throw new ServiceException("内定数量不能大于奖品数量");
            }

            MarketingAwards marketingAwards = new MarketingAwards();
            BeanUtils.copyProperties(awardsParam, marketingAwards);
            marketingAwards.setId(null);
            // 设置活动id
            marketingAwards.setMarketingId(marketing.getId());
            marketingAwardsService.save(marketingAwards);

            for (MarketingAwardsPrizeParam prizeParam : awardsParam.getPrizeList()) {
                MarketingAwardsPrize awardsPrize = new MarketingAwardsPrize();
                BeanUtils.copyProperties(prizeParam, awardsPrize);
                awardsPrize.setId(null);
                awardsPrize.setMarketingId(marketing.getId());
                awardsPrize.setAwardsId(marketingAwards.getId());
                if (null == awardsPrize.getQuantity() || 0 == awardsPrize.getQuantity()) {
                    // 页面没设置奖品的具体数量，则默认为整个奖项的数量
                    awardsPrize.setQuantity(marketingAwards.getQuantity());
                }
                if (prizeParam.getPrizeType() == TicketPrizeTypeEnum.GOODS) {
                    Goods goods = goodsService.getById(awardsPrize.getRefId());
                    awardsPrize.setTitle(goods.getTitle());
                    awardsPrize.setPicUrl(goods.getPicUrl());
                    awardsPrize.setValue(goods.getValue());
                } else if (prizeParam.getPrizeType() == TicketPrizeTypeEnum.COUPON) {
                    Coupon coupon = couponService.getById(awardsPrize.getRefId());
                    awardsPrize.setTitle(coupon.getTitle());
                    awardsPrize.setPicUrl(coupon.getPicUrl());
                    awardsPrize.setValue(coupon.getDiscount());
                } else if (prizeParam.getPrizeType() == TicketPrizeTypeEnum.COUPON_PKG) {
                    CouponPkg couponPkg = couponPkgService.getById(awardsPrize.getRefId());
                    awardsPrize.setTitle(couponPkg.getTitle());
                    awardsPrize.setValue(couponPkg.getFacePrice());
                    awardsPrize.setPicUrl(couponPkg.getPicUrl());
                } else {
                    awardsPrize.setTitle("盲豆");
                    awardsPrize.setPicUrl(Constants.MANGDOU_PIC);
                }
                marketingAwardsPrizeList.add(awardsPrize);
            }
        }
        if (insideNum > 100) {
            throw new ServiceException("内定人数不能超过100");
        }
        marketingAwardsPrizeService.saveBatch(marketingAwardsPrizeList);
    }


}
