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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.tmerclub.cloud.api.multishop.feign.ShopDetailFeignClient;
import com.tmerclub.cloud.api.multishop.vo.ShopDetailVO;
import com.tmerclub.cloud.api.platform.constant.OfflineHandleEventStatus;
import com.tmerclub.cloud.api.platform.constant.OfflineHandleEventType;
import com.tmerclub.cloud.api.platform.dto.OfflineHandleEventDTO;
import com.tmerclub.cloud.api.platform.feign.OfflineHandleEventFeignClient;
import com.tmerclub.cloud.api.platform.vo.OfflineHandleEventVO;
import com.tmerclub.cloud.api.product.bo.SpuSimpleBO;
import com.tmerclub.cloud.api.product.feign.SkuFeignClient;
import com.tmerclub.cloud.api.product.feign.SpuFeignClient;
import com.tmerclub.cloud.common.cache.constant.CacheNames;
import com.tmerclub.cloud.common.cache.constant.GroupCacheNames;
import com.tmerclub.cloud.common.cache.util.RedisUtil;
import com.tmerclub.cloud.common.constant.SendTypeEnum;
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.i18n.I18nMessage;
import com.tmerclub.cloud.common.order.vo.SendNotifyBO;
import com.tmerclub.cloud.common.product.constant.SpuType;
import com.tmerclub.cloud.common.product.dto.SpuDTO;
import com.tmerclub.cloud.common.product.vo.GroupActivitySpuVO;
import com.tmerclub.cloud.common.product.vo.SkuVO;
import com.tmerclub.cloud.common.product.vo.SpuVO;
import com.tmerclub.cloud.common.product.vo.app.SkuAppVO;
import com.tmerclub.cloud.common.response.ResponseEnum;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.rocketmq.config.RocketMqConstant;
import com.tmerclub.cloud.common.security.AuthUserContext;
import com.tmerclub.cloud.common.util.BeanUtil;
import com.tmerclub.cloud.group.constant.GroupActivityStatusEnum;
import com.tmerclub.cloud.group.dto.GroupActivityDTO;
import com.tmerclub.cloud.group.dto.GroupSkuDTO;
import com.tmerclub.cloud.group.mapper.GroupActivityMapper;
import com.tmerclub.cloud.group.model.GroupActivity;
import com.tmerclub.cloud.group.model.GroupSku;
import com.tmerclub.cloud.group.service.GroupActivityService;
import com.tmerclub.cloud.group.service.GroupSkuService;
import com.tmerclub.cloud.group.vo.GroupActivityVO;
import com.tmerclub.cloud.group.vo.GroupSkuVO;
import com.tmerclub.cloud.group.vo.app.AppGroupActivityVO;
import com.tmerclub.cloud.group.vo.app.AppGroupSkuVO;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 拼团活动表
 *
 * @author YXF
 * @date 2021-03-20 10:39:31
 */
@Service
public class GroupActivityServiceImpl implements GroupActivityService {


    private static final Logger logger = LoggerFactory.getLogger(GroupActivityServiceImpl.class);

    @Autowired
    private GroupActivityMapper groupActivityMapper;
    @Autowired
    private GroupSkuService groupSkuService;
    @DubboReference
    private SpuFeignClient spuFeignClient;
    @DubboReference
    private ShopDetailFeignClient shopDetailFeignClient;
    @DubboReference
    private SkuFeignClient skuFeignClient;
    @DubboReference
    private OfflineHandleEventFeignClient offlineHandleEventFeignClient;
    @Autowired
    private RocketMQTemplate sendActivityOfflineNotifyToShopTemplate;

    @Autowired
    protected RocketMQTemplate sendActivityAuditNotifyToShopTemplate;



