
package com.tmerclub.cloud.user.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.tmerclub.cloud.api.coupon.constant.PutOnStatus;
import com.tmerclub.cloud.api.coupon.feign.CouponFeignClient;
import com.tmerclub.cloud.api.coupon.vo.CouponDataVO;
import com.tmerclub.cloud.api.feign.SearchSpuFeignClient;
import com.tmerclub.cloud.api.multishop.constant.ShopStatus;
import com.tmerclub.cloud.api.multishop.feign.ShopDetailFeignClient;
import com.tmerclub.cloud.api.multishop.feign.ShopRenovationFeignClient;
import com.tmerclub.cloud.api.multishop.vo.ShopDetailVO;
import com.tmerclub.cloud.api.multishop.vo.ShopRenovationVO;
import com.tmerclub.cloud.api.product.feign.CategoryFeignClient;
import com.tmerclub.cloud.api.user.vo.UserApiVO;
import com.tmerclub.cloud.common.cache.constant.CacheNames;
import com.tmerclub.cloud.common.cache.constant.UserCacheNames;
import com.tmerclub.cloud.common.cache.util.RedisUtil;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.constant.JumpType;
import com.tmerclub.cloud.common.constant.StatusEnum;
import com.tmerclub.cloud.common.database.dto.PageDTO;
import com.tmerclub.cloud.common.database.util.PageUtil;
import com.tmerclub.cloud.common.database.vo.PageVO;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.product.constant.SpuStatus;
import com.tmerclub.cloud.common.product.vo.CategoryVO;
import com.tmerclub.cloud.common.product.vo.search.SpuSearchVO;
import com.tmerclub.cloud.common.util.BeanUtil;
import com.tmerclub.cloud.user.bo.CategoryLinkBO;
import com.tmerclub.cloud.user.bo.JumpUrlBO;
import com.tmerclub.cloud.user.bo.mongo.MongoPopupUserLogBO;
import com.tmerclub.cloud.user.constant.*;
import com.tmerclub.cloud.user.dto.CostPerPopupDTO;
import com.tmerclub.cloud.user.mapper.CostPerPopupMapper;
import com.tmerclub.cloud.user.mapper.UserLevelMapper;
import com.tmerclub.cloud.user.model.CostPerPopup;
import com.tmerclub.cloud.user.model.PopupRelate;
import com.tmerclub.cloud.user.model.UserLevel;
import com.tmerclub.cloud.user.service.CostPerPopupService;
import com.tmerclub.cloud.user.service.PopupRelateService;
import com.tmerclub.cloud.user.service.PopupUserLogService;
import com.tmerclub.cloud.user.vo.CostPerPopupVO;
import com.tmerclub.cloud.user.vo.PopupRelateVO;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 弹窗广告
 * @author TRACK
 */
@Service
public class CostPerPopupServiceImpl implements CostPerPopupService {

    @Autowired
    private CostPerPopupMapper costPerPopupMapper;
    @DubboReference
    private SearchSpuFeignClient searchSpuFeignClient;
    @Autowired
    private UserLevelMapper userLevelMapper;
    @Autowired
    private PopupRelateService popupRelateService;
    @Autowired
    private PopupUserLogService popupUserLogService;
    @Autowired
    private MongoTemplate mongoTemplate;
    @DubboReference
    private CouponFeignClient couponFeignClient;
    @DubboReference
    private ShopDetailFeignClient shopDetailFeignClient;
    @DubboReference
    private CategoryFeignClient categoryFeignClient;
    @DubboReference
    private ShopRenovationFeignClient shopRenovationFeignClient;

    @Override
    public PageVO<CostPerPopupVO> page(PageDTO pageDTO, CostPerPopupDTO costPerPopupDTO) {
        return PageUtil.doPage(pageDTO, () -> costPerPopupMapper.list(costPerPopupDTO));
    }

