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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.github.pagehelper.Page;
import com.tmerclub.cloud.api.auth.constant.SysTypeEnum;
import com.tmerclub.cloud.api.combo.feign.ComboFeignClient;
import com.tmerclub.cloud.api.coupon.feign.CouponFeignClient;
import com.tmerclub.cloud.api.delivery.feign.DeliveryFeignClient;
import com.tmerclub.cloud.api.delivery.feign.SameCityFeignClient;
import com.tmerclub.cloud.api.delivery.feign.StationFeignClient;
import com.tmerclub.cloud.api.delivery.vo.SameCityVO;
import com.tmerclub.cloud.api.delivery.vo.ShopTransportVO;
import com.tmerclub.cloud.api.delivery.vo.StationVO;
import com.tmerclub.cloud.common.order.vo.WarehouseVO;
import com.tmerclub.cloud.api.discount.feign.DiscountFeignClient;
import com.tmerclub.cloud.api.distribution.feign.DistributionFeignClient;
import com.tmerclub.cloud.api.feign.SearchSpuFeignClient;
import com.tmerclub.cloud.api.flow.feign.FlowFeignClient;
import com.tmerclub.cloud.api.group.feign.GroupFeignClient;
import com.tmerclub.cloud.api.group.vo.GroupActivityVO;
import com.tmerclub.cloud.api.multishop.bo.EsShopDetailBO;
import com.tmerclub.cloud.api.multishop.constant.ShopStatus;
import com.tmerclub.cloud.api.multishop.feign.IndexImgFeignClient;
import com.tmerclub.cloud.api.multishop.feign.ShopDetailFeignClient;
import com.tmerclub.cloud.api.multishop.feign.ShopSubstituteSalesFeignClient;
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.ConfigFeignClient;
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.dto.SupplierSpuUpdateDTO;
import com.tmerclub.cloud.api.product.feign.CategoryShopFeignClient;
import com.tmerclub.cloud.api.product.feign.GiveawayFeignClient;
import com.tmerclub.cloud.api.product.util.ProductLangUtil;
import com.tmerclub.cloud.api.product.vo.SkuStockVO;
import com.tmerclub.cloud.api.seckill.feign.SeckillFeignClient;
import com.tmerclub.cloud.api.seckill.vo.SeckillApiVO;
import com.tmerclub.cloud.api.supplier.bo.SupplierDetailBO;
import com.tmerclub.cloud.api.supplier.constant.SupplierStatus;
import com.tmerclub.cloud.api.supplier.feign.SupplierDetailFeignClient;
import com.tmerclub.cloud.api.supplier.vo.SupplierApiDetailVO;
import com.tmerclub.cloud.api.vo.EsPageVO;
import com.tmerclub.cloud.common.cache.constant.CacheNames;
import com.tmerclub.cloud.common.cache.constant.ProductCacheNames;
import com.tmerclub.cloud.common.cache.util.RedisUtil;
import com.tmerclub.cloud.common.constant.Constant;
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.PageAdapter;
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.i18n.LanguageEnum;
import com.tmerclub.cloud.common.leaf.manager.SegmentManager;
import com.tmerclub.cloud.common.order.vo.SendNotifyBO;
import com.tmerclub.cloud.common.product.bo.EsCategoryBO;
import com.tmerclub.cloud.common.product.constant.*;
import com.tmerclub.cloud.common.product.dto.*;
import com.tmerclub.cloud.common.product.vo.*;
import com.tmerclub.cloud.common.product.vo.app.SkuAppVO;
import com.tmerclub.cloud.common.product.vo.app.SpuAppVO;
import com.tmerclub.cloud.common.product.vo.search.SpuAdminVO;
import com.tmerclub.cloud.common.product.vo.search.SpuSearchVO;
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.common.util.Json;
import com.tmerclub.cloud.common.util.PriceUtil;
import com.tmerclub.cloud.common.vo.ShopSubstituteSalesVO;
import com.tmerclub.cloud.product.constant.DistributedIdKey;
import com.tmerclub.cloud.product.dto.SpuPageSearchDTO;
import com.tmerclub.cloud.api.product.dto.WarehouseDTO;
import com.tmerclub.cloud.product.manager.StockManager;
import com.tmerclub.cloud.product.mapper.*;
import com.tmerclub.cloud.product.model.*;
import com.tmerclub.cloud.product.service.*;
import com.tmerclub.cloud.product.mapper.*;
import com.tmerclub.cloud.product.model.*;
import com.tmerclub.cloud.product.service.SpuStockService;
import com.tmerclub.cloud.product.vo.SpuCountVO;
import com.tmerclub.cloud.product.vo.SupplierSpuVo;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.collections.CollectionUtils;
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.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Lazy;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

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

/**
 * spu信息
 *
 * @author tmerclub
 * @date 2020-10-28 15:27:24
 */
@Service
public class SpuServiceImpl implements SpuService {
    private static final Logger logger = LoggerFactory.getLogger(SpuServiceImpl.class);
    @Autowired
    private SpuMapper spuMapper;
    @Autowired
    private SegmentManager segmentManager;
    @Autowired
    private SpuOfflineService spuOfflineService;
    @Autowired
    private SpuDetailService spuDetailService;
    @Autowired
    private SpuExtensionService spuExtensionService;
    @Autowired
    private SpuTagReferenceService spuTagReferenceService;
    @Autowired
    private SpuAttrValueService spuAttrValueService;
    @Autowired
    private SkuService skuService;
    @Autowired
    private SkuComboService skuComboService;
    @Autowired
    private SpuLangService spuLangService;
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private CategoryBrandService categoryBrandService;
    @Autowired
    private BrandMapper brandMapper;
    @Autowired
    private BrandShopService brandShopService;
    @Autowired
    private CategoryShopMapper categoryShopMapper;
    @DubboReference
    private FlowFeignClient flowFeignClient;
    @DubboReference
    private DiscountFeignClient discountFeignClient;
    @DubboReference
    private CouponFeignClient couponFeignClient;
    @DubboReference
    private OfflineHandleEventFeignClient offlineHandleEventFeignClient;
    @DubboReference
    private GroupFeignClient groupFeignClient;
    @Autowired
    @Lazy
    private AttrService attrService;
    @DubboReference
    private SeckillFeignClient seckillFeignClient;
    @DubboReference
    private ComboFeignClient comboFeignClient;
    @DubboReference
    private SearchSpuFeignClient searchSpuFeignClient;
    @DubboReference
    private ShopDetailFeignClient shopDetailFeignClient;
    @DubboReference
    private DistributionFeignClient distributionFeignClient;
    @DubboReference
    private DeliveryFeignClient deliveryFeignClient;
    @Autowired
    private SkuMapper skuMapper;
    @DubboReference
    private ShopSubstituteSalesFeignClient shopSubstituteSalesFeignClient;
    @DubboReference
    private SupplierDetailFeignClient supplierDetailFeignClient;
    @Autowired
    private SkuLangService skuLangService;
    @Autowired
    private SpuConsignmentChangeMapper spuConsignmentChangeMapper;
    @Autowired
    private SpuSupplierChangeLogService spuSupplierChangeLogService;
    @Autowired
    private ImportSupplierSpuService importSupplierSpuService;
    @Autowired
    private SupplierSpuUpdateLaterOperateService supplierSpuUpdateLaterOperateService;
    @Autowired
    private GiveawaySpuMapper giveawaySpuMapper;
    @Autowired
    private RocketMQTemplate sendProductNotifyToShopTemplate;
    @DubboReference
    private ConfigFeignClient configFeignClient;
    @Autowired
    private SkuStockService skuStockService;
    @DubboReference
    private SameCityFeignClient sameCityFeignClient;
    @DubboReference
    private IndexImgFeignClient indexImgFeignClient;
    @Autowired
    private GiveawayService giveawayService;
    @DubboReference
    private GiveawayFeignClient giveawayFeignClient;
    @Autowired
    private SpuStockService spuStockService;
    @Autowired
    private StockPointSkuService stockPointSkuService;
    @DubboReference
    private StationFeignClient stationFeignClient;
    @Autowired
    private WarehouseService warehouseService;
    @DubboReference
    private CategoryShopFeignClient categoryShopFeignClient;

    private static final Integer SHOP_OFFLINE_TYPE = 3;

    @Autowired
    private StockManager stockManager;

    @Override
    public PageVO<SpuVO> page(PageDTO pageDTO, SpuPageSearchDTO spuDTO) {
        return PageUtil.doPage(pageDTO, () -> spuMapper.list(spuDTO));
    }

    @Override
    @Cacheable(cacheNames = CacheNames.SPU_KEY, key = "#spuId", sync = true)
    public SpuVO getBySpuId(Long spuId) {
        // 获取数据列表：spu、spu国际化、spu详情、skuIds、赠品活动信息
        SpuVO spu = spuMapper.getSpuInfoBySpuId(spuId);
        if (Objects.isNull(spu)) {
            throw new LuckException(ResponseEnum.SPU_NOT_EXIST);
        }
        // 获取skuId和组合商品的sku组合列表
        // skuId列表，更改sku时spu必定会更新，此处的缓存就会被清除，不需要做额外处理，用于后台管理页面查询商品总库存，减少一次sku列表的查询
        List<SkuVO> skuList = skuMapper.listSimpleSkuAndComboBySpuId(spuId);
        spu.setSkus(skuList);
        // 定金预售
        if (Objects.equals(spu.getPreSaleType(), PreSaleType.DEPOSIT.value())) {
            spu.setDepositValue(PriceUtil.toDecimalPrice(spu.getDepositAmount()));
            spu.setDepositExpansionValue(PriceUtil.toDecimalPrice(spu.getDepositExpansionAmount()));
        }
        // 插入赠品的信息, 组装订单项时减少赠品的查询，仅活动的数据，不需要用到具体的赠品信息
        GiveawayVO giveawayVO = giveawayService.getGiveawayBySpuId(spuId);
        spu.setGiveawayVO(giveawayVO);
        return spu;
    }

    @Override
    public Map<Long, SpuVO> mapSpuByCache(List<Long> spuIds) {
        if (CollUtil.isEmpty(spuIds)) {
            return Collections.emptyMap();
        }
        Map<Long, SpuVO> spuMap = RedisUtil.mapByIds(CacheNames.SPU_KEY, spuIds , SpuVO.class);
        if (MapUtil.isNotEmpty(spuMap) && spuMap.size() != spuIds.size()) {
            spuIds.removeAll(spuMap.keySet());
            if (CollUtil.isEmpty(spuIds)) {
                return spuMap;
            }
        }
        SpuService spuService = (SpuServiceImpl) AopContext.currentProxy();
        for (Long spuId : spuIds) {
            SpuVO spuVO = spuService.getBySpuId(spuId);
            if (Objects.isNull(spuVO)) {
                throw new LuckException("商品不存在或者已删除");
            }
            spuMap.put(spuId, spuVO);
        }
        return spuMap;
    }

    @Override
    @Cacheable(cacheNames = CacheNames.SPU_EXTENSION_KEY, key = "#spuId", sync = true)
    public SpuExtension getSpuExtension(Long spuId) {
        return spuExtensionService.getBySpuId(spuId);
    }