    @Override
    public PageVO<GroupActivityVO> page(PageDTO pageDTO, GroupActivityDTO groupActivityDTO) {
        if (StrUtil.isNotBlank(groupActivityDTO.getSpuName())) {
            SpuSimpleBO spuSimpleBO = new SpuSimpleBO();
            spuSimpleBO.setSpuName(groupActivityDTO.getSpuName());
            spuSimpleBO.setSeq(1);
            spuSimpleBO.setLang(I18nMessage.getLang());
            ServerResponseEntity<List<SpuSimpleBO>> spuRes = spuFeignClient.listSimple(spuSimpleBO);
            if (!spuRes.isSuccess()) {
                throw new LuckException(spuRes.getMsg());
            }
            if (CollUtil.isNotEmpty(spuRes.getData())) {
                Set<Long> spuIds = spuRes.getData().stream().map(SpuSimpleBO::getSpuId).collect(Collectors.toSet());
                groupActivityDTO.setSpuIds(new ArrayList<>(spuIds));
            }
        }
        PageVO<GroupActivityVO> page = PageUtil.doPage(pageDTO, () -> groupActivityMapper.list(groupActivityDTO));
        Set<Long> spuIdSet = page.getList().stream().map(GroupActivityVO::getSpuId).collect(Collectors.toSet());
        if (CollUtil.isEmpty(spuIdSet)) {
            return page;
        }
        ServerResponseEntity<List<SpuVO>> spuResponseEntity = spuFeignClient.listSpuBySpuIds(new ArrayList<>(spuIdSet));
        if (CollUtil.isEmpty(spuResponseEntity.getData())) {
            return page;
        }
        Map<Long, String> spuNameMap = spuResponseEntity.getData().stream().collect(Collectors.toMap(SpuVO::getSpuId, SpuVO::getName));
        Map<Long, String> imgUrlMap = spuResponseEntity.getData().stream().collect(Collectors.toMap(SpuVO::getSpuId, SpuVO::getMainImgUrl));
        for (GroupActivityVO groupActivity : page.getList()) {
            groupActivity.setSpuName(spuNameMap.get(groupActivity.getSpuId()));
            groupActivity.setMainImgUrl(imgUrlMap.get(groupActivity.getSpuId()));
        }
        return page;
    }

    @Override
    public PageVO<GroupActivityVO> platformPage(PageDTO pageDTO, GroupActivityDTO groupActivityDTO) {
        if (StringUtils.isNotBlank(groupActivityDTO.getShopName())) {
            List<Long> data = shopDetailFeignClient.getShopIdsByLikeShopName(groupActivityDTO.getShopName()).getData();
            groupActivityDTO.setShopIds(data);
        }
        PageVO<GroupActivityVO> page = PageUtil.doPage(pageDTO, () -> groupActivityMapper.list(groupActivityDTO));
        Set<Long> shopIdSet = page.getList().stream().map(GroupActivityVO::getShopId).collect(Collectors.toSet());
        Set<Long> spuIdSet = page.getList().stream().map(GroupActivityVO::getSpuId).collect(Collectors.toSet());
        ServerResponseEntity<List<SpuVO>> spuResponseEntity = spuFeignClient.listSpuBySpuIds(new ArrayList<>(spuIdSet));
        ServerResponseEntity<List<ShopDetailVO>> responseEntity = shopDetailFeignClient.listByShopIds(new ArrayList<>(shopIdSet));
        if (CollUtil.isEmpty(responseEntity.getData())) {
            return page;
        }
        Map<Long, String> shopMap = responseEntity.getData().stream().collect(Collectors.toMap(ShopDetailVO::getShopId, ShopDetailVO::getShopName));
        Map<Long, String> spuNameMap = spuResponseEntity.getData().stream().collect(Collectors.toMap(SpuVO::getSpuId, SpuVO::getName));
        Map<Long, String> imgUrlMap = spuResponseEntity.getData().stream().collect(Collectors.toMap(SpuVO::getSpuId, SpuVO::getMainImgUrl));
        for (GroupActivityVO groupActivity : page.getList()) {
            groupActivity.setShopName(shopMap.get(groupActivity.getShopId()));
            groupActivity.setSpuName(spuNameMap.get(groupActivity.getSpuId()));
            groupActivity.setMainImgUrl(imgUrlMap.get(groupActivity.getSpuId()));
        }
        return page;
    }

    @Override
    public GroupActivityVO getByGroupActivityId(Long groupActivityId) {
        return groupActivityMapper.getByGroupActivityId(groupActivityId);
    }