    @Override
    public CostPerPopup getShopPopupByCondition(Integer isShopCustomer, Integer pageType, Long spuId, Long shopId, Long userId, Long uuid) {
        // 当商家选了多件商品，频次一天一次，则进入这些商品详情页也只会弹一次，不会每个商品都弹
        List<CostPerPopup> costPerPopupList = costPerPopupMapper.getShopPopupByCondition(isShopCustomer, pageType, spuId, shopId);
        if (CollUtil.isEmpty(costPerPopupList)) {
            return null;
        }
        // 校验时间
        Iterator<CostPerPopup> iterator = costPerPopupList.iterator();
        while (iterator.hasNext()) {
            CostPerPopup costPerPopup = iterator.next();
            // 校验是否为跳转优惠券并且用户领取过并且有库存
            if (checkCoupon(userId, iterator, costPerPopup)) {
                continue;
            }
            if (Objects.equals(costPerPopup.getPushFrequency(), PushFrequencyEnum.EVERY_TIME.value())) {
                // 每次进入直接返回
                return costPerPopup;
            }
            if (Objects.equals(costPerPopup.getPushFrequency(), PushFrequencyEnum.ONCE.value())) {
                // 永久一次的校验是否曾推送过
                List<MongoPopupUserLogBO> list = popupUserLogService.getByCondition(userId, uuid, costPerPopup);
                if (CollUtil.isEmpty(list)) {
                    return costPerPopup;
                }
                // 推送过了
                iterator.remove();
                continue;
            }
            checkWeek(iterator, costPerPopup);
        }
        if (CollUtil.isEmpty(costPerPopupList)) {
            return null;
        }
        // 校验弹窗日志
        for (CostPerPopup costPerPopup : costPerPopupList) {
            List<MongoPopupUserLogBO> list = popupUserLogService.getByCondition(userId, uuid, costPerPopup);
            if (CollUtil.isEmpty(list)) {
                return costPerPopup;
            }
        }
        return null;
    }

    private boolean checkCoupon(Long userId, Iterator<CostPerPopup> iterator, CostPerPopup costPerPopup) {
        // 如果是提示领取同一张优惠券的，则用户领取完之后不再推送
        JumpUrlBO jumpUrlBO = JSON.parseObject(costPerPopup.getJumpUrl(), JumpUrlBO.class);
        if (!Objects.equals(jumpUrlBO.getType(), JumpType.COUPON.value())) {
            return false;
        }
        Long couponId = Long.parseLong(jumpUrlBO.getLink());
        if (Objects.nonNull(userId)) {
            Query query = new Query(Criteria.where("couponId").is(couponId).and("userId").is(userId));
            long receiveCount = mongoTemplate.count(query, "coupon_user");
            if (receiveCount > 0) {
                // 优惠券领取过
                iterator.remove();
                return true;
            }
        }
        // 校验库存
        Integer stock = couponFeignClient.getStockByCouponId(couponId).getData();
        return stock < 1;
    }

    @Override
    public CostPerPopup getSysPopupByCondition(UserApiVO user, Integer pageType, Long uuid) {
        List<Long> levelIds = new ArrayList<>(Collections.singletonList(user.getUserLevelId()));
        if (Objects.equals(user.getLevelType(), LevelTypeEnum.PAY_USER.value())) {
            levelIds.add(user.getVipUserLevelId());
        }
        List<CostPerPopup> costPerPopupList = costPerPopupMapper.getSysPopupByCondition(levelIds, pageType);
        if (CollUtil.isEmpty(costPerPopupList)) {
            return null;
        }
        // 校验时间
        Iterator<CostPerPopup> iterator = costPerPopupList.iterator();
        while (iterator.hasNext()) {
            CostPerPopup costPerPopup = iterator.next();
            // 校验是否为跳转优惠券并且用户领取过
            if (checkCoupon(user.getUserId(), iterator, costPerPopup)) {
                continue;
            }
            if (Objects.equals(costPerPopup.getPushFrequency(), PushFrequencyEnum.EVERY_TIME.value())) {
                // 每次进入直接返回
                return costPerPopup;
            }
            if (Objects.equals(costPerPopup.getPushFrequency(), PushFrequencyEnum.ONCE.value())) {
                // 永久一次的校验是否曾推送过
                List<MongoPopupUserLogBO> list = popupUserLogService.getByCondition(user.getUserId(), uuid, costPerPopup);
                if (CollUtil.isEmpty(list)) {
                    return costPerPopup;
                }
                // 推送过了
                iterator.remove();
            }
            checkWeek(iterator, costPerPopup);
        }
        if (CollUtil.isEmpty(costPerPopupList)) {
            return null;
        }
        // 校验弹窗日志
        for (CostPerPopup costPerPopup : costPerPopupList) {
            List<MongoPopupUserLogBO> list = popupUserLogService.getByCondition(user.getUserId(), uuid, costPerPopup);
            if (CollUtil.isEmpty(list)) {
                return costPerPopup;
            }
        }
        return null;
    }