    @Override
    public void batchRemoveSpuActivityCache(List<Long> spuIds) {
        if (CollUtil.isEmpty(spuIds)) {
            return;
        }
        RedisUtil.deleteBatch(CacheNames.SPU_ACTIVITY_KEY, spuIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void changeSpuStatus(Long spuId, Integer status) {
        batchChangeSpuStatus(Collections.singletonList(spuId), status);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchChangeSpuStatus(List<Long> spuIds, Integer status) {
        if (Objects.isNull(AuthUserContext.get().getSysType())) {
            throw new LuckException("下线异常");
        }
        spuMapper.batchChangeSpuStatus(spuIds, status);
        // 更新品牌信息
        List<Long> brandIds = brandMapper.listBrandIdBySpuIds(spuIds);
        brandMapper.batchUpdateSpuCount(brandIds);
        if (Objects.equals(status, StatusEnum.DISABLE.value()) || Objects.equals(status, StatusEnum.OFFLINE.value())) {
            // 更新商品分组信息
            handleStatusChange(spuIds);
            // T删掉满减、优惠券,组合商品的商品关联信息
            if (Objects.nonNull(AuthUserContext.get())) {
                handleSpuStatusChange(spuIds);
            } else {
                handleCommissionSpuStatusChange(spuIds);
            }
            // 下线掉关联商品的活动 (在线下活动之前已经修改了商品的状态，下面的方法就查询不到已有的商品了，所以就需要带着修改后的商品去状态去查询)
            spuOfflineService.offlineSpuStatusAndActivity(1, spuIds, null, null, status, null);
        } else if (Objects.equals(status, StatusEnum.ENABLE.value())) {
            handleDistributionSpuStatusChange(spuIds, status);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchChangeCommissionSpuStatus(List<Long> spuIds, Integer status, Integer sysType) {
        if (CollUtil.isEmpty(spuIds)) {
            return;
        }
        spuMapper.batchChangeSpuStatus(spuIds, status);
        // 更新品牌信息
        List<Long> brandIds = brandMapper.listBrandIdBySpuIds(spuIds);
        brandMapper.batchUpdateSpuCount(brandIds);
        if (Objects.equals(status, StatusEnum.DISABLE.value()) || Objects.equals(status, StatusEnum.OFFLINE.value())) {
            // 更新商品分组信息
            handleStatusChange(spuIds);
            // T删掉满减、优惠券的商品关联信息
            if (!Objects.isNull(AuthUserContext.get())) {
                handleSpuStatusChange(spuIds);
            } else {
                handleCommissionSpuStatusChange(spuIds);
            }
            // 下线掉关联商品的活动 (在线下活动之前已经修改了商品的状态，下面的方法就查询不到已有的商品了，所以就需要带着修改后的商品去状态去查询)
            spuOfflineService.offlineCommissionSpuStatusAndActivity(1, spuIds, null, null, status, sysType);
        } else if (Objects.equals(status, StatusEnum.ENABLE.value())) {
            handleDistributionSpuStatusChange(spuIds, status);
        }
    }

    private void handleDistributionSpuStatusChange(List<Long> spuIds, Integer status) {
        List<Long> shopIds;
        if (Objects.equals(AuthUserContext.get().getTenantId(), Constant.PLATFORM_SHOP_ID)) {
            shopIds = new ArrayList<>(1);
        } else {
            shopIds = spuMapper.spuShopIdsBySpuIds(spuIds);
        }
        ServerResponseEntity<Void> responseEntity = distributionFeignClient.handleSpuState(spuIds, shopIds, status);
        if (!responseEntity.isSuccess()) {
            throw new LuckException(responseEntity.getMsg());
        }
        // 如果是组合商品且为供应商发货的商品,再检查下供应商商品的状态是否为上架状态,如果不是上架状态不能上架
        List<Long> supplierComboSpuIds = new ArrayList<>();
        for (Long spuId : spuIds) {
            SpuServiceImpl spuService = (SpuServiceImpl) AopContext.currentProxy();
            // 商品信息
            SpuVO spu = spuService.getBySpuId(spuId);
            if(Objects.equals(spu.getSpuMold(),SpuMold.COMBO.value()) && Objects.equals(spu.getSupplierDeliveryType(),SupplierDeliveryType.SUPPLIER_DELIVERY.value())){
                supplierComboSpuIds.add(spu.getSupplierSpuId());
            }
        }
        if(CollectionUtil.isNotEmpty(supplierComboSpuIds)){
            List<SpuVO> spuList = listSpuBySpuIds(supplierComboSpuIds);
            long count = spuList.stream().filter(spuVO -> !Objects.equals(spuVO.getStatus(), StatusEnum.ENABLE.value())).count();
            if(count > 0){
                throw new LuckException("当前代销组合商品的供应商商品状态异常,不能进行上架");
            }
        }
    }

    private void handleSpuStatusChange(List<Long> spuIds) {
        List<Long> shopIds;
        if (Objects.equals(AuthUserContext.get().getTenantId(), Constant.PLATFORM_SHOP_ID)) {
            shopIds = new ArrayList<>(1);
        } else {
            shopIds = spuMapper.spuShopIdsBySpuIds(spuIds);
        }
        if (CollUtil.isNotEmpty(spuIds)) {
            ServerResponseEntity<Void> discountResponseEntity = discountFeignClient.handleSpuOffline(spuIds, shopIds);
            if (!discountResponseEntity.isSuccess()) {
                throw new LuckException(discountResponseEntity.getMsg());
            }
            ServerResponseEntity<Void> couponResponseEntity = couponFeignClient.handleSpuOffline(spuIds, shopIds);
            if (!couponResponseEntity.isSuccess()) {
                throw new LuckException(couponResponseEntity.getMsg());
            }
            offlineRelatedComboBySpuIds(spuIds);
        }
    }


    private void handleCommissionSpuStatusChange(List<Long> spuIds) {
        List<Long> shopIds = spuMapper.spuShopIdsBySpuIds(spuIds);
        if (CollUtil.isNotEmpty(spuIds)) {
            ServerResponseEntity<Void> discountResponseEntity = discountFeignClient.handleSpuOffline(spuIds, shopIds);
            if (!discountResponseEntity.isSuccess()) {
                throw new LuckException(discountResponseEntity.getMsg());
            }
            ServerResponseEntity<Void> couponResponseEntity = couponFeignClient.handleSpuOffline(spuIds, shopIds);
            if (!couponResponseEntity.isSuccess()) {
                throw new LuckException(couponResponseEntity.getMsg());
            }
            offlineRelatedComboBySpuIds(spuIds);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(SpuDTO spuDTO) {
        int sysType = AuthUserContext.get().getSysType();
        if (sysType == SysTypeEnum.MULTISHOP.value()) {
            spuDTO.setShopId(AuthUserContext.get().getTenantId());
            spuDTO.setSupplierId(-1L);
        } else if (sysType == SysTypeEnum.SUPPLIER.value()) {
            spuDTO.setSupplierId(AuthUserContext.get().getTenantId());
            spuDTO.setShopId(-1L);
        }
        checkSaveOrUpdateInfo(spuDTO, null, true);
        Spu spu = BeanUtil.map(spuDTO, Spu.class);
        handlePreSaleInfo(spuDTO, spu);
        Long spuId = segmentManager.getSegmentId(DistributedIdKey.tmerclub_SPU);
        spu.setSpuId(spuId);
        //判断发货方式，供应商发货属于代销商品
        handleSupplierDelivery(spuDTO, spu);
        //判断发货方式，商家发货属于普通商品
        if (Objects.nonNull(spu.getSupplierDeliveryType()) && Objects.equals(spu.getSupplierDeliveryType(), SupplierDeliveryType.SHOP_DELIVERY.value())) {
            spu.setSupplierSpuType(SupplierSpuType.NO.value());
        }
        handlePlatformAudit(sysType, spu);
        // 1.保存商品信息
        spu.setBrandId(Objects.equals(spuDTO.getBrandId(), 0L) ? null : spuDTO.getBrandId());
        spu.setScoreFee(Objects.isNull(spuDTO.getScoreFee()) ? Constant.ZERO_LONG : spuDTO.getScoreFee());
        if (!Objects.equals(sysType, SysTypeEnum.SUPPLIER.value())) {
            if (!Objects.isNull(spuDTO.getSupplierDeliveryType())) {
                spu.setDeliveryTemplateId(Objects.nonNull(spuDTO.getSupplierDeliveryType()) && spuDTO.getSupplierDeliveryType() == 2 ? spuDTO.getDeliveryTemplateId() : 0);
            }
        }
        spu.setSupplierId(Objects.isNull(spu.getSupplierId()) ? 0L : spu.getSupplierId());
        //供应商商品没有店铺分类
        spu.setShopCategoryId(Objects.equals(spu.getSupplierId(), -1L) ? spuDTO.getShopCategoryId() : -1L);
        spu.setSpuMold(Objects.nonNull(spuDTO.getSpuMold()) ? spuDTO.getSpuMold() : 0);
        if (Objects.equals(spu.getSpuMold(), 1)) {
            // 虚拟商品的配送方式
            SpuVO.DeliveryModeVO mode = new SpuVO.DeliveryModeVO();
            mode.setHasShopDelivery(true);
            mode.setHasUserPickUp(false);
            mode.setHasCityDelivery(false);
            spu.setDeliveryMode(Json.toJsonString(mode));
        }

        spuMapper.save(spu);
        // 2.保存商品属性信息
        spuAttrValueService.save(spu.getSpuId(), spu.getCategoryId(), spuDTO.getSpuAttrValues(), AuthUserContext.get().getSysType());
        // 3.国际化信息、商品详情
        spuDTO.setSpuId(spu.getSpuId());
        List<SpuLang> spuLangList = loadSpuLangInfo(spuDTO, Boolean.TRUE);
        saveSpuExtension(spuDTO, spu);
        // 5.更新品牌信息，仅在商家端发布商品时才更新
        if (Objects.equals(sysType, SysTypeEnum.MULTISHOP.value()) && Objects.nonNull(spu.getBrandId())) {
            brandMapper.batchUpdateSpuCount(Collections.singleton(spu.getBrandId()));
        }
        // 6.保存sku和库存信息
        loadSkuInfo(spuLangList, spu.getMainImgUrl(), spuDTO.getSkuList());
        skuService.saveSkuAndStock(spuDTO.getSpuMold(), spu.getSpuId(), spu.getStatus(), spuDTO.getSkuList(), sysType, AuthUserContext.get().getUserId(), AuthUserContext.get().getTenantId());

    }

    private void loadSkuInfo(List<SpuLang> spuLangList, String mainImgUrl, List<SkuDTO> skuList) {
        Map<Integer, String> spuNameMap = spuLangList.stream().collect(Collectors.toMap(SpuLang::getLang, SpuLang::getSpuName));
        for (SkuDTO skuDTO : skuList) {
            // 目前默认是中文，后面如果要国际化再改
            skuDTO.setSpuName(spuNameMap.get(LanguageEnum.LANGUAGE_ZH_CN.getLang()));
            skuDTO.setSpuMainImgUrl(mainImgUrl);
        }
    }

    private void handleSupplierDelivery(SpuDTO spuDTO, Spu spu) {
        if (Objects.nonNull(spu.getSupplierDeliveryType()) && Objects.equals(spu.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())) {
            //供应商商品类型为代销商品
            spu.setSupplierSpuType(SupplierSpuType.CONSIGNMENT.value());
            //判断规格全选还是部分选择
            //获取供应商商品sku信息
            SpuVO spuVO = BeanUtil.map(spu, SpuVO.class);
            List<SkuVO> skuVOList = skuService.listSkuAllInfoBySpuId(spu.getSupplierSpuId(), spuVO, false);
            //判断选择sku长度是否小于供应商商品sku
            spu.setSkuChoiceStatus(SkuChoiceStatus.ALL_CHOICE.value());
            if (spuDTO.getSkuList().size() < skuVOList.size()) {
                //规格部分选择
                spu.setSkuChoiceStatus(SkuChoiceStatus.PART_CHOICE.value());
            }
        }
    }

    private void saveSpuExtension(SpuDTO spuDTO, Spu spu) {
        // 4.商品扩展信息
        SpuExtension spuExtension = new SpuExtension();
        spuExtension.setSpuId(spu.getSpuId());
        spuExtensionService.save(spuExtension);
    }

    private void handlePlatformAudit(int sysType, Spu spu) {
        // 判断是否开启“商品发布审核”，若开启，商品状态改为“待审核”【平台端发布不用审核】
        String prodSwitchConfig = configFeignClient.getConfig(Constant.SPU_SWITCH_CONFIG).getData();
        if (!SysTypeEnum.PLATFORM.value().equals(sysType)
                && !ObjectUtils.isEmpty(prodSwitchConfig)) {
            Boolean spuAudit = JSON.parseObject(prodSwitchConfig, new TypeReference<Map<String, Boolean>>() {
                    })
                    .getOrDefault("spuAudit", false);
            if (spuAudit) {
                spu.setStatus(SpuStatus.PUBLISH_WAIT_AUDIT.value());
            }
        }
    }

    /**
     * 处理平台端商品审核
     * @param sysType
     * @param spuDTO
     * @param spuDb
     * @param isUpdate true:只更新商品名称 false:整个商品修改
     */
    private void handlePlatformAudits(int sysType, SpuDTO spuDTO, SpuVO spuDb, boolean isUpdate) {
        // 判断是否开启“商品发布审核”，若开启，商品状态改为“待审核”【平台端发布不用审核】
        String prodSwitchConfig = configFeignClient.getConfig(Constant.SPU_SWITCH_CONFIG).getData();
        if (!SysTypeEnum.PLATFORM.value().equals(sysType) && !ObjectUtils.isEmpty(prodSwitchConfig)) {
            Boolean spuAudit = JSON.parseObject(prodSwitchConfig, new TypeReference<Map<String, Boolean>>() {
                    })
                    .getOrDefault("spuAudit", false);
            // 只有商品审核开启并且商品状态为上架状态的商品需要判断，并且不能是积分商品
            if (spuAudit && Objects.equals(spuDb.getStatus(), SpuStatus.PUT_SHELF.value()) && !spuDb.getSpuType().equals(SpuType.SCORE.value())) {
                if (isUpdate) {
                    if (spuDTO.getSpuLangList() != null && !Objects.equals(spuDTO.getSpuLangList().get(0).getSpuName(), spuDb.getSpuLangList().get(0).getSpuName())) {
                        logger.info("判断商品是否修改了商品名称");
                        spuDTO.setStatus(SpuStatus.PUBLISH_WAIT_AUDIT.value());
                    }
                } else {
                    handleAudits(spuDTO, spuDb);
                }
            }
        }
    }

    /**
     * 判断商品是否需要审核
     * @param spuDTO
     * @param spuDb
     */
    private void handleAudits(SpuDTO spuDTO, SpuVO spuDb){
        // 判断商品是否修改了商品名称
        logger.info("判断商品是否修改了商品名称、卖点、详情");
        Map<Integer, String> detailMap = spuDb.getDetailList().stream().collect(Collectors.toMap(SpuDetailVO::getLang, SpuDetailVO::getDetail));
        spuDTO.getSpuLangList().forEach(spuLangDTO -> {
            spuDb.getSpuLangList().forEach(dbSpuLang -> {
                if (spuLangDTO.getLang().equals(LanguageEnum.LANGUAGE_ZH_CN.getLang())) {
                    boolean spuflag = (!Objects.equals(spuLangDTO.getSpuName(), dbSpuLang.getSpuName())
                            || !Objects.equals(spuLangDTO.getSellingPoint(), dbSpuLang.getSellingPoint()));
                    boolean detailFlag = (Objects.equals(spuLangDTO.getDetail(), "") && spuDb.getDetailList().size() != 0)
                            || (!Objects.equals(spuLangDTO.getDetail(), "") && spuDb.getDetailList().size() == 0)
                            || !Objects.equals(spuLangDTO.getDetail(), detailMap.get(spuLangDTO.getLang()) == null ? "" : detailMap.get(spuLangDTO.getLang()));
                    if (spuflag || detailFlag) {
                        spuDTO.setStatus(SpuStatus.PUBLISH_WAIT_AUDIT.value());
                    }
                }
            });
        });
        // 判断商品是否修改了图片视频
        boolean picflag = Objects.equals(spuDTO.getMainImgUrl(), spuDb.getMainImgUrl())
                && Objects.equals(spuDTO.getImgUrls(), spuDb.getImgUrls())
                && Objects.equals(spuDTO.getVideo(), spuDb.getVideo());
        List<SkuVO> oldSkuList = skuService.listSkuWithAttrBySpuId(spuDTO.getSpuId());
        if (spuDTO.getSkuList().size() == oldSkuList.size() && picflag) {
            logger.info("判断商品是否修改了规格（名，值，图片）");
            spuDTO.getSkuList().forEach(sku -> {
                oldSkuList.forEach(dbSku -> {
                    if (Objects.equals(sku.getSkuId(), null)) {
                        logger.info("新增的sku");
                        spuDTO.setStatus(SpuStatus.PUBLISH_WAIT_AUDIT.value());
                        return;
                    }
                    if (sku.getSkuId().equals(dbSku.getSkuId()) && !Objects.equals(sku.getSkuLangList(), null)
                            && sku.getSkuLangList().size() != 0 && dbSku.getSkuLangList().size() != 0) {
                        Map<Integer, String> skuNameMap = sku.getSkuLangList().stream().collect(Collectors.toMap(SkuLangDTO::getLang, SkuLangDTO::getSkuName));
                        Map<Integer, String> dbSkuNameMap = dbSku.getSkuLangList().stream().collect(Collectors.toMap(SkuLangVO::getLang, SkuLangVO::getSkuName));
                        logger.info("语言判断");
                        if (!Objects.equals(skuNameMap.get(LanguageEnum.LANGUAGE_ZH_CN.getLang()), dbSkuNameMap.get(LanguageEnum.LANGUAGE_ZH_CN.getLang()))
                                || !Objects.equals(sku.getImgUrl(), dbSku.getImgUrl())) {
                            spuDTO.setStatus(SpuStatus.PUBLISH_WAIT_AUDIT.value());
                        }
                    }
                });
            });
        } else {
            spuDTO.setStatus(SpuStatus.PUBLISH_WAIT_AUDIT.value());
            return;
        }
        // 判断商品是否修改了基本属性
        List<SpuAttrValueVO> dbSpuAttrValues = spuAttrValueService.getSpuAttrsBySpuId(spuDTO.getSpuId());
        if (Objects.equals(spuDTO.getSpuAttrValues(), null) && Objects.isNull(dbSpuAttrValues)) {
            logger.info("判断商品基本属性为空，直接返回");
            return;
        }
        boolean parameterFlag = !Objects.equals(spuDTO.getSpuAttrValues(), null) && Objects.isNull(dbSpuAttrValues);
        boolean dbParameterFlag = Objects.nonNull(dbSpuAttrValues) && Objects.equals(spuDTO.getSpuAttrValues(), null);
        if (parameterFlag || dbParameterFlag) {
            logger.info("判断商品基本属性修改过，直接返回");
            spuDTO.setStatus(SpuStatus.PUBLISH_WAIT_AUDIT.value());
            return;
        }
        List<SpuAttrValueDTO> spuAttrValueDTOS = spuDTO.getSpuAttrValues().stream().filter(spuAttrValueDTO -> !Objects.equals(spuAttrValueDTO.getAttrValueName(), null)).collect(Collectors.toList());
        if (spuAttrValueDTOS.size() != dbSpuAttrValues.size()) {
            logger.info("商品新增或者删除了基本属性");
            spuDTO.setStatus(SpuStatus.PUBLISH_WAIT_AUDIT.value());
        } else {
            spuAttrValueDTOS.forEach(spuAttrValueDTO -> {
                dbSpuAttrValues.forEach(dbSpuAttrValue -> {
                    if (Objects.equals(spuAttrValueDTO.getAttrId(), dbSpuAttrValue.getAttrId())) {
                        logger.info("商品是否修改了基本属性值");
                        boolean attrflag = Objects.equals(spuAttrValueDTO.getAttrValueName(), dbSpuAttrValue.getSpuAttrValueLangList().get(0).getAttrValueName());
                        if (!attrflag) {
                            spuDTO.setStatus(SpuStatus.PUBLISH_WAIT_AUDIT.value());
                        }
                    }
                });
            });
        }
    }

    /**
     * 处理商品的预售信息
     *
     * @param spuDTO
     * @param spu
     */
    private void handlePreSaleInfo(SpuDTO spuDTO, Spu spu) {
        if (Objects.isNull(spuDTO.getPreSaleType()) || Objects.equals(spuDTO.getPreSaleType(), PreSaleType.DISABLE.value())) {
            spu.setPreSaleType(-1);
            return;
        }
        if (!(Objects.equals(spuDTO.getPreSaleType(), PreSaleType.FULLPAY.value()) || Objects.equals(spuDTO.getPreSaleType(), PreSaleType.DEPOSIT.value()))) {
            spu.setPreSaleType(-1);
            return;
        }
        if (Objects.isNull(spuDTO.getPreSaleDeliveryType())) {
            throw new LuckException(ResponseEnum.DATA_INCOMPLETE);
        }
        // 定金预售
        if (Objects.equals(spuDTO.getPreSaleType(), PreSaleType.DEPOSIT.value())) {
            Long depositAmount = PriceUtil.toLongCent(spuDTO.getDepositValue());
            if (depositAmount < 1) {
                throw new LuckException("定金数值设置错误，数值不能小于0.01");
            }
            spu.setDepositAmount(depositAmount);
            Long depositExpansionAmount = PriceUtil.toLongCent(spuDTO.getDepositExpansionValue());
            long balanceAmount = spu.getPriceFee() - depositExpansionAmount;
            if (depositExpansionAmount < 1) {
                throw new LuckException("定金膨胀数值设置错误，数值不能小于0.01");
            }
            if (depositExpansionAmount < depositAmount) {
                spu.setDepositExpansionAmount(depositAmount);
            }
            if (Objects.equals(spuDTO.getDepositType(), 1) && balanceAmount < 0) {
                throw new LuckException("定金膨胀数值不能大于最低尾款数值");
            }
            spu.setDepositExpansionAmount(depositExpansionAmount);
            // 校验时间先后顺序
            if (spuDTO.getBalanceStartTime().getTime() < spuDTO.getDepositStartTime().getTime() || spuDTO.getBalanceEndTime().getTime() < spuDTO.getDepositEndTime().getTime()) {
                throw new LuckException(ResponseEnum.HTTP_MESSAGE_NOT_READABLE);
            }
        }
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SPU_KEY, key = "#spuDTO.spuId")
    @Transactional(rollbackFor = Exception.class)
    public void update(SpuDTO spuDTO) {
        Integer sysType = AuthUserContext.get().getSysType();
        SpuVO spuDb = spuMapper.getBySpuId(spuDTO.getSpuId());
        checkSaveOrUpdateInfo(spuDTO, spuDb,false);
        Spu spu = BeanUtil.map(spuDTO, Spu.class);
        spuDTO.setStatus(spuDb.getStatus());
        handlePlatformAudits(sysType, spuDTO, spuDb, false);
        spu.setStatus(spuDTO.getStatus() == null? spuDb.getStatus() : spuDTO.getStatus());
        handlePreSaleInfo(spuDTO, spu);
        if (Objects.nonNull(spuDTO.getPreSaleType()) && !Objects.equals(spuDTO.getPreSaleType(), PreSaleType.DISABLE.value())) {
            checkProductType(spuDb);
        }
        spu.setBrandId(Objects.isNull(spuDTO.getBrandId()) ? Constant.ZERO_LONG : spuDTO.getBrandId());
        // 获取启用状态sku的最低价
        spuDTO.getSkuList().stream().filter(sku -> Objects.equals(sku.getStatus(), 1)).min(Comparator.comparing(SkuDTO::getPriceFee)).ifPresent(sku -> spu.setPriceFee(sku.getPriceFee()));
        //代销商品验证基本信息是否更改以及商品金额判断修改
        if (Objects.equals(spuDTO.getSupplierSpuType(), SupplierSpuType.CONSIGNMENT.value())) {
            verifySpuMsgIsChange(spuDTO,spu);
        }
        // 如果是虚拟商品，在保存一下默认配送json | 代销商品，且供应商发货，默认只有快递配送方式
        if (Objects.equals(spu.getSpuMold(), 1)
                || (Objects.equals(spuDTO.getSupplierDeliveryType(), 1) && Objects.equals(spuDTO.getSupplierSpuType(), 2))) {
            SpuVO.DeliveryModeVO mode = new SpuVO.DeliveryModeVO();
            mode.setHasShopDelivery(true);
            mode.setHasUserPickUp(false);
            mode.setHasCityDelivery(false);
            spu.setDeliveryMode(Json.toJsonString(mode));
        }
        // 1.修改商品信息
        spuMapper.update(spu);
        // 2.非代销商品修改属性信息
        if (!Objects.equals(spu.getSupplierSpuType(), SupplierSpuType.CONSIGNMENT.value())) {
            spuAttrValueService.update(spu.getSpuId(), spu.getCategoryId(), spuDb.getSupplierSpuType(), spuDTO.getSpuAttrValues());

        }
        // 3.国际化信息、商品详情
        List<SpuLang> spuLangList = loadSpuLangInfo(spuDTO, Boolean.FALSE);
        //校验赠品活动
        giveawayService.checkGiveawaySpuPrice(spuDTO);

        // 更新品牌信息
        if (!Objects.equals(spuDb.getBrandId(), spu.getBrandId())) {
            List<Long> brandIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
            brandIds.add(spuDb.getBrandId());
            brandIds.add(spu.getBrandId());
            brandMapper.batchUpdateSpuCount(brandIds);
        }
        if (Objects.equals(sysType, SysTypeEnum.SUPPLIER.value())) {
            // 设置供应商商品变化缓存，用于更新代销商品下架
            RedisUtil.set(ProductCacheNames.SUPPLIER_SPU_UPDATE_STATUS + spuDb.getSpuId(), new SupplierSpuUpdateDTO(), 0);
            //供应商修改 商家供应商发货的商品时
            //给代销商品增加供应商是商品更新标识
            List<SpuVO> commissionSpuList = spuMapper.getCommissionSpuListBySupplierDeliver(spuDb.getSpuId());
            SendStatus sendStatus = sendProductNotifyToShopTemplate.syncSend(RocketMqConstant.SUPPLIER_PRODUCT_UPDATE, new GenericMessage<>(spu.getSpuId())).getSendStatus();
            if (!Objects.equals(sendStatus, SendStatus.SEND_OK)) {
                throw new LuckException(ResponseEnum.EXCEPTION);
            }
            ServerResponseEntity<SupplierDetailBO> supplierResp = supplierDetailFeignClient.getSupplierBySupplierId(spuDb.getSupplierId());
            // 校验spu基本信息变更
            this.checkSupplierSpuMsgChange(spuDTO, spuDb);
            //发送给商家 代销商品变更提醒
            //批量发送商品下架消息给商家或供应商：商品xxx已被平台或供应商下架，点击去查看
            List<SendNotifyBO> notifyList = new ArrayList<>(Constant.INITIAL_CAPACITY);
            for (SpuVO spuVO : commissionSpuList) {
                SendNotifyBO sendNotifyBO = new SendNotifyBO();
                sendNotifyBO.setShopId(spuVO.getShopId());
                sendNotifyBO.setSendType(SendTypeEnum.COMMISSION_CHANGE.getValue());
                sendNotifyBO.setSpuId(spuVO.getSpuId());
                sendNotifyBO.setSpuName(spuVO.getName());
                sendNotifyBO.setSupplierName(supplierResp.getData().getSupplierName());
                notifyList.add(sendNotifyBO);
            }
            SendStatus sendStockStatus = sendProductNotifyToShopTemplate.syncSend(RocketMqConstant.SEND_PRODUCT_NOTIFY_TO_SHOP_TOPIC, new GenericMessage<>(notifyList)).getSendStatus();
            if (!Objects.equals(sendStockStatus, SendStatus.SEND_OK)) {
                throw new LuckException(ResponseEnum.EXCEPTION);
            }
        }
        if (spu.getStatus().equals(SpuStatus.PUBLISH_WAIT_AUDIT.value())){
            //商品进入待审核状态，下架活动
            spuOfflineService.offlineCommissionSpuStatusAndActivity(1, Collections.singletonList(spu.getSpuId()), null, null, StatusEnum.FINISHED.value(), sysType);
            // 下架商品时如果商品在套餐活动中且为主商品则失效套餐活动,赠品同样
            comboFeignClient.offComboMainSpu(spu.getSpuId());
            giveawayFeignClient.changeGiveawayStatus(spu.getSpuId());
        }
        //改变 供应商商品更新后代销商品是否已同步更新
        if (!Objects.isNull(spuDTO.getIsSynUpdate()) && Objects.equals(spuDTO.getIsSynUpdate(), IsSynUpdate.NO_CHANGE.value)) {
            spuMapper.changeSynUpdate(spuDTO.getSpuId(), IsSynUpdate.YEW_CHANGE.value());
        }
        // 更新商品库存及sku信息
        updateSku(spuDTO, spuLangList);

        // 移除代销商品基本信息是否改变缓存
        RedisUtil.del(CacheNames.SPU_SUPPLIER_CHANGE_LOG + CacheNames.UNION + spuDTO.getSpuId());
    }

    /**
     * 检查商品活动是否冲突
     *
     * @param spuDb 修改前的商品信息
     */
    private void checkProductType(SpuVO spuDb) {
        // 拼团商品
        if (Objects.equals(spuDb.getSpuType(), SpuType.GROUP.value()) && Objects.nonNull(spuDb.getActivityId()) && !Objects.equals(spuDb.getActivityId(), 0L)) {
            ServerResponseEntity<GroupActivityVO> activityInfo = groupFeignClient.getActivityInfo(spuDb.getActivityId());
            String activityName = "";
            if (activityInfo.isSuccess()) {
                activityName = activityInfo.getData().getActivityName();
            }
            throw new LuckException("商品已经参加名为" + activityName + "的拼团活动,活动失效或结束后才能修改预售信息");
        }
        // 秒杀商品
        if (Objects.equals(spuDb.getSpuType(), SpuType.SECKILL.value()) && Objects.nonNull(spuDb.getActivityId()) && !Objects.equals(spuDb.getActivityId(), 0L)) {
            ServerResponseEntity<SeckillApiVO> seckillInfo = seckillFeignClient.getSeckillInfoById(spuDb.getActivityId());
            String seckillName = "";
            if (seckillInfo.isSuccess()) {
                seckillName = seckillInfo.getData().getSeckillName();
            }
            throw new LuckException("商品已经参加名为" + seckillName + "的秒杀活动,活动失效或结束后才能修改预售信息");
        }
        // 积分商品
        if (Objects.equals(spuDb.getSpuType(), SpuType.SCORE.value())) {
            throw new LuckException("积分商品无法参与预售活动");
        }
        // 活动商品
        if (Objects.equals(spuDb.getSpuType(), SpuType.ACTIVE.value())) {
            throw new LuckException("活动商品无法参与预售活动");
        }
        ServerResponseEntity<List<ComboVO>> comboInfoResponseEntity = comboFeignClient.listComboInfoBySpuId(spuDb.getShopId(), spuDb.getSpuId());
        List<ComboVO> comboVOList = comboInfoResponseEntity.getData();
        // 优惠套餐
        if (CollUtil.isNotEmpty(comboVOList)) {
            StringBuilder comboName = new StringBuilder(Constant.INITIAL_CAPACITY);
            comboVOList.forEach(comboVO -> comboName.append(comboVO.getName()).append(" "));
            throw new LuckException("此商品正在参加" + comboName + "优惠套餐,待套餐活动失效或结束后才能修改预售信息");
        }
        // 下架关联的组合商品
        List<Long> spuIds = skuComboService.getCombSpusByComboSpuIds(Collections.singletonList(spuDb.getSpuId()),null);
        if(CollUtil.isNotEmpty(spuIds)) {
            batchChangeSpuStatus(spuIds, StatusEnum.DISABLE.value());
        }
    }

    private void verifySpuMsgIsChange(SpuDTO spuDTO, Spu spu) {
        // 供应商发货，根据供应商的sku启用状态获取最低价
        if(Objects.equals(spuDTO.getSupplierDeliveryType(),SupplierDeliveryType.SUPPLIER_DELIVERY.value())){
            long priceFee = 0L;
            for (SkuDTO skuDTO : spuDTO.getSkuList()) {
                if(!Objects.equals(skuDTO.getSupplierSkuStatus(),StatusEnum.ENABLE.value())){
                    continue;
                }
                priceFee = priceFee == 0L ? skuDTO.getPriceFee() : Math.min(priceFee,skuDTO.getPriceFee());
            }
            spu.setPriceFee(priceFee);
        }
        SpuConsignmentChange spuConsignmentChange = new SpuConsignmentChange();
        spuConsignmentChange.setSpuId(spuDTO.getSpuId());
        spuConsignmentChange.setImageChange(spuDTO.getImageChange());
        spuConsignmentChange.setBrandChange(spuDTO.getBrandChange());
        spuConsignmentChange.setDetailChange(spuDTO.getDetailChange());
        spuConsignmentChange.setVideoChange(spuDTO.getVideoChange());
        spuConsignmentChange.setMeasureUnitChange(spuDTO.getMeasureUnitChange());
        spuConsignmentChange.setSellingPointChange(spuDTO.getSellingPointChange());
        spuConsignmentChange.setNameChange(spuDTO.getNameChange());
        spuConsignmentChange.setSpuCodeChange(spuDTO.getSpuCodeChange());
        if (Objects.isNull(spuDTO.getImageChange()) && Objects.isNull(spuDTO.getBrandChange()) && Objects.isNull(spuDTO.getDetailChange())
                && Objects.isNull(spuDTO.getVideoChange()) && Objects.isNull(spuDTO.getMeasureUnitChange())
                && Objects.isNull(spuDTO.getSellingPointChange()) && Objects.isNull(spuDTO.getNameChange()) && Objects.isNull(spuDTO.getSpuCodeChange())) {
            return;
        }
        spuConsignmentChangeMapper.updateBySpuId(spuConsignmentChange);
    }

    /**
     * @param
     */
    public List<SpuLang> loadSpuLangInfo(SpuDTO spuDTO, Boolean isSave) {
        List<SpuDetail> spuDetailList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        List<SpuLang> spuLangList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        boolean dataCorrect = false;
        for (SpuLangDTO spuLangDTO : spuDTO.getSpuLangList()) {
            SpuLang spuLang = BeanUtil.map(spuLangDTO, SpuLang.class);
            spuLang.setSpuId(spuDTO.getSpuId());
            boolean isBlank = StrUtil.isBlank(spuLang.getSpuName()) && StrUtil.isBlank(spuLang.getSellingPoint());
            if (!isBlank) {
                spuLangList.add(spuLang);
            }
            if (StrUtil.isNotBlank(spuLangDTO.getDetail())) {
                SpuDetail spuDetail = new SpuDetail();
                spuDetail.setSpuId(spuDTO.getSpuId());
                spuDetail.setLang(spuLangDTO.getLang());
                spuDetail.setDetail(spuLangDTO.getDetail());
                spuDetailList.add(spuDetail);
            }
            if (!isBlank && Objects.equals(spuLang.getLang(), Constant.DEFAULT_LANG)) {
                dataCorrect = true;
            }

        }

        // 商品名称、卖点，商品详情，是否包含默认语言信息
        if (CollUtil.isEmpty(spuLangList) || !dataCorrect) {
            throw new LuckException(ResponseEnum.DATA_ERROR);
        }
        if (isSave) {
            if (spuDetailList.size() != 0) {
                spuDetailService.batchSave(spuDetailList);
            }
            if (spuLangList.size() != 0) {
                spuLangService.batchSave(spuLangList);
            }
            return spuLangList;
        }
        SpuVO spuDb = getBySpuId(spuDTO.getSpuId());
        spuDetailService.update(spuDetailList, spuDb.getDetailList(), spuDb.getSpuId());
        spuLangService.update(spuLangList, spuDb.getSpuId());
        return spuLangList;
    }


    /**
     * 更新sku列表信息
     *
     * @param spuDTO 商品信息
     */
    private void updateSku(SpuDTO spuDTO, List<SpuLang> spuLangList) {
        // 供应商商品不需要进行活动判断
        if(spuDTO.getShopId() != null) {
            logger.info(" 商品进行套餐、赠品活动判断");
            // 套餐,赠品商品禁止修改新增/删除/禁用sku
            List<SkuDTO> newSkuList = spuDTO.getSkuList();
            List<Integer> newSkuStatus = newSkuList.stream().map(SkuDTO::getStatus).toList();
            // 获取修改前的sku信息
            List<SkuVO> oldSkuList = skuService.listSkuWithAttrBySpuId(spuDTO.getSpuId());
            List<Integer> oldSkuStatus = oldSkuList.stream().map(SkuVO::getStatus).toList();
            boolean equals = newSkuStatus.equals(oldSkuStatus);
            if (newSkuList.size() != oldSkuList.size() || !equals) {
                Boolean isComboSpu = comboFeignClient.checkComboSpu(spuDTO.getSpuId(), spuDTO.getShopId()).getData();
                if (isComboSpu) {
                    throw new LuckException("商品正在参与套餐活动，不能修改规格");
                }
                List<GiveawaySpuVO> giveawaySpuVOList = giveawaySpuMapper.getBySpuId(spuDTO.getSpuId());
                if (CollectionUtil.isNotEmpty(giveawaySpuVOList)) {
                    throw new LuckException("商品正在参与赠品活动，不能修改规格");
                }
            }
        }
        boolean notAllChange = false;
        Integer stock = 0;
        for (SkuDTO skuDTO : spuDTO.getSkuList()) {
            stock = Objects.isNull(skuDTO.getStock()) ? 0 : skuDTO.getStock() + stock;
            if (!notAllChange && Objects.nonNull(skuDTO.getSkuId())) {
                notAllChange = true;
            }
            if (Objects.isNull(skuDTO.getSkuId())) {
                if (spuDTO.getSpuType() != null && spuDTO.getSpuType().equals(SpuType.GROUP.value())) {
                    // 商品正在参与拼团活动，无法新增规格
                    throw new LuckException("商品正在参与拼团活动，无法新增规格");
                }
                if (spuDTO.getSpuType() != null && spuDTO.getSpuType().equals(SpuType.SECKILL.value())) {
                    // 商品正在参与秒杀活动，无法新增规格
                    throw new LuckException("商品正在参与秒杀活动，无法新增规格");
                }
            }
        }
        // 商品库存、商品sku
        // sku更新
        if (notAllChange) {
            updateGroupActivityPrice(spuDTO);
            skuService.update(spuDTO, spuDTO.getSkuList());
            return;
        }
        List<SkuVO> skuVOList = skuMapper.listSkuWithAttrBySpuId(spuDTO.getSpuId());
        if (skuVOList.size() > spuDTO.getSkuList().size()) {
            //删除了sku
            RedisUtil.set(ProductCacheNames.SKU_STATUS_DELETE + spuDTO.getSpuId(), 1, -1);
            List<Long> commissionSpuIdList = spuMapper.getCommissionSpuIdList(spuDTO.getSpuId(), null);
            //改变 供应商商品更新后代销商品是否已同步更新
            if (commissionSpuIdList.size() != 0) {
                spuMapper.batchChangeSynUpdate(commissionSpuIdList, IsSynUpdate.YEW_CHANGE.value());
            }
        }
        skuService.deleteBySpuId(spuDTO);
        loadSkuInfo(spuLangList, spuDTO.getMainImgUrl(), spuDTO.getSkuList());
        skuService.saveSkuAndStock(spuDTO.getSpuMold(), spuDTO.getSpuId(), spuDTO.getStatus(), spuDTO.getSkuList(), AuthUserContext.get().getSysType(), AuthUserContext.get().getUserId(), AuthUserContext.get().getTenantId());
    }

    private void updateGroupActivityPrice(SpuDTO spuDTO) {
        List<Long> skuIds = spuDTO.getSkuList().stream().filter(sku -> Objects.equals(sku.getStatus(), 1)).map(SkuDTO::getSkuId).collect(Collectors.toList());
        ServerResponseEntity<Void> updateGroupActivityPrice = groupFeignClient.updateGroupActivityPrice(skuIds, spuDTO.getSpuId());
        if (!updateGroupActivityPrice.isSuccess()) {
            throw new LuckException(updateGroupActivityPrice.getMsg());
        }
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SPU_KEY, key = "#spuId")
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void deleteById(Long spuId) {
        SpuVO spuVO = getBySpuId(spuId);
        if (Objects.isNull(spuVO) || Objects.equals(spuVO.getStatus(), StatusEnum.DELETE.value())) {
            throw new LuckException("商品不存在或者已被删除！");
        }
        // 删除商品、sku信息(逻辑删除)
        spuMapper.updateStatusBySpuId(spuId);
        List<Long> spuIds = Collections.singletonList(spuId);
        // 删除关联活动的信息
        handleSpuStatusChange(spuIds);
        // 下线掉关联商品的活动 (在线下活动之前已经修改了商品的状态，下面的方法就查询不到已有的商品了，所以就需要带着修改后的商品去状态去查询)
        spuOfflineService.offlineSpuStatusAndActivity(1, spuIds, null, null, SpuStatus.DELETE.value(), null);
        // 更新品牌信息
        brandMapper.batchUpdateSpuCount(Collections.singleton(spuVO.getBrandId()));
        // 移除关联的分组
        handleStatusChange(Collections.singletonList(spuId));
        // 删除关联的组合商品信息
        skuComboService.deleteByComboSpuIds(spuIds);
        handleStatusChange(Collections.singletonList(spuId));
        //如果是供应商品,给代销商品标注供应商品以更新
        if (Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.YES.value())) {
            SpuDTO spuDTO = BeanUtil.map(spuVO, SpuDTO.class);
            this.offSupplierSendCommissionSpu(spuDTO);
        }
        // 更新关联该商品的轮播图，以及缓存
        indexImgFeignClient.udpateIndexImgBySpuId(spuId, spuVO.getShopId());
        // 清除商品的统计数据
        flowFeignClient.deleteSpuDataBySpuId(spuId);
        // 删除仓库门店关联商品库存信息
        stockPointSkuService.deleteBySpuId(spuId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSpuOrSku(SpuDTO spuDTO) {
        Spu spu = new Spu();
        spu.setSpuId(spuDTO.getSpuId());
        SpuVO spuDb = spuMapper.getBySpuId(spuDTO.getSpuId());
        Integer sysType = AuthUserContext.get().getSysType();
        // 供货价修改代销商品需要判断是否下架
        if (Objects.equals(sysType, SysTypeEnum.SUPPLIER.value()) && Objects.nonNull(spuDTO.getPriceFee())) {
            SupplierSpuUpdateDTO spuUpdateDTO = new SupplierSpuUpdateDTO();
            spuUpdateDTO.setPriceUpdate(true);
            RedisUtil.set(CacheNames.SUPPLIER_SPU_UPDATE_STATUS + spuDb.getSpuId(), spuUpdateDTO, 0);
        }

        handlePlatformAudits(sysType, spuDTO, spuDb, true);
        spu.setStatus(spuDTO.getStatus() == null? spuDb.getStatus() : spuDTO.getStatus());
        ProductLangUtil.spu(spuDb);
        List<SkuVO> skusDb = skuMapper.listSkuWithAttrBySpuId(spuDTO.getSpuId());
        // 修改商品名
        if (CollUtil.isNotEmpty(spuDTO.getSpuLangList())) {
            SpuVO spuVO = spuMapper.getBySpuId(spuDTO.getSpuId());
            if (Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.CONSIGNMENT.value())) {
                //代销商品修改名称，记录代销商品基本信息是否已更新
                SpuConsignmentChange spuConsignmentChange = new SpuConsignmentChange();
                spuConsignmentChange.setSpuId(spuDTO.getSpuId());
                spuConsignmentChange.setNameChange(1);
                spuConsignmentChangeMapper.updateBySpuId(spuConsignmentChange);
            }
            for (SpuLangDTO spuLangDTO : spuDTO.getSpuLangList()) {
                spuLangDTO.setSpuId(spuDTO.getSpuId());
            }
            spuLangService.update(BeanUtil.mapAsList(spuDTO.getSpuLangList(), SpuLang.class), spuDTO.getSpuId());
        }
        spu.setSeq(spuDTO.getSeq());
        spuDTO.setName(spuDb.getName());
        spuDTO.setMainImgUrl(spuDb.getMainImgUrl());
        if (CollUtil.isNotEmpty(spuDTO.getSkuList())) {
            skuService.updateAmountOrStock(spuDTO);
        }
        spu.setPriceFee(spuDTO.getPriceFee());
        //校验赠品活动
        spuDTO.setPriceFee(null == spuDTO.getPriceFee() ? spuDb.getPriceFee() : spuDTO.getPriceFee());
        giveawayService.checkGiveawaySpuPrice(spuDTO);
        spuMapper.update(spu);
        //供应商修改spu信息时，生成对应的变更记录
        if (Objects.equals(AuthUserContext.get().getSysType(), SysTypeEnum.SUPPLIER.value())) {
            //变更类型 1.商品上架 2.商品下架 3.代销sku信息变更4.新增sku
            //新增sku
            List<SpuSupplierChangeLog> spuSupplierChangeLogs = new ArrayList<>(Constant.INITIAL_CAPACITY);
            if (CollUtil.isNotEmpty(spuDTO.getSkuList()) && spuDTO.getSkuList().size() > skusDb.size()) {
                SpuSupplierChangeLog spuSupplierChangeLog = new SpuSupplierChangeLog();
                spuSupplierChangeLog.setSpuId(spuDTO.getSpuId());
                spuSupplierChangeLog.setChangeType(SupplierSpuChangeType.ADD_SKU.value());
                spuSupplierChangeLogs.add(spuSupplierChangeLog);
            }
            //商品上架
            if (!Objects.equals(spuDTO.getStatus(), spuDb.getStatus()) && Objects.equals(spuDTO.getStatus(), StatusEnum.ENABLE.value())) {
                SpuSupplierChangeLog spuSupplierChangeLog = new SpuSupplierChangeLog();
                spuSupplierChangeLog.setSpuId(spuDTO.getSpuId());
                spuSupplierChangeLog.setChangeType(SupplierSpuChangeType.PUT_SHELF.value());
                spuSupplierChangeLogs.add(spuSupplierChangeLog);
            }
            //商品下架
            if (!Objects.equals(spuDTO.getStatus(), spuDb.getStatus()) && Objects.equals(spuDTO.getStatus(), StatusEnum.DISABLE.value())) {
                SpuSupplierChangeLog spuSupplierChangeLog = new SpuSupplierChangeLog();
                spuSupplierChangeLog.setChangeType(SupplierSpuChangeType.OFF_SHELF.value());
                spuSupplierChangeLog.setSpuId(spuDTO.getSpuId());
                spuSupplierChangeLogs.add(spuSupplierChangeLog);
            }
            //代销商品信息变更
            if (Objects.equals(spuDb.getSupplierSpuType(), SupplierSpuType.YES.value())) {
                SpuSupplierChangeLog spuSupplierChangeLog = new SpuSupplierChangeLog();
                spuSupplierChangeLog.setChangeType(SupplierSpuChangeType.SKU_MSG_CHANGE.value());
                spuSupplierChangeLog.setSpuId(spuDTO.getSpuId());
                spuSupplierChangeLogs.add(spuSupplierChangeLog);
            }
            if (spuSupplierChangeLogs.size() > 0) {
                spuSupplierChangeLogService.saveBatch(spuSupplierChangeLogs);
            }
        }
        if (spu.getStatus().equals(SpuStatus.PUBLISH_WAIT_AUDIT.value())){
            //商品进入待审核状态，下架活动
            spuOfflineService.offlineCommissionSpuStatusAndActivity(1, Collections.singletonList(spu.getSpuId()), null, null, StatusEnum.FINISHED.value(), sysType);
            // 下架商品时如果商品在套餐活动中且为主商品则失效套餐活动,赠品同样
            comboFeignClient.offComboMainSpu(spu.getSpuId());
            giveawayFeignClient.changeGiveawayStatus(spu.getSpuId());
        }
    }

    @Override
    public void updateSpuUpdateTime(List<Long> spuIds, List<Long> categoryIds, List<Long> shopIds, Integer sysType) {
        if (CollUtil.isEmpty(spuIds) && CollUtil.isEmpty(categoryIds) && CollUtil.isEmpty(shopIds)) {
            return;
        }
        spuMapper.updateSpuUpdateTime(spuIds, categoryIds, shopIds, sysType);
    }


    /**
     * 处理分类数据
     *
     * @param category
     * @return
     */
    private EsCategoryBO handleCategory(CategoryVO category) {
        EsCategoryBO categoryBO = new EsCategoryBO();
        categoryBO.setCategoryId(category.getCategoryId());
        Map<Integer, String> categoryMap = category.getCategoryLangList().stream().collect(Collectors.toMap(CategoryLangVO::getLang, CategoryLangVO::getName));
        categoryBO.setCategoryNameZh(categoryMap.get(LanguageEnum.LANGUAGE_ZH_CN.getLang()));
        categoryBO.setCategoryNameEn(categoryMap.get(LanguageEnum.LANGUAGE_EN.getLang()));
        return categoryBO;
    }

    @Override
    public List<Long> getSpuIdsBySpuUpdateDTO(List<Long> shopCategoryIds, List<Long> categoryIds, Long brandId, Long shopId) {
        if (CollUtil.isEmpty(shopCategoryIds) && CollUtil.isEmpty(categoryIds) && Objects.isNull(brandId) && Objects.isNull(shopId)) {
            return new ArrayList<>(0);
        }
        return spuMapper.getSpuIdsBySpuUpdateDTO(shopCategoryIds, categoryIds, brandId, shopId);
    }

    @Override
    @Cacheable(cacheNames = CacheNames.SPU_ACTIVITY_KEY, key = "#spuId", sync = true)
    public SpuActivityAppVO spuActivityBySpuId(Long shopId, Long spuId) {
        SpuActivityAppVO spuActivity = new SpuActivityAppVO();
        // 满减活动
        ServerResponseEntity<List<SpuDiscountAppVO>> discountResponse = discountFeignClient.spuDiscountList(shopId, spuId);
        if (!Objects.equals(discountResponse.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(discountResponse.getMsg());
        }
        spuActivity.setDiscountList(discountResponse.getData());

        // 优惠券
        ServerResponseEntity<List<SpuCouponAppVO>> couponResponse = couponFeignClient.couponOfSpuDetail(shopId, spuId);
        if (!Objects.equals(couponResponse.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(couponResponse.getMsg());
        }
        spuActivity.setCouponList(couponResponse.getData());
        return spuActivity;
    }

    @Override
    public List<Long> listSpuIdsByShopId(Long shopId) {
        return spuMapper.getSpuIdsBySpuUpdateDTO(null, null, null, shopId);
    }

    @Override
    public SpuCountVO getSpuCountBySupplierId(Long supplierId) {
        return spuMapper.getSpuCountBySupplierId(supplierId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void offlineSpuByShopId(Long shopId) {
        spuMapper.offlineSpuByShopId(shopId);
        // 查询出秒杀or团购的商品进行下线
        // 下线掉关联商品的活动
        // 下面这个方法查不到正常状态的商品了，所以需要把修改后的商品状态传过去
        spuOfflineService.offlineSpuStatusAndActivity(3, null, shopId, null, StatusEnum.DISABLE.value(), null);
    }

    @Override
    public List<SpuVO> list(SpuPageSearchDTO spu) {
        return spuMapper.list(spu);
    }

    @Override
    public void updateSpu(Spu spu) {
        spuMapper.update(spu);
    }

    @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.PROD.getValue());
        offlineHandleEvent.setOfflineReason(offlineHandleEventDto.getOfflineReason());
        ServerResponseEntity<Void> responseEntity = offlineHandleEventFeignClient.save(offlineHandleEvent);
        if (!Objects.equals(responseEntity.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(responseEntity.getMsg());
        }
        // 更新活动状态为下线状态
        changeSpuStatus(offlineHandleEvent.getHandleId(), StatusEnum.OFFLINE.value());
    }

    @Override
    public OfflineHandleEventVO getOfflineHandleEvent(Long couponId) {
        ServerResponseEntity<OfflineHandleEventVO> offlineHandleEventResponse =
                offlineHandleEventFeignClient.getProcessingEventByHandleTypeAndHandleId(OfflineHandleEventType.PROD.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 spuId = offlineHandleEventDto.getHandleId();
        // 审核通过
        if (Objects.equals(offlineHandleEventDto.getStatus(), OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())) {
            changeSpuStatus(spuId, StatusEnum.DISABLE.value());
        }
        // 审核不通过
        else if (Objects.equals(offlineHandleEventDto.getStatus(), OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue())) {
            changeSpuStatus(spuId, StatusEnum.OFFLINE.value());
        }
        //发送商品审核结果消息给商家或供应商：商品xxx审核成功，点击去查看
        SpuVO spuVO = spuMapper.getBySpuId(spuId);
        SendNotifyBO sendNotifyBO = new SendNotifyBO();
        if (Objects.nonNull(spuVO.getSupplierSpuType()) && Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.YES.value())) {
            sendNotifyBO.setSupplierId(spuVO.getSupplierId());
        } else {
            sendNotifyBO.setShopId(spuVO.getShopId());
        }
        sendNotifyBO.setSendType(Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.YES.value()) ? SendTypeEnum.PRODUCT_AUDIT_TO_SUPPLIER.getValue() : SendTypeEnum.PRODUCT_AUDIT.getValue());
        sendNotifyBO.setSpuId(spuVO.getSpuId());
        sendNotifyBO.setSpuName(spuVO.getName());

        SendStatus sendStockStatus = sendProductNotifyToShopTemplate.syncSend(RocketMqConstant.SEND_PRODUCT_NOTIFY_TO_SHOP_TOPIC, new GenericMessage<>(Collections.singletonList(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());
        }
        // 更新优惠券为待审核状态
        changeSpuStatus(offlineHandleEventDto.getHandleId(), StatusEnum.WAIT_AUDIT.value());
    }

    @Override
    public List<SpuVO> listCanSeckillProd(Long spuId, Long shopId) {
        PageDTO pageDTO = new PageDTO();
        pageDTO.setPageNum(0);
        pageDTO.setPageSize(PageDTO.MAX_PAGE_SIZE);
        SpuDTO spuDTO = new SpuDTO();
        spuDTO.setShopId(shopId);
        spuDTO.setSpuId(spuId);
        return spuMapper.listCanSeckillProd(new PageAdapter(pageDTO), spuDTO, I18nMessage.getLang());
    }

    @Override
    public Integer countByTransportId(Long transportId) {
        return spuMapper.countByTransportId(transportId);
    }

    @Override
    public void changeToNormalSpu(List<Long> spuIds) {
        spuMapper.changeToNormalSpu(spuIds);
    }

    @Override
    public int countByCategoryAndShopId(Long categoryId, Long shopId, Integer sysType) {
        return spuMapper.countByCategoryAndShopId(categoryId, shopId, sysType);
    }

    @Override
    public void handleStatusChange(List<Long> spuIds) {
        // 删除商品的分组信息
        spuTagReferenceService.deleteSpuData(spuIds);

    }

    @Override
    public Integer countByUserId(Long userId) {
        return spuMapper.countByUserId(userId);
    }

    @Override
    public List<SpuVO> listSpuNameBySpuIds(List<Long> spuIds) {
        if (CollUtil.isEmpty(spuIds)) {
            return new ArrayList<>(0);
        }
        List<SpuVO> spuVOList = spuMapper.listSpuNameBySpuIds(spuIds);
        ProductLangUtil.spuList(spuVOList);
        return spuVOList;
    }

    @Override
    public List<SpuVO> listSpuDetailBySpuIds(List<Long> spuIds) {
        return spuMapper.listSpuDetailBySpuIds(spuIds);
    }

    @Override
    public void batchChangeSpuStatusByCidListAndShopId(List<Long> cidList, Integer status, Long shopId, Integer sysType) {
        if (Objects.isNull(cidList) || cidList.size() == 0) {
            return;
        }
        List<Long> spuIds = spuMapper.listIdByCidAndShopId(cidList, shopId, sysType);
        if (Objects.isNull(spuIds) || spuIds.size() == 0) {
            return;
        }
        this.batchChangeSpuStatus(spuIds, status);
    }

    @Override
    public List<SpuVO> listSpuBySpuIds(List<Long> spuIds) {
        if (CollUtil.isEmpty(spuIds)) {
            return null;
        }
        List<SpuVO> spuList = spuMapper.listSpuBySpuIds(spuIds);
        ProductLangUtil.spuList(spuList);
        if (CollectionUtil.isEmpty(spuList)) {
            return spuList;
        }
        List<Long> shopIds = spuList.stream().map(SpuVO::getShopId).collect(Collectors.toList());
        ServerResponseEntity<List<ShopDetailVO>> shopResponse = shopDetailFeignClient.listByShopIds(shopIds);
        if (!shopResponse.isSuccess()) {
            throw new LuckException(shopResponse.getMsg());
        }
        List<ShopDetailVO> shopDetailList = shopResponse.getData();
        Map<Long, String> shopMap = shopDetailList.stream().collect(Collectors.toMap(ShopDetailVO::getShopId, ShopDetailVO::getShopName));
        for (SpuVO spuVO : spuList) {
            if (!shopMap.containsKey(spuVO.getShopId())) {
                continue;
            }
            spuVO.setShopName(shopMap.get(spuVO.getShopId()));
        }
        return spuList;
    }

    @Override
    public void verifySpuData() {
        Date currentTime = new Date();
        // 获取数据库商品更新的数量
        ProductSearchDTO productSearchDTO = new ProductSearchDTO();
        Long spuNum = spuMapper.getAllSpuNum(currentTime);
        productSearchDTO.setPageSize(1);
        productSearchDTO.setPageNum(1);
        // 需要获取被删除的商品，否则数量不对
        productSearchDTO.setGetDelete(1);
        // 数量相同，不需要更新
        if (verifySpuNum(currentTime, productSearchDTO, spuNum)) {
            return;
        }
        PageDTO pageDTO = new PageDTO();
        pageDTO.setPageSize(Constant.MAX_PAGE_SIZE);
        pageDTO.setPageNum(1);
        List<Long> updateList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        ProductSearchDTO simpleDTO = new ProductSearchDTO();
        while (spuNum > 0) {
            // 每十次循环判断下，数据库与es中的商品数量是否一致了, 一致则不需要再更新
            boolean notUpdate = pageDTO.getPageNum() % 10 == 0 && verifySpuNum(currentTime, productSearchDTO, null) && CollUtil.isEmpty(updateList);
            if (notUpdate) {
                return;
            }
            PageVO<Spu> page = PageUtil.doPage(pageDTO, () -> spuMapper.listAllSpu(currentTime));
            if (CollUtil.isEmpty(page.getList())) {
                break;
            }
            List<Long> spuIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
            for (Spu spu : page.getList()) {
                spuIds.add(spu.getSpuId());
            }
            simpleDTO.setSpuIds(spuIds);
            // 需要获取被删除的商品，否则数量不对
            simpleDTO.setGetDelete(1);
            ServerResponseEntity<List<SpuSearchVO>> spuResponseEntity = searchSpuFeignClient.simpleList(simpleDTO);
            if (!spuResponseEntity.isSuccess()) {
                throw new LuckException(spuResponseEntity.getMsg());
            }
            Map<Long, Date> spuMap = spuResponseEntity.getData().stream().collect(Collectors.toMap(SpuSearchVO::getSpuId, SpuSearchVO::getUpdateTime));
            for (Spu spu : page.getList()) {
                boolean isSame = spuMap.containsKey(spu.getSpuId()) && DateUtil.isSameTime(spu.getUpdateTime(), spuMap.get(spu.getSpuId()));
                if (isSame) {
                    continue;
                }
                updateList.add(spu.getSpuId());
            }
            if (updateList.size() > Constant.MAX_DATA_HANDLE_NUM) {
                spuMapper.updateSpuUpdateTime(updateList, null, null, null);
                updateList.clear();
            }
            spuNum = spuNum - Constant.MAX_PAGE_SIZE;
            pageDTO.setPageNum(pageDTO.getPageNum() + 1);
        }
        if (CollUtil.isNotEmpty(updateList)) {
            spuMapper.updateSpuUpdateTime(updateList, null, null, null);
        }
    }

    @Override
    public SpuAppVO prodInfo(Long spuId) {
        SpuServiceImpl spuService = (SpuServiceImpl) AopContext.currentProxy();
        // 商品信息
        SpuVO spu = spuService.getBySpuId(spuId);
        // 如果商品未上架，直接返回
        if (!Objects.equals(spu.getStatus(), StatusEnum.ENABLE.value())) {
            this.updateSpuUpdateTime(Collections.singletonList(spuId), null, null, null);
            throw new LuckException("商品已下架");
        }
        ProductLangUtil.spu(spu);
        ProductLangUtil.spuDetail(spu);
        // 检验店铺信息
        this.checkShopStatusIsOpen(spu.getShopId());
        // 判断同城配送情况
        this.checkSameCity(spu);
        SpuAppVO spuAppVO = BeanUtil.map(spu, SpuAppVO.class);
        spuAppVO.setSpuName(spu.getName());

        // 插入商品评论数量
        this.loadSpuSale(spuId, spuService, spuAppVO);

        // 商品sku
        List<SkuVO> skuList = skuService.listSkuWithAttrBySpuId(spu.getSpuId());

        // 代销商品且是供应商发货，更改商品运费模板、商品sku信息替换为供应商商品sku信息
        if (Objects.nonNull(spu.getSupplierSpuType()) && Objects.equals(spu.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())) {
            this.handleSupplierDelivery(spuService, spu, spuAppVO, skuList);
        }

        // 启用的sku，app查询到的商品是启用sku的商品
        skuList = skuList.stream().filter(skuVO -> Objects.equals(skuVO.getStatus(), StatusEnum.ENABLE.value())).collect(Collectors.toList());
        // 获取商品sku的国际化信息
        ProductLangUtil.skuList(skuList);
        // 如果是组合商品获取所有组合的商品信息并组装,且获取对应库存
        if(Objects.equals(spu.getSpuMold(),SpuMold.COMBO.value())){
            skuService.assembleComboSpuListAndStock(skuList,spu);
        }
        // 拼接sku属性
        List<SkuAppVO> skuAppList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (SkuVO sku : skuList) {
            SkuAppVO skuAppVO = BeanUtil.map(sku, SkuAppVO.class);
            skuAppVO.setProperties(skuService.spliceProperties(sku.getSpuSkuAttrValues()));
            skuAppList.add(skuAppVO);
        }

        spuAppVO.setSkus(skuAppList);
        return spuAppVO;
    }

    private void handleSupplierDelivery(SpuServiceImpl spuService, SpuVO spu, SpuAppVO spuAppVO, List<SkuVO> skuList) {
        // 获取供应商商品spu
        SpuVO spupplierSpu = spuService.getBySpuId(spuAppVO.getSupplierSpuId());
        spuAppVO.setDeliveryTemplateId(spupplierSpu.getDeliveryTemplateId());
        //获取供应商品sku
        List<SkuVO> supplierSkuList = skuService.listSkuWithAttrBySpuId(spu.getSupplierSpuId());
        Map<Long, SkuVO> skuMap = supplierSkuList.stream().collect(Collectors.toMap(SkuVO::getSkuId, s -> s));
        Iterator<SkuVO> iterator = skuList.iterator();
        while (iterator.hasNext()) {
            SkuVO skuVO = iterator.next();
            SkuVO supplierSkuVO = skuMap.get(skuVO.getSupplierSkuId());
            // 判断是否需要删除
            boolean isDelete = Objects.isNull(supplierSkuVO) ||
                    Objects.equals(supplierSkuVO.getStatus(), null) ||
                    Objects.equals(supplierSkuVO.getStatus(), 0) ||
                    Objects.equals(supplierSkuVO.getStatus(), -1);
            //供应商商品信息
            if (isDelete) {
                iterator.remove();
                continue;
            }
            skuVO.setWeight(supplierSkuVO.getWeight());
            skuVO.setVolume(supplierSkuVO.getVolume());
            skuVO.setSupplyPriceFee(supplierSkuVO.getPriceFee());
            skuVO.setSupplierSkuCode(supplierSkuVO.getPartyCode());
            skuVO.setSupplierSkuStatus(supplierSkuVO.getStatus());
            if (supplierSkuVO.getStatus() >= 0) {
                skuVO.setIsSell(supplierSkuVO.getStatus());
            }
        }
    }

    /**
     * 插入商品销量和评论数量
     *
     * @param spuId
     * @return
     */
    private void loadSpuSale(Long spuId, SpuServiceImpl spuService, SpuAppVO spuAppVO) {
        SpuExtension spuExtension = spuService.getSpuExtension(spuId);
        spuAppVO.setCommentNum(spuExtension.getCommentNum());
    }

    @Override
    public void offlineSpuByShopIds(Integer type, List<Long> shopIds) {
        if (CollUtil.isEmpty(shopIds)) {
            return;
        }
        List<Long> spuIds = spuMapper.listSpuIdByShopIdsAndStatus(SysTypeEnum.MULTISHOP.value(), shopIds, StatusEnum.ENABLE.value(), null);
        if (CollUtil.isEmpty(spuIds)) {
            return;
        }
        // 删除商品分组信息
        this.handleStatusChange(spuIds);
        if (SHOP_OFFLINE_TYPE.equals(type)) {
            logger.info("通过店铺ids下架店铺商品");
            spuOfflineService.offlineSpuStatusAndActivity(3, spuIds, null, null, null, shopIds);
        } else {
            logger.info("通过商品id修改商品类型");
            spuOfflineService.offlineSpuStatusAndActivity(type, spuIds, null, null, null, null);
        }
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SPU_KEY, key = "#spuId")
    public void toTopBySpuId(Long spuId) {
        spuMapper.toTopBySpuId(spuId);
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SPU_KEY, key = "#spuId")
    public void removeSpuCacheBySpuId(Long spuId) {

    }

    @Override
    public List<Long> listSpuIdsByShopIds(List<Long> shopIds) {
        if (CollUtil.isEmpty(shopIds)) {
            return new ArrayList<>(0);
        }
        return spuMapper.getSpuIdsByShopIds(shopIds);
    }

    @Override
    public void removeBrandOfSpu(Long brandId) {
        spuMapper.removeBrandOfSpu(brandId);
    }

    @Override
    public ServerResponseEntity<Void> checkSpuStatus(List<Long> spuIds) {
        List<SpuVO> spuList = spuMapper.listSpuStatusByIds(spuIds);
        spuList.forEach(spuVO -> {
            if (!Objects.equals(spuVO.getStatus(), StatusEnum.ENABLE.value())) {
                throw new LuckException(ResponseEnum.SPU_STATUS_ERROR, spuVO.getSpuId());
            }
        });
        return ServerResponseEntity.success();
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void batchOffile(OfflineHandleEventDTO offlineHandleEventDto) {
        List<SpuVO> spuList = spuMapper.listSpuStatusByIds(offlineHandleEventDto.getHandleIds());
        ProductLangUtil.spuList(spuList);
        if (CollUtil.isEmpty(spuList)) {
            throw new LuckException(ResponseEnum.DATA_ERROR);
        }
        List<OfflineHandleEventDTO> offlineHandleEventList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        List<Long> spuIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (SpuVO spuVO : spuList) {
            //如果是供应商品 给代销商品增加供应商品变更值
            if (Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.YES.value())) {
                List<Long> spuIdList = spuMapper.getSupIdListBySupplierId(spuVO.getSpuId());
                if (CollUtil.isNotEmpty(spuIdList)) {
                    spuMapper.batchChangeSynUpdate(spuIdList, IsSynUpdate.NO_CHANGE.value());
                }
            }
            if (!Objects.equals(spuVO.getStatus(), SpuStatus.OFF_SHELF.value()) && !Objects.equals(spuVO.getStatus(), SpuStatus.PUT_SHELF.value())) {
                continue;
            }
            OfflineHandleEventDTO offlineHandleEvent = new OfflineHandleEventDTO();
            //设置sysType
            if (Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.NO.value()) || Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.CONSIGNMENT.value())) {
                offlineHandleEvent.setSysType(SysTypeEnum.MULTISHOP.value());
            }
            if (Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.YES.value())) {
                offlineHandleEvent.setSysType(SysTypeEnum.SUPPLIER.value());
            }
            offlineHandleEvent.setHandleId(spuVO.getSpuId());
            offlineHandleEvent.setHandleType(OfflineHandleEventType.PROD.getValue());
            offlineHandleEvent.setOfflineReason(offlineHandleEventDto.getOfflineReason());
            spuIds.add(spuVO.getSpuId());
            offlineHandleEventList.add(offlineHandleEvent);
        }
        if (CollUtil.isEmpty(offlineHandleEventList)) {
            throw new LuckException("您选择的商品数据已发生改变，请刷新后重试");
        }

        // 批量新增下线事件记录
        ServerResponseEntity<Void> responseEntity = offlineHandleEventFeignClient.batchSave(offlineHandleEventList);
        if (!Objects.equals(responseEntity.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(responseEntity.getMsg());
        }
        // 批量更新活动状态为下线状态
        batchChangeSpuStatus(spuIds, StatusEnum.OFFLINE.value());
        //批量发送商品下架消息给商家或供应商：商品xxx已被平台或供应商下架，点击去查看
        List<Long> supplierIds = spuList.stream().filter(s -> Objects.equals(s.getSupplierSpuType(), SupplierSpuType.YES.value())).map(SpuVO::getSupplierId).collect(Collectors.toList());
        ServerResponseEntity<List<SupplierApiDetailVO>> supplierResp = supplierDetailFeignClient.listSupplierDetailBySupplierIds(supplierIds);
        Map<Long, String> supplierNameMap = supplierResp.getData().stream().collect(Collectors.toMap(SupplierApiDetailVO::getSupplierId, SupplierApiDetailVO::getSupplierName));
        List<SendNotifyBO> notifyList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (SpuVO spuVO : spuList) {
            SendNotifyBO sendNotifyBO = new SendNotifyBO();
            if (Objects.nonNull(spuVO.getSupplierSpuType()) && Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.YES.value())) {
                sendNotifyBO.setShopId(null);
                sendNotifyBO.setSupplierId(spuVO.getSupplierId());
            } else {
                sendNotifyBO.setShopId(spuVO.getShopId());
                sendNotifyBO.setSupplierId(null);
            }
            sendNotifyBO.setSendType(Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.YES.value()) ? SendTypeEnum.PRODUCT_OFFLINE_TO_SUPPLIER.getValue() : SendTypeEnum.PRODUCT_OFFLINE.getValue());
            sendNotifyBO.setSpuId(spuVO.getSpuId());
            sendNotifyBO.setSpuName(spuVO.getName());
            sendNotifyBO.setSupplierName(Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.YES.value()) ? supplierNameMap.get(spuVO.getSupplierId()) : null);
            notifyList.add(sendNotifyBO);
        }

        SendStatus sendStockStatus = sendProductNotifyToShopTemplate.syncSend(RocketMqConstant.SEND_PRODUCT_NOTIFY_TO_SHOP_TOPIC, new GenericMessage<>(notifyList)).getSendStatus();
        if (!Objects.equals(sendStockStatus, SendStatus.SEND_OK)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }

    @Override
    public List<SpuSimpleBO> listSimple(SpuSimpleBO spuSimpleBO) {
        return spuMapper.listSimple(spuSimpleBO);
    }

    @Override
    public List<SpuSimpleBO> listSimples(SpuSimpleBO spuSimpleBO) {
        return spuMapper.listSimples(spuSimpleBO);
    }

    private Boolean verifySpuNum(Date currentTime, ProductSearchDTO productSearchDTO, Long spuNum) {
        if (Objects.isNull(spuNum)) {
            spuNum = spuMapper.getAllSpuNum(currentTime);
        }
        ServerResponseEntity<EsPageVO<SpuAdminVO>> responseEntity = searchSpuFeignClient.adminPage(productSearchDTO);
        if (!responseEntity.isSuccess()) {
            throw new LuckException(responseEntity.getMsg());
        }
        Long total = responseEntity.getData().getTotal();
        // 数量相同，不需要更新
        return Objects.equals(spuNum, total);
    }


    private void checkShopStatusIsOpen(Long shopId) {
        Date now = new Date();
        ServerResponseEntity<EsShopDetailBO> shopDetailRes = shopDetailFeignClient.getShopByShopId(shopId);
        if (!shopDetailRes.isSuccess()) {
            throw new LuckException(shopDetailRes.getMsg());
        }
        EsShopDetailBO esShopDetailBO = shopDetailRes.getData();
        if (Objects.equals(esShopDetailBO.getShopStatus(), ShopStatus.OPEN.value())) {
            return;
        }
        if (Objects.equals(esShopDetailBO.getShopStatus(), ShopStatus.OFFLINE.value()) || Objects.equals(esShopDetailBO.getShopStatus(), ShopStatus.OFFLINE_AWAIT_AUDIT.value())) {
            throw new LuckException("店铺已下线");
        }
        if (Objects.equals(esShopDetailBO.getShopStatus(), ShopStatus.STOP.value())) {
            if (now.compareTo(esShopDetailBO.getContractStartTime()) < 0) {
                throw new LuckException("店铺未开始营业");
            } else {
                throw new LuckException("店铺已停止营业");
            }
        }
    }

    private void checkSameCity(SpuVO spuVO) {
        SpuVO.DeliveryModeVO deliveryModeVO = Json.parseObject(spuVO.getDeliveryMode(), SpuVO.DeliveryModeVO.class);
        // 商品不支持同城配送
        if (!deliveryModeVO.getHasCityDelivery()) {
            spuVO.setCityDelivery(false);
            return;
        }
        ServerResponseEntity<SameCityVO> responseEntity = sameCityFeignClient.getSameCityByShopId(spuVO.getShopId());
        if (!responseEntity.isSuccess()) {
            spuVO.setCityDelivery(false);
        }
        SameCityVO sameCityVO = responseEntity.getData();
        spuVO.setCityDelivery(!Objects.isNull(sameCityVO) && sameCityVO.getStatus() != 0);
    }

    /**
     * 校验spu新增或更新信息
     *
     * @param spuDTO
     * @param spuDb
     * @param saveProd true: 保存，false: 更新
     */
    private void checkSaveOrUpdateInfo(SpuDTO spuDTO, SpuVO spuDb, boolean saveProd) {
        Long tenantId = AuthUserContext.get().getTenantId();
        Integer sysType = AuthUserContext.get().getSysType();
        if (!Objects.equals(Constant.PLATFORM_SHOP_ID, tenantId) && Objects.isNull(spuDTO.getShopCategoryId()) && Objects.equals(sysType, SysTypeEnum.MULTISHOP.value())) {
            throw new LuckException("店铺分类不能为空");
        }
        if (Objects.isNull(spuDTO.getCategoryId()) && !Objects.equals(spuDTO.getSpuType(), SpuType.SCORE.value())) {
            throw new LuckException("平台分类不能为空");
        }
        if (saveProd) {
            checkShopStatus(spuDTO, tenantId, sysType);
            checkCategory(spuDTO, tenantId, sysType);
        }
        // spu编码校验（编码为空or编码重复，自动生成新的编码）
        List<String> spuCodes = spuMapper.listSpuCodes(tenantId, sysType, spuDTO.getSpuId());
        if (ObjectUtils.isEmpty(spuDTO.getSpuCode())
                || spuCodes.contains(spuDTO.getSpuCode())) {
            String spuCode;
            do {
                spuCode = StringUtils.join("P", segmentManager.getSegmentCode(DistributedIdKey.tmerclub_PRODUCT_SKU_CODE));
            } while (spuCodes.contains(spuCode));
            spuDTO.setSpuCode(spuCode);
        }
        checkShopCategory(spuDTO, tenantId, sysType);
        checkBrand(spuDTO, tenantId, sysType);
        //校验运费模板
        if (Objects.nonNull(spuDTO.getDeliveryTemplateId())) {
            //发货方式为仓库发货才校验
            if (Objects.nonNull(spuDTO.getSupplierDeliveryType()) && Objects.equals(spuDTO.getSupplierDeliveryType(), SupplierDeliveryType.SHOP_DELIVERY.value())) {
                ServerResponseEntity<List<ShopTransportVO>> response = deliveryFeignClient.listTransportByShopId(spuDTO.getShopId());
                if (!Objects.equals(response.getCode(), ResponseEnum.OK.value())) {
                    throw new LuckException(response.getMsg());
                }
                Set<Long> transportIds = response.getData().stream().map(ShopTransportVO::getTransportId).collect(Collectors.toSet());
                if (!transportIds.contains(spuDTO.getDeliveryTemplateId())
                        && spuDTO.getDeliveryTemplateId() != 0L && spuDTO.getDeliveryTemplateId() != -1L) {
                    throw new LuckException("产品运费模板不存在");
                }
            }
        }
        if (Objects.isNull(spuDTO.getSeq())) {
            spuDTO.setSeq(0);
        }
        if (Objects.isNull(spuDTO.getBrandId())) {
            spuDTO.setBrandId(0L);
        }
        if (Objects.isNull(spuDTO.getVideo())) {
            spuDTO.setVideo("");
        }
        List<String> partyCodes = skuService.listSkuPartyCodesByShopId(tenantId, sysType, spuDTO.getSpuId());
        for (SkuDTO sku : spuDTO.getSkuList()) {
            // 生成商品编码
            if (StrUtil.isBlank(sku.getPartyCode())) {
                String partyCode = StringUtils.join("P", segmentManager.getSegmentCode(DistributedIdKey.tmerclub_PRODUCT_SKU_CODE));
                sku.setPartyCode(partyCode);
            }
            if (CollUtil.isNotEmpty(partyCodes)) {
                if (partyCodes.contains(sku.getPartyCode())) {
                    // 商品编码已存在,生成新的
                    String partyCode = StringUtils.join("P", segmentManager.getSegmentCode(DistributedIdKey.tmerclub_PRODUCT_SKU_CODE));
                    sku.setPartyCode(partyCode);
                } else {
                    partyCodes.add(sku.getPartyCode());
                }
            }
        }
        List<GiveawaySpuVO> giveawaySpuList = giveawaySpuMapper.getBySpuId(spuDTO.getSpuId());
        if (CollectionUtils.isNotEmpty(giveawaySpuList) && !Objects.equals(spuDTO.getPreSaleType(), PreSaleType.DISABLE.value())) {
            // 参与赠品活动的商品不能添加为定金预售商品
            throw new LuckException("参与赠品活动的赠品不能添加为预售商品");
        }
        if (Objects.equals(spuDTO.getSpuMold(), SpuMold.VIRTUAL.value()) || Objects.equals(spuDTO.getSpuType(), SpuType.ACTIVE.value())) {
            spuDTO.setDeliveryTemplateId(null);
            spuDTO.setDeliveryAmount(null);
        }
        spuDTO.setIsAllEntity(0);

        // 检查一下组合商品情况或者关联组合商品的情况
        checkComboSpuOrRelatedCombo(spuDTO,spuDb,saveProd);
    }

    /**
     * 组合商品关联的子商品状态变更,导致组合商品下架:
     * 1.关联子商品信息不变
     * 1.1 子商品下架
     * 1.2 子商品由商家发货转为供应商发货(商家商品)
     * 1.3 子商品变成预售商品
     * 1.4 sku禁用
     * 2.关联子商品信息删除
     * 2.1 删除子商品或者规格
     *
     * @param spuDTO
     * @param spuDb
     * @param saveProd
     */
    private void checkComboSpuOrRelatedCombo(SpuDTO spuDTO, SpuVO spuDb, boolean saveProd) {
        if(!Objects.equals(spuDTO.getSpuMold(),SpuMold.COMBO.value())) {
            // 如果是新增的普通商品不需要判断
            if(saveProd){
                return;
            }
            Set<Long> handleSkuIds = new HashSet<>();
            Set<Long> deleteSkuIds = new HashSet<>();
            List<SkuDTO> skuList = spuDTO.getSkuList().stream().filter(skuDTO -> Objects.nonNull(skuDTO.getSkuId())).toList();
            Map<Long, SkuDTO> skuMap = skuList.stream().collect(Collectors.toMap(SkuDTO::getSkuId, skuVO -> skuVO));
            Set<Long> skuIds = skuList.stream().map(SkuDTO::getSkuId).collect(Collectors.toSet());
            boolean checkSupplierSpu = !Objects.equals(spuDTO.getShopId(), -1L) && Objects.equals(spuDTO.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())
                    && Objects.equals(spuDb.getSupplierDeliveryType(), SupplierDeliveryType.SHOP_DELIVERY.value());
            boolean checkPreSale = !Objects.equals(spuDTO.getPreSaleType(), -1);
            if(checkSupplierSpu || checkPreSale) {
                handleSkuIds.addAll(skuIds);
            }
            // 获取修改前的sku信息
            List<SkuVO> oldSkuList = skuService.listSkuWithAttrBySpuId(spuDTO.getSpuId());
            Map<Long, SkuVO> skuDbMap = oldSkuList.stream().collect(Collectors.toMap(SkuVO::getSkuId, skuVO -> skuVO));
            for (Long skuIdDb : skuDbMap.keySet()) {
                // 修改时如果不存在数据库的sku,则表示已经删除,进行下架和删除关联
                if(!skuMap.containsKey(skuIdDb)){
                    deleteSkuIds.add(skuIdDb);
                    Long priceFee = skuDbMap.get(skuIdDb).getPriceFee();
                    continue;
                }
                // 如果数据库是启用,修改时变成禁用,则进行下架
                if(Objects.equals(skuDbMap.get(skuIdDb).getStatus(),StatusEnum.ENABLE.value()) && Objects.equals(skuMap.get(skuIdDb),StatusEnum.DISABLE.value())){
                    handleSkuIds.add(skuIdDb);
                }
            }
            handleSkuIds.addAll(deleteSkuIds);
            if(CollectionUtil.isNotEmpty(handleSkuIds)) {
                // 下架关联的组合商品
                List<Long> spuIds = skuComboService.getCombSpusByComboSpuIds(null, new ArrayList<>(handleSkuIds));
                if (CollUtil.isNotEmpty(spuIds)) {
                    batchChangeSpuStatus(spuIds, StatusEnum.DISABLE.value());
                }
            }
            if(CollectionUtil.isNotEmpty(deleteSkuIds)) {
                // 删除关联的组合商品信息
                skuComboService.deleteByComboSkuIds(deleteSkuIds.stream().toList());
            }
        }
        if(!Objects.equals(spuDTO.getSpuMold(),SpuMold.COMBO.value())){
            return;
        }
        // 组合商品不能选择其他组合商品一起组合
        Set<Long> spuIds = new HashSet<>();
        for (SkuDTO skuDTO : spuDTO.getSkuList()) {
            spuIds.addAll(skuDTO.getSkuComboList().stream().map(SkuComboDTO::getComboSpuId).collect(Collectors.toSet()));
        }
        List<SpuVO> spuList = spuMapper.listSpuBySpuIds(spuIds.stream().toList());
        List<SpuVO> comboSpuList = spuList.stream().filter(spuVO -> Objects.equals(spuVO.getSpuMold(), SpuMold.COMBO)).toList();
        for (SpuVO spuVO : spuList) {
            if (Objects.equals(spuVO.getSpuMold(), SpuMold.COMBO.value())) {
                throw new LuckException("组合商品不能选择其他组合商品一起组合");
            }
            // 组合商品不能为(预售,供应商发货(商家的组合商品))类型
            if (!Objects.equals(spuVO.getPreSaleType(), -1)) {
                throw new LuckException("组合商品的关联商品不能为预售类型");
            }
            if (!Objects.equals(spuVO.getShopId(), -1L) && Objects.equals(spuVO.getSupplierDeliveryType(),SupplierDeliveryType.SUPPLIER_DELIVERY.value())) {
                throw new LuckException("组合商品的关联商品发货方式不能为供应商发货");
            }
        }
        // 判断一下是否为全实物商品,用于赠品操作
        List<SpuVO> noRealSpuList = spuList.stream().filter(spuVO -> !Objects.equals(spuVO.getSpuMold(), SpuMold.REAL.value())).toList();
        spuDTO.setIsAllEntity(CollectionUtil.isNotEmpty(noRealSpuList) ? 0 : 1);
    }

    private void checkBrand(SpuDTO spuDTO, Long tenantId, Integer sysType) {
        // 校验品牌是否可用
        if (Objects.nonNull(spuDTO.getBrandId()) && !Objects.equals(spuDTO.getBrandId(), 0L)) {
            BrandVO brandVO = brandMapper.getByBrandId(spuDTO.getBrandId());
            if (Objects.isNull(brandVO) || !Objects.equals(brandVO.getStatus(), StatusEnum.ENABLE.value())) {
                throw new LuckException("当前选择的品牌已下架或已删除，请重新选择品牌");
            }
            if (!Objects.equals(tenantId, Constant.PLATFORM_SHOP_ID)) {
                if (!Objects.equals(spuDTO.getSupplierSpuType(), SupplierDeliveryType.SHOP_DELIVERY.value())) {
                    // 判断当前店铺是否可以使用该品牌
                    int categoryBrandCount = categoryBrandService.countByBrandIdAndCategoryId(spuDTO.getBrandId(), spuDTO.getCategoryId());
                    if (categoryBrandCount == 0) {
                        int signingCount = brandShopService.countByShopIdAndBrandId(tenantId, spuDTO.getBrandId(), sysType);
                        if (signingCount == 0) {
                            throw new LuckException("当前选择的品牌签约关系已失效，请重新选择品牌");
                        }
                    }
                }
            }
        }
    }

    private void checkShopCategory(SpuDTO spuDTO, Long tenantId, Integer sysType) {
        // 校验店铺分类是否可用
        if (!Objects.equals(Constant.PLATFORM_SHOP_ID, tenantId) && Objects.equals(sysType, SysTypeEnum.MULTISHOP.value()) && Objects.nonNull(spuDTO.getShopCategoryId())) {
            CategoryVO shopCategory = categoryMapper.getById(spuDTO.getShopCategoryId());
            if (Objects.isNull(shopCategory) || !Objects.equals(shopCategory.getStatus(), StatusEnum.ENABLE.value())) {
                throw new LuckException("当前选择的店铺分类已下架或已删除， 请重新选择店铺分类");
            }
        }
        // 校验供应商分类是否可用
        if (!Objects.equals(Constant.PLATFORM_SHOP_ID, tenantId) && Objects.equals(sysType, SysTypeEnum.SUPPLIER.value()) && Objects.nonNull(spuDTO.getSupplierCategoryId())) {
            CategoryVO supplierCategory = categoryMapper.getById(spuDTO.getSupplierCategoryId());
            if (Objects.isNull(supplierCategory) || !Objects.equals(supplierCategory.getStatus(), StatusEnum.ENABLE.value())) {
                throw new LuckException("当前选择的供应商分类已下架或已删除， 请重新选择供应商分类");
            }
        }
    }

    private void checkCategory(SpuDTO spuDTO, Long tenantId, Integer sysType) {
        // 校验平台分类是否处于上架状态
        CategoryVO platformCategory = categoryMapper.getById(spuDTO.getCategoryId());
        // 积分商品不需要分类
        if (!Objects.equals(spuDTO.getSpuType(), SpuType.SCORE.value())) {
            //如果是下架了分类，就提示 该平台分类已被下线，无法上架该商品
            //如果是签约丢了，就提示 您已取消与该商品类型的签约，请重新签约该商品类型方可上架
            if (Objects.isNull(platformCategory) || !Objects.equals(platformCategory.getStatus(), StatusEnum.ENABLE.value())) {
                throw new LuckException("该平台分类已被下线，无法上架该商品");
            }
            if (!Objects.equals(tenantId, Constant.PLATFORM_SHOP_ID)) {
                // 判断当前店铺是否可用使用该平台分类
                int signingCount = categoryShopMapper.countByShopIdAndCategoryId(tenantId, spuDTO.getCategoryId(), sysType);
                if (signingCount == 0) {
                    throw new LuckException("您已取消与该商品类型的签约，请重新签约该商品类型方可上架");
                }
            }
        } else {
            spuDTO.setCategoryId(0L);
        }
    }

    private void checkShopStatus(SpuDTO spuDTO, Long tenantId, Integer sysType) {
        if (Objects.equals(sysType, SysTypeEnum.MULTISHOP.value())) {
            // 发布商品时，需要根据店铺或供应商状态判断是否可以发布商品
            ServerResponseEntity<EsShopDetailBO> shopRequest = shopDetailFeignClient.getShopByShopId(tenantId);
            EsShopDetailBO shopDetail = shopRequest.getData();
            if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE.value())) {
                throw new LuckException("店铺处于违规下线状态，不能发布新商品");
            }
            if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE_AWAIT_AUDIT.value())) {
                throw new LuckException("店铺上线申请待审核中，不能发布新商品");
            }
            if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.STOP.value())) {
                logger.info("店铺处于停止状态，商品状态设置为下架");
                spuDTO.setStatus(StatusEnum.DISABLE.value());
            }
        } else if (Objects.equals(sysType, SysTypeEnum.SUPPLIER.value())) {
            ServerResponseEntity<SupplierDetailBO> supplierRequest = supplierDetailFeignClient.getSupplierBySupplierId(tenantId);
            SupplierDetailBO supplierDetail = supplierRequest.getData();
            if (Objects.equals(supplierDetail.getSupplierStatus(), SupplierStatus.OFFLINE.value())) {
                throw new LuckException("供应商处于违规下线状态，不能发布新商品");
            }
            if (Objects.equals(supplierDetail.getSupplierStatus(), SupplierStatus.OFFLINE_AWAIT_AUDIT.value())) {
                throw new LuckException("供应商上线申请待审核中，不能发布新商品");
            }
            if (Objects.equals(supplierDetail.getSupplierStatus(), SupplierStatus.STOP.value())) {
                logger.info("供应商处于停止状态，商品状态设置为下架");
                spuDTO.setStatus(StatusEnum.DISABLE.value());
            }
        }
    }