    @Override
    public GroupActivityVO getGroupActivityInfo(Long groupActivityId) {
        GroupActivityVO groupActivityVO = groupActivityMapper.getByGroupActivityId(groupActivityId);
        ServerResponseEntity<SpuVO> spuResponse = spuFeignClient.getSpuAndSkuBySpuId(groupActivityVO.getSpuId());
        groupActivityVO.setGroupSkuList(groupSkuService.listByGroupActivityId(groupActivityId));
        SpuVO spuVO = spuResponse.getData();
        // 商品不存在
        if (Objects.isNull(spuVO)) {
            groupActivityVO.setSpuId(null);
            return groupActivityVO;
        }
        Map<Long, GroupSkuVO> skuMap = groupActivityVO.getGroupSkuList().stream().collect(Collectors.toMap(GroupSkuVO::getSkuId, g -> g));
        for (SkuVO sku : spuVO.getSkus()) {
            GroupSkuVO groupSkuVO = skuMap.get(sku.getSkuId());
            if (groupSkuVO == null) {
                continue;
            }
            groupSkuVO.setSkuName(sku.getSkuName());
            groupSkuVO.setPrice(sku.getPriceFee());
        }
        groupActivityVO.setMainImgUrl(spuVO.getMainImgUrl());
        groupActivityVO.setSpuName(spuVO.getName());
        return groupActivityVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void save(GroupActivityDTO groupActivityDTO) {
        // 判断是否是普通商品
        ServerResponseEntity<SpuVO> spuResponseEntity = spuFeignClient.getDetailById(groupActivityDTO.getSpuId());
        if (!spuResponseEntity.isSuccess()) {
            throw new LuckException(spuResponseEntity.getMsg());
        }
        SpuVO spuVO = spuResponseEntity.getData();
        if (!Objects.equals(spuVO.getSpuType(), SpuType.NORMAL.value())) {
            throw new LuckException(ResponseEnum.DATA_ERROR);
        }
        // 保存团购信息
        GroupActivity groupActivity = BeanUtil.map(groupActivityDTO, GroupActivity.class);
        // 默认为未启用状态
        groupActivity.setStatus(GroupActivityStatusEnum.DISABLE.value());
        groupActivity.setShopId(AuthUserContext.get().getTenantId());
        groupActivity.setPrice(getGroupSpuPrice(groupActivityDTO.getGroupSkuList()));
        groupActivityMapper.save(groupActivity);
        groupSkuService.batchSave(BeanUtil.mapAsList(groupActivityDTO.getGroupSkuList(), GroupSku.class), groupActivity.getGroupActivityId());

        changeSpuType(groupActivity.getGroupActivityId(), groupActivity.getSpuId(), SpuType.GROUP, StatusEnum.ENABLE);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void update(GroupActivityDTO groupActivityDTO) {
        GroupActivityVO dbGroupActivity = groupActivityMapper.getByGroupActivityId(groupActivityDTO.getGroupActivityId());
        if (!Objects.equals(dbGroupActivity.getShopId(), AuthUserContext.get().getTenantId())) {
            throw new LuckException(ResponseEnum.UNAUTHORIZED);
        }
        groupActivityDTO.setSpuId(dbGroupActivity.getSpuId());
        GroupActivity groupActivity = BeanUtil.map(groupActivityDTO, GroupActivity.class);
        groupActivity.setPrice(getGroupSpuPrice(groupActivityDTO.getGroupSkuList()));
        // 不更新的字段-预防非法修改
        groupActivity.setStatus(null);
        groupActivity.setSpuId(null);
        groupActivityMapper.update(groupActivity);
        // 更新团购商品信息
        changeSpuType(dbGroupActivity.getGroupActivityId(), dbGroupActivity.getSpuId(), null, null);
        // 状态为未启用可以更新sku
        if (Objects.equals(GroupActivityStatusEnum.DISABLE.value(), dbGroupActivity.getStatus())) {
            List<GroupSku> groupSkuList = BeanUtil.mapAsList(groupActivityDTO.getGroupSkuList(), GroupSku.class);
            groupSkuService.batchUpdate(groupSkuList, groupActivity.getGroupActivityId());
        }
    }


    @Override
    public void updateStatus(Long groupActivityId, GroupActivityStatusEnum status) {
        GroupActivity groupActivity = new GroupActivity();
        groupActivity.setStatus(status.value());
        groupActivity.setGroupActivityId(groupActivityId);
        groupActivityMapper.update(groupActivity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void invalidGroupActivity(Long groupActivityId, Long spuId) {
        updateStatus(groupActivityId, GroupActivityStatusEnum.EXPIRED);
        changeSpuType(0L, spuId, SpuType.NORMAL, StatusEnum.ENABLE);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void deleteGroupActivity(Long groupActivityId, Long spuId) {
        changeSpuType(groupActivityId, spuId, SpuType.NORMAL, StatusEnum.ENABLE);
        updateStatus(groupActivityId, GroupActivityStatusEnum.DELETE);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void activeGroupActivity(Long groupActivityId, Long spuId) {
        //获取活动sku最低价
        GroupActivityVO groupActivity = groupActivityMapper.getByGroupActivityId(groupActivityId);
        List<Long> skuIds = groupSkuService.getSkuIdByActivityIdAndActPrice(groupActivityId, groupActivity.getPrice());
        //根据skuId获取对应原价最低的值
        ServerResponseEntity<Long> minPriceFees = skuFeignClient.getMinPriceFeeByIds(skuIds);
        Long minPriceFee = minPriceFees.getData();
        //将最低活动价对应的sku原价存入redis
        RedisUtil.set(CacheNames.GROUP_SPU_PRICE_FREE + groupActivityId, minPriceFee, 3600);
        // 失效掉状态为（禁用/等待审核/违规下架）的同商品
        List<Long> groupActivityIds = groupActivityMapper.listNoFailureBySpuId(groupActivity.getSpuId(), groupActivityId);
        for (Long activityId : groupActivityIds) {
            updateStatus(activityId, GroupActivityStatusEnum.EXPIRED);
        }

        updateStatus(groupActivityId, GroupActivityStatusEnum.ENABLE);
        changeSpuType(groupActivityId, spuId, null, StatusEnum.ENABLE);
    }

    @Override
    public void offlineGroupActivity(Long groupActivityId) {
        GroupActivityVO groupActivity = getByGroupActivityId(groupActivityId);
        updateStatus(groupActivityId, GroupActivityStatusEnum.OFFLINE);
        changeSpuType(groupActivityId, groupActivity.getSpuId(), null, StatusEnum.ENABLE);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void offline(OfflineHandleEventDTO offlineHandleEventDto) {
        OfflineHandleEventDTO offlineHandleEvent = new OfflineHandleEventDTO();
        offlineHandleEvent.setHandleId(offlineHandleEventDto.getHandleId());
        offlineHandleEvent.setHandleType(OfflineHandleEventType.GROUP_BUY.getValue());
        offlineHandleEvent.setOfflineReason(offlineHandleEventDto.getOfflineReason());
        ServerResponseEntity<Void> responseEntity = offlineHandleEventFeignClient.save(offlineHandleEvent);
        if (!Objects.equals(responseEntity.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(responseEntity.getMsg());
        }
        // 更新活动状态为下线状态
        offlineGroupActivity(offlineHandleEventDto.getHandleId());

        //发送活动下线消息给店铺
        GroupActivityVO groupActivity = getByGroupActivityId(offlineHandleEventDto.getHandleId());
        SendNotifyBO sendNotifyBO = new SendNotifyBO();
        sendNotifyBO.setSendType(SendTypeEnum.ACTIVITY_OFFLINE.getValue());
        sendNotifyBO.setShopId(groupActivity.getShopId());
        sendNotifyBO.setActivityName(groupActivity.getActivityName());
        sendNotifyBO.setActivityId(groupActivity.getGroupActivityId());
        SendStatus sendStockStatus = sendActivityOfflineNotifyToShopTemplate.syncSend(RocketMqConstant.SEND_ACTIVITY_OFFLINE_NOTIFY_TO_SHOP_TOPIC, new GenericMessage<>(sendNotifyBO)).getSendStatus();
        if (!Objects.equals(sendStockStatus, SendStatus.SEND_OK)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }

    @Override
    public OfflineHandleEventVO getOfflineHandleEvent(Long couponId) {
        ServerResponseEntity<OfflineHandleEventVO> offlineHandleEventResponse =
                offlineHandleEventFeignClient.getProcessingEventByHandleTypeAndHandleId(OfflineHandleEventType.GROUP_BUY.getValue(), couponId, null);
        return offlineHandleEventResponse.getData();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void audit(OfflineHandleEventDTO offlineHandleEventDto) {
        ServerResponseEntity<Void> responseEntity = offlineHandleEventFeignClient.auditOfflineEvent(offlineHandleEventDto);
        if (!Objects.equals(responseEntity.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(responseEntity.getMsg());
        }
        Long groupActivityId = offlineHandleEventDto.getHandleId();
        GroupActivityVO dbGroupActivityVO = getByGroupActivityId(groupActivityId);
        // 审核通过
        if (Objects.equals(offlineHandleEventDto.getStatus(), OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())) {
            updateStatus(groupActivityId, GroupActivityStatusEnum.DISABLE);
            changeSpuType(groupActivityId, dbGroupActivityVO.getSpuId(), null, StatusEnum.ENABLE);
            // 清除缓存
            GroupActivityServiceImpl groupActivityService = (GroupActivityServiceImpl) AopContext.currentProxy();
            groupActivityService.removeCache(dbGroupActivityVO.getSpuId());
        }
        // 审核不通过
        else if (Objects.equals(offlineHandleEventDto.getStatus(), OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue())) {
            updateStatus(offlineHandleEventDto.getHandleId(), GroupActivityStatusEnum.OFFLINE);
        }
        //发送活动审核结果消息给店铺
        GroupActivityVO groupActivity = getByGroupActivityId(offlineHandleEventDto.getHandleId());
        SendNotifyBO sendNotifyBO = new SendNotifyBO();
        sendNotifyBO.setSendType(SendTypeEnum.ACTIVITY_AUDIT.getValue());
        sendNotifyBO.setShopId(groupActivity.getShopId());
        sendNotifyBO.setActivityName(groupActivity.getActivityName());
        sendNotifyBO.setActivityId(groupActivity.getGroupActivityId());
        SendStatus sendStockStatus = sendActivityAuditNotifyToShopTemplate.syncSend(RocketMqConstant.SEND_ACTIVITY_AUDIT_NOTIFY_TO_SHOP_TOPIC, new GenericMessage<>(sendNotifyBO)).getSendStatus();
        if (!Objects.equals(sendStockStatus, SendStatus.SEND_OK)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void auditApply(OfflineHandleEventDTO offlineHandleEventDto) {
        // 更新事件状态
        ServerResponseEntity<Void> responseEntity = offlineHandleEventFeignClient.updateToApply(offlineHandleEventDto);
        if (!Objects.equals(responseEntity.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(responseEntity.getMsg());
        }
        // 更新为待审核状态
        updateStatus(offlineHandleEventDto.getHandleId(), GroupActivityStatusEnum.WAIT_AUDIT);
    }

    @Override
    public AppGroupActivityVO getAppGroupActivityInfo(Long spuId) {

        GroupActivityServiceImpl groupActivityService = (GroupActivityServiceImpl) AopContext.currentProxy();

        // 从缓存获取团购的数据
        AppGroupActivityVO appGroupActivityVO = groupActivityService.getBySpuId(spuId);
        if (Objects.isNull(appGroupActivityVO)) {
            return null;
        }
        setAppGroupActivityInfo(appGroupActivityVO);
        return appGroupActivityVO;
    }

    private void setAppGroupActivityInfo(AppGroupActivityVO appGroupActivityVO) {
        ServerResponseEntity<List<SkuAppVO>> skuResponse = skuFeignClient.listBySpuId(appGroupActivityVO.getSpuId());
        if (!Objects.equals(skuResponse.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(skuResponse.getMsg());
        }
        Map<Long, SkuAppVO> skuMap = skuResponse.getData().stream().collect(Collectors.toMap(SkuAppVO::getSkuId, s -> s));
        List<AppGroupSkuVO> groupSkuList = appGroupActivityVO.getGroupSkuList();

        Iterator<AppGroupSkuVO> groupSkuIterator = groupSkuList.iterator();
        while (groupSkuIterator.hasNext()) {
            AppGroupSkuVO groupSkuVO = groupSkuIterator.next();
            SkuAppVO skuAppVO = skuMap.get(groupSkuVO.getSkuId());
            if (skuAppVO == null) {
                groupSkuIterator.remove();
                continue;
            }
            groupSkuVO.setSkuName(skuAppVO.getSkuName());
            groupSkuVO.setProperties(skuAppVO.getProperties());
            groupSkuVO.setImgUrl(skuAppVO.getImgUrl());
            // 如果没有市场价，就用售价当作市场价
            groupSkuVO.setMarketPriceFee(skuAppVO.getPriceFee());
            groupSkuVO.setStock(skuAppVO.getStock());
            groupSkuVO.setSpuId(skuAppVO.getSpuId());
            groupSkuVO.setSkuComboList(skuAppVO.getSkuComboList());
            groupSkuVO.setStatus(1);
        }
    }


    @Override
    @Cacheable(cacheNames = GroupCacheNames.GROUP_BY_SPU_KEY, key = "#spuId")
    public AppGroupActivityVO getBySpuId(Long spuId) {
        return groupActivityMapper.getBySpuId(spuId);
    }

    @Override
    public List<GroupActivitySpuVO> groupSpuListBySpuIds(List<Long> spuIds) {
        return groupActivityMapper.groupSpuListBySpuIds(spuIds);
    }

    @Override
    public List<GroupActivity> listUnEndButNeedEndActivity() {
        return groupActivityMapper.listUnEndButNeedEndActivity();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void changeProdTypeByGroupActivityIdList(List<GroupActivity> groupActivityList) {
        // 失效团购活动
        groupActivityMapper.expiredGroupActivityByGroupActivityIdList(groupActivityList);
        List<Long> spuIds = groupActivityList.stream().map(GroupActivity::getSpuId).collect(Collectors.toList());
        spuFeignClient.changeToNormalSpu(spuIds);
    }

    @Override
    @CacheEvict(cacheNames = GroupCacheNames.GROUP_BY_SPU_KEY, key = "#spuId")
    public void removeCache(Long spuId) {

    }

    @Override
    public AppGroupActivityVO getAppGroupActivityByGroupActivityId(Long groupActivityId) {
        AppGroupActivityVO appGroupActivityVO = groupActivityMapper.getAppGroupActivityByGroupActivityId(groupActivityId);

        if (Objects.isNull(appGroupActivityVO)) {
            return null;
        }
        setAppGroupActivityInfo(appGroupActivityVO);
        return appGroupActivityVO;
    }

    @Override
    public void updateGroupActivityPrice(List<Long> skuIds, Long spuId) {
        GroupActivityVO activityInfoBySpuId = groupActivityMapper.getGroupActivityInfoBySpuId(spuId);
        if (Objects.isNull(activityInfoBySpuId)) {
            return;
        }
        //重新计算price
        List<GroupSkuVO> skuList = activityInfoBySpuId.getGroupSkuList();
        List<GroupSkuDTO> groupSkuList = BeanUtil.mapAsList(skuList, GroupSkuDTO.class);
        groupSkuList.removeIf(sku -> !skuIds.contains(sku.getSkuId()));
        Long groupSpuPrice = getGroupSpuPrice(groupSkuList);
        GroupActivity groupActivity = BeanUtil.map(activityInfoBySpuId, GroupActivity.class);
        groupActivity.setPrice(groupSpuPrice);
        groupActivityMapper.update(groupActivity);
    }

    @Override
    public List<Long> getGroupPriceFree(Long groupActivityId) {
        //获取活动sku最低价
        GroupActivityVO groupActivity = groupActivityMapper.getByGroupActivityId(groupActivityId);
        return groupSkuService.getSkuIdByActivityIdAndActPrice(groupActivityId, groupActivity.getPrice());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void updateGroupActivityStatus(Long spuId) {
        AppGroupActivityVO groupActivityVO = groupActivityMapper.getBySpuId(spuId);
        if (Objects.isNull(groupActivityVO)) {
            logger.info("团购活动为空，spuId={}", spuId);
            return;
        }
        updateStatus(groupActivityVO.getGroupActivityId(), GroupActivityStatusEnum.EXPIRED);
        spuFeignClient.changeToNormalSpu(Arrays.asList(spuId));
    }

    @Override
    public void offlineGroupBySpuIds(List<Long> spuIds) {
        groupActivityMapper.expiredGroupActivityBySpuIds(spuIds);
    }

    /**
     * 更改商品类型
     *
     * @param groupActivityId
     * @param spuId
     * @param spuType
     * @param status
     */
    private void changeSpuType(Long groupActivityId, Long spuId, SpuType spuType, StatusEnum status) {
        SpuDTO spuDTO = new SpuDTO();
        spuDTO.setSpuId(spuId);
        spuDTO.setActivityId(groupActivityId);
        if (Objects.nonNull(spuType)) {
            spuDTO.setSpuType(spuType.value());
        } else {
            spuDTO.setSpuType(SpuType.GROUP.value());
        }
        if (Objects.nonNull(status)) {
            spuDTO.setStatus(status.value());
        }
        ServerResponseEntity<Void> spuResponse = spuFeignClient.changeSpuType(spuDTO);
        if (!Objects.equals(spuResponse.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(spuResponse.getMsg());
        }
    }

    /**
     * 获取sku中的最低价格
     *
     * @param groupSkuList
     * @return
     */
    private Long getGroupSpuPrice(List<GroupSkuDTO> groupSkuList) {
        Long minPrice = null;
        for (GroupSkuDTO groupSku : groupSkuList) {
            if (Objects.isNull(minPrice) || groupSku.getActPrice() < minPrice) {
                minPrice = groupSku.getActPrice();
            }
        }
        return minPrice;
    }
}