    private static void checkWeek(Iterator<CostPerPopup> iterator, CostPerPopup costPerPopup) {
        if (Objects.equals(costPerPopup.getPushFrequency(), PushFrequencyEnum.CUSTOM.value()) && StrUtil.isNotBlank(costPerPopup.getWeekFrequency())) {
            List<String> weeks = Arrays.stream(costPerPopup.getWeekFrequency().split(StrUtil.COMMA)).toList();
            int week = DateUtil.dayOfWeek(new Date());
            if (!weeks.contains(String.valueOf(week))) {
                iterator.remove();
            }
        }
    }

    @Override
    @Cacheable(value = UserCacheNames.POPUP_KEY, key = "#popupId")
    public CostPerPopupVO getByPopupId(Long popupId) {
        CostPerPopup popup = costPerPopupMapper.getByPopupId(popupId);
        CostPerPopupVO popupVO = BeanUtil.map(popup, CostPerPopupVO.class);
        List<PopupRelate> relateList = popupRelateService.getByPopupId(popupId);
        if (CollUtil.isNotEmpty(relateList)) {
            List<PopupRelateVO> popupRelateVOList = BeanUtil.mapAsList(relateList, PopupRelateVO.class);
            popupVO.setPopupRelateList(popupRelateVOList);
        }
        return popupVO;
    }