    @Override
    public Integer isCommissionByShopIdAndSpuId(Long shopId, Long supplierSpuId) {
        return spuMapper.isCommissionByShopIdAndSpuId(shopId, supplierSpuId);
    }

    @Override
    public SupplierSpuVo getSupplierInfoBySpuId(Long spuId, Long shopId) {
        SupplierSpuVo supplierSpuVo = new SupplierSpuVo();
        SpuVO spu = spuMapper.getBySpuId(spuId);
        //编辑返回数据
        supplierSpuVo.setSupplierSpuId(spu.getSpuId());
        supplierSpuVo.setMainImgUrl(spu.getMainImgUrl());
        supplierSpuVo.setImgUrls(spu.getImgUrls());
        supplierSpuVo.setSellingPoint(spu.getSellingPoint());
        supplierSpuVo.setVideo(spu.getVideo());
        supplierSpuVo.setMeasureUnit(spu.getMeasureUnit());
        supplierSpuVo.setSpuCode(spu.getSpuCode());
        supplierSpuVo.setCategoryId(spu.getCategoryId());
        supplierSpuVo.setShopCategoryId(spu.getShopCategoryId());
        supplierSpuVo.setSupplierId(spu.getSupplierId());
        supplierSpuVo.setSpuLangList(spu.getSpuLangList());
        supplierSpuVo.setDetail(spu.getDetail());
        supplierSpuVo.setDetailList(spu.getDetailList());
        supplierSpuVo.setBrandId(spu.getBrandId());
        supplierSpuVo.setHasSkuImg(spu.getHasSkuImg());
        //返回数据时根据智能代销设置销售价
        //获取店铺的代销设置
        ServerResponseEntity<ShopSubstituteSalesVO> sales = shopSubstituteSalesFeignClient.getByShopSubstituteSalesId(shopId);
        ShopSubstituteSalesVO data = sales.getData();
        //sku信息
        List<SkuVO> skuVOList = skuService.listSkuAllInfoBySpuId(spuId,spu, false);
        for (SkuVO skuVO : skuVOList) {
            List<SkuLangVO> skuLang = skuLangService.getBySkuId(skuVO.getSkuId());
            skuVO.setSkuLangList(skuLang);
            //设置供货价
            skuVO.setSupplyPriceFee(skuVO.getPriceFee());
            if (!Objects.isNull(data)) {
                //代销设置为智能设价时,计算代销商品售价
                if (data.getSalesType() != 1) {
                    long price = 0L;
                    if (data.getSalesPriceType() == 0) {
                        //按比例加价
                        price = PriceUtil.divideByBankerRounding(spu.getPriceFee() * data.getSalesPrice(), 100) + spu.getPriceFee();
                    }
                    if (data.getSalesPriceType() == 1) {
                        //按固定数值加价
                        price = skuVO.getPriceFee() + data.getSalesPrice();
                    }
                    skuVO.setPriceFee(price);
                }
            }
            //判断sku状态是否可售
            skuVO.setIsSell(SkuIsSell.NO_SELL.value());
            if (skuVO.getStatus() == 1) {
                skuVO.setIsSell(SkuIsSell.CAN_SELL.value());
            }
            if (skuVO.getStatus() == 0) {
                skuVO.setIsSell(SkuIsSell.NO_SELL.value());
            }
            skuVO.setStockWarning(0L);
        }
        supplierSpuVo.setSkus(skuVOList);
        return supplierSpuVo;
    }

    @Override
    public void soldOutSpu(Long skuId, Long supplierPrice) {
        SkuVO skuBySkuId = skuMapper.getSkuBySkuId(skuId);
        SpuVO bySpuId = spuMapper.getBySpuId(skuBySkuId.getSpuId());
        if (Objects.equals(bySpuId.getSupplierSpuType(), SupplierSpuType.YES.value())) {
            //查询代销商品
            List<Spu> supplierSup = spuMapper.getSupplierSupIdBySkuId(skuId);
            for (int i = 0; i < supplierSup.size(); i++) {
                Long shopId = supplierSup.get(i).getShopId();
                //获取代销商品sku信息
                Long spuSkuId = skuMapper.getSkuIdBySpuIdAndSupplierSkuId(supplierSup.get(i).getSpuId(), skuId);
                //过滤掉没有设置手动设价的店铺
                ServerResponseEntity<ShopSubstituteSalesVO> salesType = shopSubstituteSalesFeignClient.getByShopSubstituteSalesId(shopId);
                if (!Objects.isNull(salesType.getData())) {
                    //智能设价 商家发货的代销商品不需要修改价格
                    if (Objects.equals(salesType.getData().getSalesType(), 0) && Objects.equals(supplierSup.get(i).getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())) {
                        //重新计算售价
                        //智能设价计算售价
                        long priceFee = 0L;
                        if (salesType.getData().getSalesPriceType() == 0) {
                            //按比例加价
                            priceFee = PriceUtil.divideByBankerRounding(supplierPrice * salesType.getData().getSalesPrice(), 10000) + supplierPrice;
                        }
                        if (salesType.getData().getSalesPriceType() == 1) {
                            //按固定数值加价
                            priceFee = supplierPrice + salesType.getData().getSalesPrice();
                        }
                        //更新sku
                        Sku sku = new Sku();
                        sku.setSkuId(spuSkuId);
                        sku.setPriceFee(priceFee);
                        sku.setMarketPriceFee(priceFee);
                        skuMapper.update(sku);
                        break;
                    }
//                    //没有设置供货价高于代销价时自动下架的移除
//                    if (Objects.equals(salesType.getData().getAutomaticOff(), 0)) {
//                        supplierSup.remove(i);
//                        break;
//                    }
//                    //获取代销商品sku代销价
//                    Long spuId = supplierSup.get(i).getSpuId();
//                    Long priceFee = skuMapper.getPriceFeeBySpuIdAndSupplierSkuId(spuId, skuId);
//                    //下架商品
//                    Spu spu = new Spu();
//                    spu.setSpuId(spuId);
//                    spu.setStatus(SpuStatus.OFF_SHELF.value());
//                    spuMapper.update(spu);
//                }
                }
            }
        }
    }