    @Override
    public void handleInfo(CostPerPopupVO popup) {
        if (CollUtil.isEmpty(popup.getPopupRelateList())) {
            return;
        }
        List<PopupRelateVO> popupRelateVOList = popup.getPopupRelateList();
        // 组装商品/会员等级数据
        if (Objects.equals(popup.getPageType(), PopupPageTypeEnum.SPU_DETAIL.value())) {
            List<Long> spuIds = popupRelateVOList.stream().map(PopupRelateVO::getSpuId).collect(Collectors.toList());
            List<SpuSearchVO> spuList = searchSpuFeignClient.listNotDeleteSpu(spuIds).getData();
            Map<Long, SpuSearchVO> spuMap = spuList.stream().filter(spu -> Objects.equals(spu.getSpuStatus(), SpuStatus.PUT_SHELF.value())).collect(Collectors.toMap(SpuSearchVO::getSpuId, s -> s));
            Iterator<PopupRelateVO> iterator = popupRelateVOList.iterator();
            while (iterator.hasNext()) {
                PopupRelateVO popupRelateVO = iterator.next();
                SpuSearchVO spuSearchVO = spuMap.get(popupRelateVO.getSpuId());
                if (Objects.isNull(spuSearchVO)) {
                    iterator.remove();
                    continue;
                }
                popupRelateVO.setSpuName(spuSearchVO.getSpuName());
                popupRelateVO.setMainImgUrl(spuSearchVO.getMainImgUrl());
            }
        }
        boolean isLevel = Objects.equals(popup.getShopId(), Constant.PLATFORM_SHOP_ID)
                && (Objects.equals(popup.getUserType(), PopupUserTypeEnum.FREE_USER.value())
                || Objects.equals(popup.getUserType(), PopupUserTypeEnum.PAY_USER.value()));
        if (isLevel) {
            List<Long> userLevelIds = popupRelateVOList.stream().map(PopupRelateVO::getUserLevelId).collect(Collectors.toList());
            List<UserLevel> userLevels = userLevelMapper.listUserLevelIds(userLevelIds);
            Map<Long, String> levelMap = userLevels.stream().collect(Collectors.toMap(UserLevel::getUserLevelId, UserLevel::getLevelName));
            Iterator<PopupRelateVO> iterator = popupRelateVOList.iterator();
            while (iterator.hasNext()) {
                PopupRelateVO popupRelateVO = iterator.next();
                String levelName = levelMap.get(popupRelateVO.getUserLevelId());
                if (StrUtil.isBlank(levelName)) {
                    iterator.remove();
                    continue;
                }
                popupRelateVO.setLevelName(levelName);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(CostPerPopup costPerPopup) {
        setTime(costPerPopup);
        checkJumpUrl(costPerPopup);
        List<Long> spuIds = checkAndGetSpuIds(costPerPopup);
        List<Long> userLevelIds = checkAndGetUserLevelIds(costPerPopup);
        costPerPopupMapper.save(costPerPopup);
        List<PopupRelate> popupRelates = getPopupRelates(costPerPopup, spuIds, userLevelIds);
        if (CollUtil.isNotEmpty(popupRelates)) {
            popupRelateService.saveBatch(popupRelates);
        }
    }

    private void checkJumpUrl(CostPerPopup costPerPopup) {
        JumpUrlBO jumpUrlBO = JSON.parseObject(costPerPopup.getJumpUrl(), JumpUrlBO.class);
        String type = jumpUrlBO.getType();
        if (Objects.equals(type, JumpType.SPU.value())) {
            List<SpuSearchVO> data = searchSpuFeignClient.listNotDeleteSpu(Collections.singletonList(Long.valueOf(jumpUrlBO.getLink()))).getData();
            if (!Objects.equals(data.get(0).getSpuStatus(), SpuStatus.PUT_SHELF.value())) {
                throw new LuckException("跳转商品状态异常，请重新选择");
            }
            return;
        }
        if (Objects.equals(type, JumpType.CATEGORY.value())) {
            List<CategoryLinkBO> linkList = JSON.parseArray(jumpUrlBO.getLink(), CategoryLinkBO.class);
            CategoryLinkBO categoryLinkBO = linkList.get(linkList.size() - 1);
            CategoryVO categoryVO = categoryFeignClient.getByCategoryId(categoryLinkBO.getValue()).getData();
            if (!Objects.equals(categoryVO.getStatus(), StatusEnum.ENABLE.value())) {
                throw new LuckException("跳转分类状态异常，请重新选择");
            }
            return;
        }
        if (Objects.equals(type, JumpType.SHOP.value())) {
            ShopDetailVO shopDetailVO = shopDetailFeignClient.getShopDetailByShopId(Long.valueOf(jumpUrlBO.getLink())).getData();
            if (!Objects.equals(shopDetailVO.getShopStatus(), ShopStatus.OPEN.value())) {
                throw new LuckException("跳转店铺状态异常，请重新选择");
            }
            return;
        }
        if (Objects.equals(type, JumpType.MINI_PAGE.value())) {
            ShopRenovationVO shopRenovationVO = shopRenovationFeignClient.getbyRenovationId(Long.valueOf(jumpUrlBO.getLink())).getData();
            if (Objects.isNull(shopRenovationVO)) {
                throw new LuckException("跳转微页面状态异常，请重新选择");
            }
            return;
        }
        if (Objects.equals(type, JumpType.COUPON.value())) {
            List<CouponDataVO> couponDataVOList = couponFeignClient.getCouponListByCouponIds(Collections.singletonList(Long.valueOf(jumpUrlBO.getLink()))).getData();
            if (CollUtil.isEmpty(couponDataVOList) || !Objects.equals(couponDataVOList.get(0).getPutonStatus(), PutOnStatus.PUT_ON.value())) {
                throw new LuckException("跳转优惠券状态异常，请重新选择");
            }
        }
    }

    private static void setTime(CostPerPopup costPerPopup) {
        if (!Objects.equals(costPerPopup.getPushFrequency(), PushFrequencyEnum.CUSTOM.value())) {
            costPerPopup.setWeekFrequency(null);
            costPerPopup.setDayFrequency(null);
        }
        if (costPerPopup.getStartTime().getTime() > System.currentTimeMillis()) {
            costPerPopup.setStatus(PopupStatusEnum.NOT_START.value());
        } else if (costPerPopup.getEndTime().getTime() < System.currentTimeMillis()) {
            costPerPopup.setStatus(PopupStatusEnum.FINISH.value());
        } else {
            costPerPopup.setStatus(PopupStatusEnum.PUT_ON.value());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = UserCacheNames.POPUP_KEY, key = "#costPerPopup.popupId")
    public void update(CostPerPopup costPerPopup) {
        CostPerPopup dbPopup = costPerPopupMapper.getByPopupId(costPerPopup.getPopupId());
        if (Objects.isNull(dbPopup)) {
            throw new LuckException("活动不存在");
        }
        if (Objects.equals(dbPopup.getStatus(), PopupStatusEnum.FINISH.value())) {
            throw new LuckException("当前活动已结束，无法更新信息");
        }
        checkJumpUrl(costPerPopup);
        setTime(costPerPopup);
        List<Long> spuIds = checkAndGetSpuIds(costPerPopup);
        List<Long> userLevelIds = checkAndGetUserLevelIds(costPerPopup);
        costPerPopupMapper.update(costPerPopup);
        List<PopupRelate> popupRelates = getPopupRelates(costPerPopup, spuIds, userLevelIds);
        popupRelateService.updateBatch(costPerPopup.getPopupId(), popupRelates);
    }

    private static List<PopupRelate> getPopupRelates(CostPerPopup costPerPopup, List<Long> spuIds, List<Long> userLevelIds) {
        List<PopupRelate> popupRelates = new ArrayList<>();
        if (CollUtil.isNotEmpty(spuIds)) {
            for (Long spuId : spuIds) {
                PopupRelate popupRelate = new PopupRelate(costPerPopup.getPopupId(), spuId, null);
                popupRelates.add(popupRelate);
            }
        }
        if (CollUtil.isNotEmpty(userLevelIds)) {
            for (Long userLevelId : userLevelIds) {
                PopupRelate popupRelate = new PopupRelate(costPerPopup.getPopupId(), null, userLevelId);
                popupRelates.add(popupRelate);
            }
        }
        return popupRelates;
    }

    private List<Long> checkAndGetUserLevelIds(CostPerPopup costPerPopup) {
        List<Long> userLevelIds = new ArrayList<>();
        if (CollUtil.isNotEmpty(costPerPopup.getUserLevelIds())) {
            List<UserLevel> userLevels = userLevelMapper.listUserLevelIds(costPerPopup.getUserLevelIds());
            if (CollUtil.isEmpty(userLevels)) {
                throw new LuckException("会员等级均不存在，请重新选择");
            }
            userLevelIds = userLevels.stream().map(UserLevel::getUserLevelId).collect(Collectors.toList());
        }
        return userLevelIds;
    }

    private List<Long> checkAndGetSpuIds(CostPerPopup costPerPopup) {
        List<Long> spuIds = new ArrayList<>();
        if (CollUtil.isNotEmpty(costPerPopup.getSpuIds())) {
            List<SpuSearchVO> data = searchSpuFeignClient.listNotDeleteSpu(costPerPopup.getSpuIds()).getData();
            spuIds = data.stream().filter(spu -> Objects.equals(spu.getSpuStatus(), SpuStatus.PUT_SHELF.value()))
                    .map(SpuSearchVO::getSpuId).collect(Collectors.toList());
            if (CollUtil.isEmpty(spuIds)) {
                throw new LuckException("商品状态均异常，请重新选择");
            }
        }
        return spuIds;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = UserCacheNames.POPUP_KEY, key = "#popupId")
    public void deleteById(Long popupId) {
        costPerPopupMapper.deleteById(popupId);
        // 弹窗广告关联商品/会员等级删除
        popupRelateService.deleteById(popupId);
        // 弹窗广告记录删除
        popupUserLogService.removeByPopupId(popupId);
    }

    @Override
    @CacheEvict(value = UserCacheNames.POPUP_KEY, key = "#popupId")
    @Transactional(rollbackFor = Exception.class)
    public void invalid(Long popupId) {
        costPerPopupMapper.invalid(popupId);
        // 弹窗广告记录删除
        popupUserLogService.removeByPopupId(popupId);
    }

    @Override
    public List<CostPerPopupVO> listByParam(CostPerPopup costPerPopup) {
        return costPerPopupMapper.listByParam(costPerPopup);
    }

    @Override
    public List<Long> putOnAdvertise() {
        List<Long> putOnIds = costPerPopupMapper.listPopUpByStatus(PopupStatusEnum.PUT_ON.value());
        if (CollUtil.isEmpty(putOnIds)) {
            return new ArrayList<>();
        }
        costPerPopupMapper.updateStatus(PopupStatusEnum.PUT_ON.value());
        return putOnIds;
    }

    @Override
    public List<Long> endAdvertise() {
        List<Long> endIds = costPerPopupMapper.listPopUpByStatus(PopupStatusEnum.FINISH.value());
        if (CollUtil.isEmpty(endIds)) {
            return new ArrayList<>();
        }
        costPerPopupMapper.updateStatus(PopupStatusEnum.FINISH.value());
        return endIds;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePopupByRelate(Long relateThingId, Long shopId) {
        List<CostPerPopup> costPerPopupList = costPerPopupMapper.listNotEndByShopId(shopId);
        if (CollUtil.isEmpty(costPerPopupList)) {
            return;
        }
        // 批量删除关联
        List<Long> deleteIds = new ArrayList<>();
        // 批量更新没有关联商品/等级的弹窗广告为关闭状态
        List<Long> updateIds = new ArrayList<>();
        for (CostPerPopup costPerPopup : costPerPopupList) {
            List<PopupRelate> relateList = popupRelateService.getByPopupId(costPerPopup.getPopupId());
            Map<Long, Long> relateMap;
            if (Objects.equals(shopId, Constant.PLATFORM_SHOP_ID)) {
                relateMap = relateList.stream().collect(Collectors.toMap(PopupRelate::getUserLevelId, PopupRelate::getRelateId));
            } else {
                relateMap = relateList.stream().collect(Collectors.toMap(PopupRelate::getSpuId, PopupRelate::getRelateId));;
            }
            Long relateId = relateMap.get(relateThingId);
            if (Objects.isNull(relateId)) {
                // 没有关联商品
                continue;
            }
            if (relateMap.keySet().size() == 1) {
                // 只剩下这件商品/等级了，将弹窗广告关闭
                updateIds.add(costPerPopup.getPopupId());
            }
            deleteIds.add(relateId);
        }
        if (CollUtil.isNotEmpty(deleteIds)) {
            popupRelateService.deleteByRelateIds(deleteIds);
            removeCacheBatch(deleteIds);
        }
        if (CollUtil.isNotEmpty(updateIds)) {
            costPerPopupMapper.updateStatusBatch(updateIds);
        }
    }

    @Override
    public void removeCacheBatch(List<Long> popupIds) {
        List<String> keys = new ArrayList<>(popupIds.size());
        for (Long popupId : popupIds) {
            keys.add(UserCacheNames.POPUP_KEY + CacheNames.UNION + popupId);
        }
        RedisUtil.deleteBatch(keys);
    }

    @Override
    public List<String> getDuplicateList(CostPerPopup costPerPopup, CostPerPopupVO dbCostPerPopup) {
        List<String> weeks = Arrays.stream(costPerPopup.getWeekFrequency().split(StrUtil.COMMA)).toList();
        List<String> dbWeeks = Arrays.stream(dbCostPerPopup.getWeekFrequency().split(StrUtil.COMMA)).toList();
        return dbWeeks.stream().filter(weeks::contains).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteLink(Long linkId, Long shopId, String type, List<Long> categoryIds) {
        List<Long> shopIds = new ArrayList<>();
        shopIds.add(shopId);
        shopIds.add(Constant.PLATFORM_SHOP_ID);
        List<CostPerPopup> costPerPopupList = costPerPopupMapper.listNotEndLinkByShopId(shopIds);
        if (CollUtil.isEmpty(costPerPopupList)) {
            return;
        }
        List<Long> updateIds = new ArrayList<>();
        for (CostPerPopup costPerPopup : costPerPopupList) {
            JumpUrlBO jumpUrlBO = JSON.parseObject(costPerPopup.getJumpUrl(), JumpUrlBO.class);
            if (!Objects.equals(jumpUrlBO.getType(), type)) {
                continue;
            }
            if (Objects.nonNull(linkId) && !Objects.equals(jumpUrlBO.getLink(), String.valueOf(linkId))) {
                continue;
            }
            if (Objects.nonNull(categoryIds) && Objects.equals(type, JumpType.CATEGORY.value())) {
                // [{"label":"2024","value":3887},{"label":"1","value":3888},{"label":"8","value":3899}]
                String categoryStr = jumpUrlBO.getLink();
                List<CategoryLinkBO> linkList = JSON.parseArray(categoryStr, CategoryLinkBO.class);
                CategoryLinkBO categoryLinkBO = linkList.get(linkList.size() - 1);
                if (!categoryIds.contains(categoryLinkBO.getValue())) {
                    continue;
                }
            }
            updateIds.add(costPerPopup.getPopupId());
        }
        if (CollUtil.isNotEmpty(updateIds)) {
            costPerPopupMapper.updateStatusBatch(updateIds);
            removeCacheBatch(updateIds);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void offlineShop(List<Long> shopIds) {
        List<CostPerPopup> costPerPopupList = costPerPopupMapper.listNotEndLinkByShopId(shopIds);
        if (CollUtil.isEmpty(costPerPopupList)) {
            return;
        }
        List<Long> updateIds = costPerPopupList.stream().map(CostPerPopup::getPopupId).collect(Collectors.toList());
        costPerPopupMapper.updateStatusBatch(updateIds);
        removeCacheBatch(updateIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteLinkBatch(List<CouponDataVO> couponList) {
        Map<Long, List<CouponDataVO>> couponMap = couponList.stream().collect(Collectors.groupingBy(CouponDataVO::getShopId));
        List<Long> updateIds = new ArrayList<>();
        for (Long shopId : couponMap.keySet()) {
            List<CouponDataVO> couponDataList = couponMap.get(shopId);
            List<Long> couponIds = couponDataList.stream().map(CouponDataVO::getCouponId).toList();
            List<Long> shopIds = new ArrayList<>();
            shopIds.add(shopId);
            shopIds.add(Constant.PLATFORM_SHOP_ID);
            List<CostPerPopup> costPerPopupList = costPerPopupMapper.listNotEndLinkByShopId(shopIds);
            if (CollUtil.isEmpty(costPerPopupList)) {
                continue;
            }
            for (CostPerPopup costPerPopup : costPerPopupList) {
                JumpUrlBO jumpUrlBO = JSON.parseObject(costPerPopup.getJumpUrl(), JumpUrlBO.class);
                if (!Objects.equals(jumpUrlBO.getType(), JumpType.COUPON.value())) {
                    continue;
                }
                if (!couponIds.contains(Long.valueOf(jumpUrlBO.getLink()))) {
                    continue;
                }
                updateIds.add(costPerPopup.getPopupId());
            }
        }
        if (CollUtil.isNotEmpty(updateIds)) {
            costPerPopupMapper.updateStatusBatch(updateIds);
            removeCacheBatch(updateIds);
        }
    }
}