    @Override
    public List<Long> importSupplierSpu(List<Long> supplierSpuId) {
        List<Long> spuIdList = new ArrayList<>();
        for (Long aLong : supplierSpuId) {
            spuIdList.add(importSupplierSpuService.importSpu(aLong, AuthUserContext.get().getTenantId(), AuthUserContext.get().getSysType(),
                    AuthUserContext.get().getUserId(), false));
        }
        return spuIdList;
    }


    @Override
    public Long setPriceFee(SkuVO skuVO) {
        Long shopId = AuthUserContext.get().getTenantId();
        //获取商家代销设置
        ServerResponseEntity<ShopSubstituteSalesVO> salesType = shopSubstituteSalesFeignClient.getByShopSubstituteSalesId(shopId);
        ShopSubstituteSalesVO shopSubstituteSalesVO = salesType.getData();
        if (!Objects.isNull(shopSubstituteSalesVO)) {
            if (shopSubstituteSalesVO.getSalesType() == 0) {
                //智能设价计算售价
                long price = 0L;
                if (shopSubstituteSalesVO.getSalesPriceType() == 0) {
                    //按比例加价
                    price = PriceUtil.divideByBankerRounding(skuVO.getPriceFee() * shopSubstituteSalesVO.getSalesPrice(), 10000) + skuVO.getPriceFee();
                }
                if (shopSubstituteSalesVO.getSalesPriceType() == 1) {
                    //按固定数值加价
                    price = skuVO.getPriceFee() + shopSubstituteSalesVO.getSalesPrice();
                }
                return price;
            }
        }
        return 0L;
    }


    @Override
    public SpuVO getSpuByShopIdAndSupplierSpuId(Long shopId, Long supplierSpuId) {
        return spuMapper.getSpuByShopIdAndSupplierSpuId(shopId, supplierSpuId);
    }

    @Override
    public List<SpuVO> supplierSpuList(SpuPageSearchDTO spu) {
        return spuMapper.supplierSpuList(spu);
    }

    @Override
    public List<SpuVO> getSpuIdsBySupplierIdAndSupplierSpuType(Long supplierId, Date createTime, Integer supplierSpuType) {
        return spuMapper.getSpuIdsBySupplierIdAndSupplierSpuType(supplierId, createTime, supplierSpuType);
    }

    @Override
    public List<SpuVO> listMerchantSpuIdsBySupplierId(Long supplierId) {
        return spuMapper.listMerchantSpuIdsBySupplierId(supplierId);
    }

    @Override
    public List<SpuVO> listSpuByShopIdAndSupplierSpuId(Long shopId, List<Long> supplierSpuIds) {
        return spuMapper.listSpuByShopIdAndSupplierSpuId(shopId, supplierSpuIds);
    }

    @Override
    public void soldOutSpuBySpu(Long spuId, Long price, Long marketPriceFee) {
        List<SpuVO> spuVos = spuMapper.listSpuBySupplierSpuId(spuId);
        if (spuVos.size() == 0) {
            return;
        }
        // 获取商家代销设置
        List<Long> shopIds = spuVos.stream().map(SpuVO::getShopId).collect(Collectors.toList());
        ServerResponseEntity<List<ShopSubstituteSalesVO>> listServerResponseEntity = shopSubstituteSalesFeignClient.shopSubstituteSalesList(shopIds);
        if (!listServerResponseEntity.isSuccess()) {
            throw new LuckException(listServerResponseEntity.getMsg());
        }
        Map<Long, ShopSubstituteSalesVO> salesMap = listServerResponseEntity.getData().stream().collect(Collectors.toMap(ShopSubstituteSalesVO::getShopId, s -> s));
        for (SpuVO spuVo : spuVos) {
            ShopSubstituteSalesVO shopSubstituteSalesVO = salesMap.get(spuVo.getShopId());
            if (Objects.isNull(shopSubstituteSalesVO)) {
                continue;
            }
            // 手动设价不执行
            if (Objects.equals(shopSubstituteSalesVO.getSalesType(), SalesType.MANUAL_OPERATION_PRICE.value())) {
                continue;
            }
            long priceFee = 0L;
            if (Objects.equals(shopSubstituteSalesVO.getSalesPriceType(), SalesPriceType.PROPORTION_PRICE.value())) {
                // 按比例加价
                priceFee = PriceUtil.divideByBankerRounding(price * shopSubstituteSalesVO.getSalesPrice(), 10000) + price;
            }
            if (Objects.equals(shopSubstituteSalesVO.getSalesPriceType(), SalesPriceType.FIXED_NUMBER_PRICE.value())) {
                // 按固定数值加价
                priceFee = price + shopSubstituteSalesVO.getSalesPrice();
            }
            Spu spu = new Spu();
            spu.setSpuId(spuVo.getSpuId());
            spu.setPriceFee(priceFee);
            spu.setMarketPriceFee(marketPriceFee);
            spuMapper.update(spu);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void offlineSpuBySupplierId(Long supplierId) {
        List<SpuVO> supplierVoList = spuMapper.getSupplierSpuBySupplierId(supplierId, StatusEnum.ENABLE.value());
        if (CollectionUtil.isEmpty(supplierVoList)) {
            return;
        }
        spuMapper.offlineSpuBySupplierId(supplierId);
        List<Long> supplierSpuIdList = supplierVoList.stream().map(SpuVO::getSpuId).collect(Collectors.toList());
        List<Long> spuIdList = spuMapper.batchSupIdListBySupplierId(supplierSpuIdList);
        if (CollectionUtil.isNotEmpty(spuIdList)) {
            spuMapper.batchChangeSynUpdate(spuIdList, IsSynUpdate.NO_CHANGE.value());
        }
        // 查询出秒杀or团购的商品进行下线
        // 下线掉关联商品的活动
        // 下面这个方法查不到正常状态的商品了，所以需要把修改后的商品状态传过去
//        spuOfflineService.offlineSpuStatusAndActivity(3, null, shopId, null, StatusEnum.DISABLE.value());
    }

    @Override
    public List<SpuVO> listSpuBySupplierSpuId(Long supplierSpuId) {
        return spuMapper.listSpuBySupplierSpuId(supplierSpuId);
    }

    @Override
    public List<SpuVO> getSpuIsSynUpdate(List<Long> spuIds) {
        List<SpuVO> spuIsSynUpdate = spuMapper.getSpuIsSynUpdate(spuIds);
        // 获取供应商商品库存
        spuIds = spuIsSynUpdate.stream().map(spuVO -> Objects.isNull(spuVO.getSupplierSpuId()) ? spuVO.getSpuId() : spuVO.getSupplierSpuId()).collect(Collectors.toList());
        spuStockService.setSpuStock(spuIsSynUpdate);
        return spuIsSynUpdate;
    }

    @Override
    public List<Long> getSupIdListBySupplierId(Long supplierId) {
        return spuMapper.getSupIdListBySupplierId(supplierId);
    }

    @Override
    public void batchChangeSynUpdate(List<Long> spuIds, Integer isSynUpdate) {
        if (CollUtil.isEmpty(spuIds)) {
            return;
        }
        spuMapper.batchChangeSynUpdate(spuIds, isSynUpdate);
    }

    @Override
    public void batchUpdateCommissionSpuDeliverType(List<Long> spuIds, Integer deliverType) {
        if (CollUtil.isEmpty(spuIds)) {
            return;
        }
        spuMapper.batchUpdateCommissionSpuDeliverType(spuIds, deliverType);
    }

    private void offSupplierSendCommissionSpu(SpuDTO spuDTO) {
        //下架商家供应商发货的代销商品
        List<Long> commissionSpuId = spuMapper.getCommissionSpuIdList(spuDTO.getSpuId(), SupplierDeliveryType.SUPPLIER_DELIVERY.value());
        if (CollectionUtil.isNotEmpty(commissionSpuId)) {
            spuMapper.batchChangeSpuStatus(commissionSpuId, SpuStatus.OFF_SHELF.value());
        }
    }

    @Override
    public void supplierSpuUpdateLaterOffSpu(Long supplierSpuId, Integer commissionSpuOffType) {
        if (Objects.equals(commissionSpuOffType, CommissionSpuOffType.ALL.value())) {
            List<Long> commissionSpuIds = spuMapper.getSupIdListBySupplierId(supplierSpuId);
            //下架
            supplierSpuUpdateLaterOperateService.batchChangeSpuStatus(commissionSpuIds, SpuStatus.OFF_SHELF.value(), SysTypeEnum.MULTISHOP.value());
        }

        if (Objects.equals(commissionSpuOffType, CommissionSpuOffType.SUPPLIER_DELIVERY_SPU.value())) {
            List<Long> commissionSpuIds = spuMapper.getCommissionSpuIdList(supplierSpuId, SupplierDeliveryType.SUPPLIER_DELIVERY.value());
            //下架
            batchChangeSpuStatus(commissionSpuIds, SpuStatus.OFF_SHELF.value());
        }

        if (Objects.equals(commissionSpuOffType, CommissionSpuOffType.SHOP_DELIVERY.value())) {
            List<Long> commissionSpuIds = spuMapper.getCommissionSpuIdList(supplierSpuId, SupplierDeliveryType.SHOP_DELIVERY.value());
            //下架
            batchChangeSpuStatus(commissionSpuIds, SpuStatus.OFF_SHELF.value());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateManualPriceCommissionSpuPrice(Long shopId) {
        List<Long> spuIds = spuMapper.getCommissionSpuListByShopId(shopId);
        List<Long> supplierSpuId = spuMapper.getSupplierSpuId(shopId);
        if (CollUtil.isNotEmpty(spuIds)) {
            List<SpuVO> spuVOList = spuMapper.listSpuBySpuIds(spuIds);
            List<SpuVO> supplierSpuList = spuMapper.listSpuBySpuIds(supplierSpuId);
            //获取商家代销设置
            ServerResponseEntity<ShopSubstituteSalesVO> salesType = shopSubstituteSalesFeignClient.getByShopSubstituteSalesId(shopId);
            ShopSubstituteSalesVO shopSubstituteSalesVO = salesType.getData();
            if (!Objects.isNull(shopSubstituteSalesVO) && shopSubstituteSalesVO.getSalesType() == 0) {
                for (SpuVO spuVO : spuVOList) {
                    if (Objects.equals(spuVO.getSupplierDeliveryType(), SupplierDeliveryType.SHOP_DELIVERY.value())) {
                        //商家自行发货的不用执行
                        continue;
                    }
                    //供应商商品
                    SpuVO supplierSpuVO = supplierSpuList.stream().filter(spu -> spu.getSpuId().equals(spuVO.getSupplierSpuId())).findFirst().get();
                    //智能设价计算售价
                    long price = 0L;
                    if (Objects.equals(shopSubstituteSalesVO.getSalesPriceType(), SalesPriceType.PROPORTION_PRICE.value())) {
                        //按比例加价
                        price = PriceUtil.divideByBankerRounding(supplierSpuVO.getPriceFee() * shopSubstituteSalesVO.getSalesPrice(), 10000) + supplierSpuVO.getPriceFee();
                    }
                    if (Objects.equals(shopSubstituteSalesVO.getSalesPriceType(), SalesPriceType.FIXED_NUMBER_PRICE.value())) {
                        //按固定数值加价
                        price = supplierSpuVO.getPriceFee() + shopSubstituteSalesVO.getSalesPrice();
                    }
                    spuVO.setPriceFee(price);
                    //sku信息
                    List<SkuVO> skuVOList = skuMapper.listSkuWithAttrBySpuId(spuVO.getSpuId());
                    List<SkuVO> supplierSkuVOList = skuMapper.listSkuWithAttrBySpuId(supplierSpuVO.getSpuId());
                    List<Sku> skus = new ArrayList<>(Constant.INITIAL_CAPACITY);
                    for (SkuVO skuVO : skuVOList) {
                        //供应商sku
                        SkuVO supplierSkuVO = supplierSkuVOList.stream().filter(sku -> sku.getSkuId().equals(skuVO.getSupplierSkuId())).findFirst().get();
                        //智能设价计算售价
                        long skuPrice = 0L;
                        if (Objects.equals(shopSubstituteSalesVO.getSalesPriceType(), SalesPriceType.PROPORTION_PRICE.value())) {
                            //按比例加价
                            skuPrice = PriceUtil.divideByBankerRounding(supplierSkuVO.getPriceFee() * shopSubstituteSalesVO.getSalesPrice(), 10000) + supplierSkuVO.getPriceFee();
                        }
                        if (Objects.equals(shopSubstituteSalesVO.getSalesPriceType(), SalesPriceType.FIXED_NUMBER_PRICE.value())) {
                            //按固定数值加价
                            skuPrice = supplierSkuVO.getPriceFee() + shopSubstituteSalesVO.getSalesPrice();
                        }
                        skuVO.setPriceFee(skuPrice);
                        Sku sku = BeanUtil.map(skuVO, Sku.class);
                        skus.add(sku);
                    }
                    skuMapper.updateBatch(skus);
                }
                spuMapper.updateBatch(spuVOList);
            }
        }
    }

    @Override
    public List<SpuVO> getBySpuIds(List<Long> spuIds) {
        return spuMapper.getBySpuIds(spuIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchChangeSpuStatusToDisableBySupplierIds(List<Long> supplierIdsToStop) {
        List<Long> spuIds = spuMapper.listSpuIdByShopIdsAndStatus(SysTypeEnum.SUPPLIER.value(), supplierIdsToStop, StatusEnum.ENABLE.value(), null);
        if (CollectionUtil.isNotEmpty(spuIds)) {
            spuMapper.batchChangeSpuStatus(spuIds, StatusEnum.DISABLE.value());
        }
    }

    @Override
    public List<SpuVO> getCommissionSpuList(Long supplierSpuId) {
        return spuMapper.getCommissionSpuListBySupplierDeliver(supplierSpuId);
    }

    @Override
    public void syncUpdateCommissionSpuBrandOrSeq(Long brandId, Integer seq, Long supplierSpuId) {
        List<SpuVO> commissionSpuList = spuMapper.getCommissionSpuList(supplierSpuId);
        if (commissionSpuList.size() == 0) {
            return;
        }
        List<SpuVO> spuVOList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        SpuVO spuVO;
        for (SpuVO spu : commissionSpuList) {
            spuVO = new SpuVO();
            spuVO.setSpuId(spu.getSpuId());
            if (brandId != -1) {
                spuVO.setBrandId(brandId);
            }
            if (seq != -1) {
                spuVO.setSeq(seq);
            }
            spuVOList.add(spuVO);
        }
        spuMapper.updateBatch(spuVOList);
    }

    @Override
    public PageVO<SpuVO> pageSpuSku(PageDTO pageDTO, SpuDTO spuDTO) {
        PageVO<SpuVO> spuPageVO = new PageVO<>();
        // 全部商品查出，对spu进行分页处理
        List<SpuVO> spuVOList = spuMapper.pageSpuSku(spuDTO, I18nMessage.getLang());
        if (CollectionUtil.isEmpty(spuVOList)) {
            spuPageVO.setList(new ArrayList<>(0));
            spuPageVO.setTotal(0L);
            spuPageVO.setPages(0);
            return spuPageVO;
        }
        // 对spu进行分组
        Map<Long, List<SpuVO>> spuMap = spuVOList.stream()
                .collect(Collectors.groupingBy(SpuVO::getSpuId, LinkedHashMap::new, Collectors.toList()));
        // stream流分页取数据
        List<SpuVO> data = new ArrayList<>(Constant.INITIAL_CAPACITY);
        spuMap.entrySet().stream()
                .skip((long) (pageDTO.getPageNum() - 1) * pageDTO.getPageSize())
                .limit(pageDTO.getPageSize())
                .forEach(x -> data.addAll(x.getValue()));
        List<SkuVO> skuList = new ArrayList<>();
        for (SpuVO spuVO : data) {
            skuList.addAll(spuVO.getSkus());
        }
        List<Long> skuIds = skuList.stream().map(SkuVO::getSkuId).collect(Collectors.toList());
        // 获取sku总库存
        Map<Long, SkuStockVO> skuStockMap = skuStockService.mapSkuTotalStockBySkuIds(skuIds);
        for (SkuVO skuVO : skuList) {
            if (!skuStockMap.containsKey(skuVO.getSkuId())) {
                continue;
            }
            SkuStockVO skuStockVO = skuStockMap.get(skuVO.getSkuId());
            skuVO.setStock(skuStockVO.getStock());
            skuVO.setSaleNum(skuStockVO.getSale());
        }
        spuPageVO.setList(data);
        spuPageVO.setTotal(Long.valueOf(String.valueOf(spuMap.keySet().size())));
        spuPageVO.setPages(PageUtil.getPages(spuPageVO.getTotal(), pageDTO.getPageSize()));
        return spuPageVO;
    }

    @Override
    public void voluntarilyImportSupplierSpu(List<SpuVO> spuVOList, Integer sysType, Long userId) {
        for (SpuVO spuVO : spuVOList) {
            SpuVO spu = spuMapper.getSpuByShopIdAndSupplierSpuId(spuVO.getShopId(), spuVO.getSupplierSpuId());
            // 不存在则导入
            if (Objects.isNull(spu)) {
                importSupplierSpuService.importSpu(spuVO.getSupplierSpuId(), spuVO.getShopId(), sysType, userId, true);
            }
        }
    }

    @Override
    public void auditSpu(OfflineHandleEventDTO eventDTO) {
        // 查询商品及其状态
        SpuVO spuVO = spuMapper.getBySpuId(eventDTO.getHandleId());
        if (spuVO == null) {
            throw new LuckException("查找不到该商品信息");
        }
        if (!SpuStatus.PUBLISH_WAIT_AUDIT.value().equals(spuVO.getStatus())) {
            throw new LuckException("商品状态已改变，请刷新页面");
        }
        // 是否审核通过，通过直接修改商品状态；未通过新增一条下线数据，再修改状态
        Spu spu = new Spu();
        spu.setSpuId(eventDTO.getHandleId());
        if (Objects.equals(eventDTO.getStatus(), OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())) {
            spu.setStatus(SpuStatus.PUT_SHELF.value());
        } else if (Objects.equals(eventDTO.getStatus(), OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue())) {
            eventDTO.setStatus(OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue());
            eventDTO.setHandleType(OfflineHandleEventType.PROD.getValue());
            eventDTO.setSysType(SysTypeEnum.MULTISHOP.value());
            eventDTO.setShopId(spuVO.getShopId());
            eventDTO.setOfflineReason(eventDTO.getRefuseReason());
            offlineHandleEventFeignClient.save(eventDTO);
            spu.setIsTop(0);
            spu.setStatus(SpuStatus.PLATFORM_OFF_SHELF.value());
        }
        spuMapper.update(spu);
    }

    @Override
    public Long stockWarningCount(Long supplierId) {
        return spuMapper.stockWarningCount(supplierId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<SpuVO> handleExpireVirtualProd() {
        List<SpuVO> spuVOList = spuMapper.getVirtualSpuList();
        if (CollectionUtils.isEmpty(spuVOList)) {
            return null;
        }
        for (SpuVO spuVO : spuVOList) {
            spuVO.setStatus(SpuStatus.OFF_SHELF.value());
            Spu spu = new Spu();
            spu.setSpuId(spuVO.getSpuId());
            spu.setStatus(spuVO.getStatus());
            updateSpu(spu);
        }
        offlineRelatedComboBySpuIds(spuVOList.stream().map(SpuVO::getSpuId).toList());
        return spuVOList;
    }

    @Override
    public void loadSpuAttrs(SpuVO spuVO) {
        Map<Long, SpuAttrValueVO> attrMap;
        if (CollUtil.isNotEmpty(spuVO.getSpuAttrValues())) {
            attrMap = spuVO.getSpuAttrValues().stream().collect(Collectors.toMap(SpuAttrValueVO::getAttrId, s -> s));
        } else {
            attrMap = new HashMap<>(1);
        }
        List<AttrVO> attrList = attrService.getAttrsByCategoryIdAndAttrType(spuVO.getCategoryId());
        List<SpuAttrValueVO> spuAttrValues = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (AttrVO attrVO : attrList) {
            SpuAttrValueVO spuAttrValueVO = attrMap.get(attrVO.getAttrId());
            SpuAttrValueVO newSpuAttrValue = new SpuAttrValueVO();
            if (Objects.nonNull(spuAttrValueVO)) {
                boolean hasValue = false;
                for (AttrValueVO attrValue : attrVO.getAttrValues()) {
                    if (Objects.equals(attrValue.getAttrValueId(), spuAttrValueVO.getAttrValueId())) {
                        hasValue = true;
                        break;
                    }
                }
                if (hasValue || CollUtil.isEmpty(attrVO.getAttrValues())) {
                    spuAttrValues.add(spuAttrValueVO);
                    continue;
                }
                newSpuAttrValue.setSpuAttrValueId(spuAttrValueVO.getSpuAttrValueId());
            }
            newSpuAttrValue.setAttrId(attrVO.getAttrId());
            newSpuAttrValue.setAttrName(attrVO.getName());
            newSpuAttrValue.setSearchType(attrVO.getSearchType());
            spuAttrValues.add(newSpuAttrValue);
        }
        spuVO.setSpuAttrValues(spuAttrValues);
    }

    @Override
    public void updateSpuByShopId(Long shopId, Integer sysType){
        spuMapper.updateSpuByShopId(shopId, sysType);
    }

    @Override
    public List<SpuVO> listShopSpuBySupplierSpuIds(Long shopId, List<Long> supplierSpuIds) {
        List<SpuVO> spuList = spuMapper.listShopSpuBySupplierSpuIds(shopId, supplierSpuIds);
        ProductLangUtil.spuList(spuList);
        return spuList;
    }

    @Override
    public PageVO<SpuVO> pageStockPointSpu(PageDTO pageDTO, StockPointSkuDTO spuDTO) {
        // 调拨订单查询库存点商品需过滤空库存数据(空库存只有默认仓库会出现)
        if (Objects.equals(spuDTO.getType(), 0)
                && !Objects.isNull(spuDTO.getInStockPointId())) {
            List<Long> emptySkuIds = this.listEmptySkuIds(Collections.singletonList(spuDTO.getStockPointId()));
            if (!CollectionUtils.isEmpty(emptySkuIds)) {
                spuDTO.setNotInSkuIds(emptySkuIds);
            }
        }
        return PageUtil.doPage(pageDTO, () -> spuMapper.listPointSpu(spuDTO));
    }

    @Override
    public PageVO<SpuVO> pageSupplierStockPointSpu(PageDTO pageDTO, SkuStockPointSearchDTO searchDTO) {
        PageVO<SpuVO> pageVO = new PageVO<>();
        pageVO.setPages(0);
        pageVO.setTotal(0L);
        pageVO.setList(new ArrayList<>());
        // 查询仓库信息
        WarehouseVO warehouse = this.checkWarehouse(searchDTO.getStockPointId(), searchDTO.getShopId(), searchDTO.getSysType());
        // 获取可采购的供应商Id集合
        List<Long> categoryIds = categoryShopFeignClient.getCategoryIdsByShopId(searchDTO.getShopId(), SysTypeEnum.MULTISHOP.value()).getData();
        List<Long> supplierIds = categoryShopFeignClient.getSupplyIdByCategoryIds(categoryIds).getData();
        if (CollectionUtils.isEmpty(supplierIds)) {
            return pageVO;
        }
        if (!Objects.isNull(searchDTO.getSupplierId())) {
            if (supplierIds.contains(searchDTO.getSupplierId())) {
                supplierIds = Collections.singletonList(searchDTO.getSupplierId());
            } else {
                return pageVO;
            }
        }
        // 根据仓库areaId获取供应商可配送的仓库列表
        WarehouseDTO warehouseDTO = new WarehouseDTO();
        warehouseDTO.setShopIds(supplierIds);
        warehouseDTO.setSysType(SysTypeEnum.SUPPLIER.value());
        warehouseDTO.setAreaId(warehouse.getAreaId());
        List<WarehouseVO> canDeliveryWarehouses = warehouseService.listCanDeliveryWarehouse(warehouseDTO);
        List<Long> defaultWarehouseIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
        List<Long> warehouseIds = new ArrayList<>(canDeliveryWarehouses.size());
        for (WarehouseVO warehouseVO : canDeliveryWarehouses) {
            warehouseIds.add(warehouseVO.getWarehouseId());
            if (Objects.equals(warehouseVO.getType(), 0)) {
                defaultWarehouseIds.add(warehouseVO.getWarehouseId());
            }
        }
        // 分页查询仓库对应的商品
        if (!CollectionUtils.isEmpty(defaultWarehouseIds)) {
            // 默认仓库在stock_point_sku就算没有库存，关联数据也会存在，通过not in排除空库存，再进行分页
            List<Long> emptySkuIds = this.listEmptySkuIds(defaultWarehouseIds);
            if (!CollectionUtils.isEmpty(emptySkuIds)) {
                searchDTO.setNotInSkuIds(emptySkuIds);
            }
        }
        searchDTO.setCategoryIds(categoryIds);
        PageVO<SpuVO> spuPage = this.pageSupplierSpu(pageDTO, searchDTO, warehouseIds);
        if (CollectionUtils.isEmpty(spuPage.getList())) {
            return spuPage;
        }
        // 补充sku信息和库存
        this.fillSupplierSkuInfo(spuPage, warehouseIds, searchDTO);
        // 补充供应商信息
        List<SupplierApiDetailVO> suppliers = supplierDetailFeignClient.listBySupplierIds(supplierIds).getData();
        Map<Long, SupplierApiDetailVO> supplierMap = suppliers.stream().collect(Collectors.toMap(SupplierApiDetailVO::getSupplierId, x -> x));
        for (SpuVO spuVO : spuPage.getList()) {
            SupplierApiDetailVO supplier = supplierMap.get(spuVO.getSupplierId());
            spuVO.setSupplierName(Objects.isNull(supplier) ? "" : supplier.getSupplierName());
        }
        return spuPage;
    }

    @Override
    public void intiStockPointSKu() {
        // 获取所有的默认仓库
        List<WarehouseVO> warehouseVOS = warehouseService.listDefaultWarehouses();
        if (CollectionUtils.isEmpty(warehouseVOS)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
        // 根据店铺id和系统类型区分
        Map<String, List<WarehouseVO>> warehouseVOMap = warehouseVOS.stream().collect(Collectors.groupingBy(warehouse -> warehouse.getShopId() + Constant.UNDERLINE + warehouse.getSysType()));
        List<SkuVO> skuVOS = skuMapper.listAll();
        List<Long> skuIds = skuVOS.stream().map(SkuVO::getSkuId).toList();
        List<StockPointSkuVO> stockPointSkuVOList = stockPointSkuService.listBySkuIds(skuIds);
        Map<Long, List<StockPointSkuVO>> stockPointSkuMap = stockPointSkuVOList.stream().collect(Collectors.groupingBy(StockPointSkuVO::getSkuId));

        List<Long> spuIds = skuVOS.stream().map(SkuVO::getSpuId).collect(Collectors.toList());
        List<SpuVO> spuVOS = spuMapper.listSpuBySpuIds(spuIds);
        Map<Long, Long> shopMap = spuVOS.stream().collect(Collectors.toMap(SpuVO::getSpuId, SpuVO::getShopId));
        Map<Long, Long> supplierMap = spuVOS.stream().collect(Collectors.toMap(SpuVO::getSpuId, SpuVO::getSupplierId));
        List<StockPointSkuDTO> stockPointSkuList = new ArrayList<>(skuVOS.size());
        for (SkuVO skuVO : skuVOS) {
            // 已经有区域库存，就不用再创建默认库存了
            if (stockPointSkuMap.containsKey(skuVO.getSkuId()) || Objects.equals(skuVO.getStatus(), StatusEnum.DELETE.value())) {
                continue;
            }
            StockPointSkuDTO stockPointSku = new StockPointSkuDTO();
            Integer sysType = SysTypeEnum.MULTISHOP.value();
            Long shopId = shopMap.get(skuVO.getSpuId());
            if (shopId == null) {
                continue;
            }
            // 供应商商品
            if (shopId == -1) {
                shopId = supplierMap.get(skuVO.getSpuId());
                sysType = SysTypeEnum.SUPPLIER.value();
            }
            // 平台端-积分商品
            else if (Objects.equals(shopId, Constant.ZERO_LONG)) {
                sysType = SysTypeEnum.PLATFORM.value();
            }
            String key = shopId + Constant.UNDERLINE + sysType;
            if (!warehouseVOMap.containsKey(key)) {
                continue;
            }
            Long warehouseId = warehouseVOMap.get(key).get(0).getWarehouseId();
            stockPointSku.setStockPointId(warehouseId);
            stockPointSku.setStockPointType(StockPointType.WAREHOUSE.getValue());
            stockPointSku.setSkuId(skuVO.getSkuId());
            stockPointSku.setSpuId(skuVO.getSpuId());
            stockPointSku.setType(0);
            stockPointSku.setStatus(skuVO.getStatus());
            stockPointSkuList.add(stockPointSku);
        }
        if (CollUtil.isNotEmpty(stockPointSkuList)) {
            stockPointSkuService.batchSave(stockPointSkuList);
        }
    }

    @Override
    public int countNormalSpuBySpuIds(Set<Long> spuIds) {
        return spuMapper.countNormalSpuBySpuIds(spuIds);
    }

    /**
     * 校验供应商信息是否变更
     * @param spuDTO 变更的spu信息
     * @param spuDb 原spu信息
     */
    private void checkSupplierSpuMsgChange(SpuDTO spuDTO, SpuVO spuDb) {
        // 校验'图片'变化
        boolean isChange = (Objects.nonNull(spuDTO.getMainImgUrl()) && !Objects.equals(spuDTO.getMainImgUrl(), spuDb.getMainImgUrl()))
                || (Objects.nonNull(spuDTO.getImgUrls()) && !Objects.equals(spuDTO.getImgUrls(), spuDb.getImgUrls()));
        // 校验'品牌'变化
        isChange = isChange
                || (Objects.nonNull(spuDTO.getBrandId()) && !Objects.equals(spuDTO.getBrandId(), spuDb.getBrandId()));
        // 校验'详情'变化
        isChange = isChange
                || (Objects.nonNull(spuDTO.getDetail()) && !Objects.equals(spuDTO.getDetail(), spuDb.getDetail()));
        // 校验'视频'变化
        isChange = isChange
                || (Objects.nonNull(spuDTO.getVideo()) && !Objects.equals(spuDTO.getVideo(), spuDb.getVideo()));
        // 校验'计量单位'变化
        isChange = isChange
                || (Objects.nonNull(spuDTO.getMeasureUnit()) && !Objects.equals(spuDTO.getMeasureUnit(), spuDb.getMeasureUnit()));
        // 校验'商品卖点'变化
        isChange = isChange
                || (Objects.nonNull(spuDTO.getSellingPoint()) && Objects.equals(spuDTO.getSellingPoint(), spuDb.getSellingPoint()));
        // 校验'名称'变化
        isChange = isChange
                || (Objects.nonNull(spuDTO.getName()) && !Objects.equals(spuDTO.getName(), spuDb.getName()));
        // 校验'spu编码'变化
        isChange = isChange
                || Objects.nonNull(spuDTO.getSpuCode()) && !Objects.equals(spuDTO.getSpuCode(), spuDb.getSpuCode());
        // 新增供应商商品变更日志
        if (isChange) {
            SpuSupplierChangeLog changeLog = new SpuSupplierChangeLog();
            changeLog.setSpuId(spuDTO.getSpuId());
            changeLog.setChangeType(SupplierSpuChangeType.SPU_MSG_CHANGE.value());
            spuSupplierChangeLogService.save(changeLog);
        }
    }

    /**
     * 检查仓库
     * @param warehouseId 仓库id
     * @param shopId 店铺id
     * @param sysType 系统类型
     */
    private WarehouseVO checkWarehouse(Long warehouseId,
                                       Long shopId,
                                       Integer sysType) {
        WarehouseVO warehouse = warehouseService.getByWarehouseId(warehouseId);
        if (Objects.isNull(warehouse)) {
            throw new LuckException(String.format("仓库[%s]不存在", warehouseId));
        }
        if (Objects.equals(warehouse.getSysType(), SysTypeEnum.STATION.value())) {
            // 检查门店仓库
            if(Objects.equals(sysType, SysTypeEnum.SUPPLIER.value())) {
                throw new LuckException("供应商不存在门店");
            }
            StationVO station = stationFeignClient.getStationByInside(warehouse.getShopId()).getData();
            if (!Objects.equals(station.getShopId(), shopId))  {
                throw new LuckException(String.format("门店[%s]非该店铺的门店", station.getStationId()));
            }
        } else if (!Objects.equals(shopId, warehouse.getShopId())
                || !Objects.equals(sysType, warehouse.getSysType())) {
            // 检查商家/供应商仓库
            throw new LuckException(String.format("仓库[%s]非该店铺的仓库", warehouseId));
        }
        return warehouse;
    }

    /**
     * 补充供应商sku信息
     * @param pageVO 分页数据
     * @param searchDTO 查询参数
     */
    private void fillSupplierSkuInfo(PageVO<SpuVO> pageVO, List<Long> warehouseIds, SkuStockPointSearchDTO searchDTO) {
        // 查询spu在该库存关联的skuId
        List<Long> spuIds = pageVO.getList().stream().map(SpuVO::getSpuId).collect(Collectors.toList());
        StockPointSkuDTO stockPointSkuDTO = new StockPointSkuDTO();
        stockPointSkuDTO.setSpuIds(spuIds);
        stockPointSkuDTO.setStockPointIds(warehouseIds);
        List<SpuVO> spuVOList = spuMapper.listStockPointSpuAndSku(stockPointSkuDTO);
        pageVO.setList(spuVOList);
        // 查询sku信息
        List<Long> skuIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
        List<SkuVO> skuVOList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (SpuVO spuVO : spuVOList) {
            spuIds.add(spuVO.getSpuId());
            for (SkuVO skuVO : spuVO.getSkus()) {
                skuVOList.add(skuVO);
                skuIds.add(skuVO.getSkuId());
            }
        }
        SkuDTO skuDTO = new SkuDTO();
        skuDTO.setSkuIds(skuIds);
        List<SkuVO> skus = skuService.listSku(skuDTO);
        Map<Long, SkuVO> skuMap = skus.stream().collect(Collectors.toMap(SkuVO::getSkuId, x -> x));
        // 查询代销商品信息（用于查询商家库存）
        List<SkuVO> saleSkus = skuStockService.listSkuStockBySupplierSpuIds(new ArrayList<>(spuIds), searchDTO.getShopId());
        Map<Long, Long> saleSkuMap = new HashMap<>(Constant.INITIAL_CAPACITY);
        if (!CollectionUtils.isEmpty(saleSkus)) {
            saleSkuMap = saleSkus.stream().collect(Collectors.toMap(SkuVO::getSupplierSkuId, SkuVO::getSkuId));
        }
        // 查询库存
        List<StockPointSkuVO> stockPointSkuVOList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (SkuVO skuVO : skuVOList) {
            stockPointSkuVOList.add(new StockPointSkuVO(skuVO.getSkuId(), skuVO.getStockPointId()));
        }
        for (Long saleSkuId : saleSkuMap.values()) {
            stockPointSkuVOList.add(new StockPointSkuVO(saleSkuId, searchDTO.getStockPointId()));
        }
        Map<String, SkuStockVO> skuStockMap = skuStockService.mapSkuPointStockByStockPoints(stockPointSkuVOList);
        // sku数据补充
        for (SpuVO spuVO : spuVOList) {
            skuVOList = new ArrayList<>(spuVO.getSkus().size());
            for (SkuVO skuVO : spuVO.getSkus()) {
                SkuVO sku = skuMap.get(skuVO.getSkuId());
                if (Objects.isNull(sku)) {
                    continue;
                }
                sku.setStockPointId(skuVO.getStockPointId());
                // 补充库存（过滤供应商库存为0的sku）
                SkuStockVO skuStockVO = skuStockMap.get(skuVO.getSkuId() + "_" + skuVO.getStockPointId());
                if (Objects.isNull(skuStockVO)
                        || Objects.equals(skuStockVO.getStock(), 0)) {
                    continue;
                }
                sku.setSupplierStock(skuStockVO.getStock());
                // 补充代销商品库存
                skuStockVO = skuStockMap.get(saleSkuMap.get(skuVO.getSkuId()) + "_" + searchDTO.getStockPointId());
                sku.setStock(Objects.isNull(skuStockVO) ? 0 : skuStockVO.getStock());
                skuVOList.add(sku);
            }
            spuVO.setSkus(skuVOList);
        }
    }

    private void offlineRelatedComboBySpuIds(List<Long> spuIds) {
        // 下架关联的组合商品
        List<Long> comboSpuIds = skuComboService.getCombSpusByComboSpuIds(spuIds,null);
        if(CollUtil.isEmpty(comboSpuIds)){
            return;
        }
        spuMapper.batchChangeSpuStatus(comboSpuIds, StatusEnum.DISABLE.value());
        // 更新品牌信息
        List<Long> brandIds = brandMapper.listBrandIdBySpuIds(comboSpuIds);
        brandMapper.batchUpdateSpuCount(brandIds);
        // 更新商品分组信息
        handleStatusChange(comboSpuIds);
        List<Long> shopIds = spuMapper.spuShopIdsBySpuIds(comboSpuIds);
        if (CollUtil.isNotEmpty(comboSpuIds)) {
            ServerResponseEntity<Void> discountResponseEntity = discountFeignClient.handleSpuOffline(comboSpuIds, shopIds);
            if (!discountResponseEntity.isSuccess()) {
                throw new LuckException(discountResponseEntity.getMsg());
            }
            ServerResponseEntity<Void> couponResponseEntity = couponFeignClient.handleSpuOffline(comboSpuIds, shopIds);
            if (!couponResponseEntity.isSuccess()) {
                throw new LuckException(couponResponseEntity.getMsg());
            }
        }
    }

    /**
     * 获取空库存的skuId集合
     * @param warehouseIds 仓库id集合
     * @return 空库存skuId集合
     */
    private List<Long> listEmptySkuIds(List<Long> warehouseIds) {
        // 查询仓库关联的所有sku库存
        Map<String, SkuStockVO> stockMap = stockManager.mapSkuStockByStockPointIds(warehouseIds);
        if (stockMap.size() == 0) {
            return new ArrayList<>();
        }
        // 找出库存为0的skuId, 通过'not in'，分页查询sku对应的spu
        return stockMap.values().stream()
                .filter(x -> x.getStock() <= 0)
                .map(SkuStockVO::getSkuId).toList();
    }

    /**
     * 分页查询供应商商品
     * @param pageDTO 分页参数
     * @param searchDTO 查询参数
     * @param warehouseIds 仓库id集合
     * @return 供应商商品分页数据
     */
    private PageVO<SpuVO> pageSupplierSpu(PageDTO pageDTO, SkuStockPointSearchDTO searchDTO, List<Long> warehouseIds) {
        StockPointSkuDTO stockPointSkuDTO = new StockPointSkuDTO();
        BeanUtils.copyProperties(searchDTO, stockPointSkuDTO);
        stockPointSkuDTO.setShopId(null);
        stockPointSkuDTO.setStockPointId(null);
        stockPointSkuDTO.setStockPointIds(warehouseIds);
        stockPointSkuDTO.setStatus(SpuStatus.PUT_SHELF.value());
        stockPointSkuDTO.setSpuMold(SpuMold.REAL.value());
        return PageUtil.doPage(pageDTO, () -> spuMapper.listPointSpu(stockPointSkuDTO));
    }
}

