
package com.tmerclub.cloud.search.manager;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.tmerclub.cloud.api.auth.constant.SysTypeEnum;
import com.tmerclub.cloud.api.dto.EsPageDTO;
import com.tmerclub.cloud.api.group.feign.GroupFeignClient;
import com.tmerclub.cloud.api.multishop.bo.EsShopDetailBO;
import com.tmerclub.cloud.api.multishop.feign.ShopDetailFeignClient;
import com.tmerclub.cloud.api.order.feign.OrderFeignClient;
import com.tmerclub.cloud.api.product.feign.SpuCommFeignClient;
import com.tmerclub.cloud.api.product.feign.SpuFeignClient;
import com.tmerclub.cloud.api.seckill.feign.SeckillFeignClient;
import com.tmerclub.cloud.api.vo.EsPageVO;
import com.tmerclub.cloud.common.cache.constant.CacheNames;
import com.tmerclub.cloud.common.cache.util.RedisUtil;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.constant.StatusEnum;
import com.tmerclub.cloud.common.database.util.PageUtil;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.product.constant.SpuStatus;
import com.tmerclub.cloud.common.product.constant.SpuType;
import com.tmerclub.cloud.common.product.constant.SupplierDeliveryType;
import com.tmerclub.cloud.common.product.dto.ProductSearchDTO;
import com.tmerclub.cloud.common.product.dto.ProductSearchLimitDTO;
import com.tmerclub.cloud.common.product.vo.GroupActivitySpuVO;
import com.tmerclub.cloud.common.product.vo.SekillActivitySpuVO;
import com.tmerclub.cloud.common.product.vo.SpuActivityAppVO;
import com.tmerclub.cloud.common.product.vo.search.*;
import com.tmerclub.cloud.common.response.ResponseEnum;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
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.search.builder.ProductSearchRequestBuilder;
import com.tmerclub.cloud.search.builder.ProductSearchResponseBuilder;
import com.tmerclub.cloud.search.constant.DataType;
import com.tmerclub.cloud.search.constant.EsConstant;
import com.tmerclub.cloud.search.constant.EsRenovationProductSortEnum;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.elasticsearch.action.search.SearchResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

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


/**
 * @author tmerclub
 * @date 2020/11/16
 */
@Component
public class ProductSearchManager {

    private static final Logger log = LoggerFactory.getLogger(ProductSearchManager.class);

    @Autowired
    private ProductSearchResponseBuilder productSearchResponseBuilder;


    @Autowired
    private ProductSearchRequestBuilder productSearchRequestBuilder;

    @DubboReference
    private SpuFeignClient spuFeignClient;

    @DubboReference
    private GroupFeignClient groupFeignClient;

    @DubboReference
    private SeckillFeignClient seckillFeignClient;

    @DubboReference
    private ShopDetailFeignClient shopDetailFeignClient;
    @DubboReference
    private SpuCommFeignClient spuCommFeignClient;
    @DubboReference
    private OrderFeignClient orderFeignClient;

    /**
     * 通过搜索信息分页搜索es数据并聚合返回的信息
     *
     * @param pageDTO          分页数据
     * @param productSearchDTO 商品搜索条件
     * @return 搜索结果
     */
    public EsPageVO<ProductSearchVO> page(EsPageDTO pageDTO, ProductSearchDTO productSearchDTO) {
        productSearchDTO.setAppDisplay(Boolean.TRUE);
        SearchResponse response = productSearchRequestBuilder.pageSearchResult(pageDTO, productSearchDTO, Boolean.TRUE);
        return buildSearchResult(pageDTO, response);
    }

    /**
     * 通过搜索信息分页搜索es数据的信息
     *
     * @param pageDTO          分页数据
     * @param productSearchDTO 商品搜索条件
     * @return 搜索结果
     */
    public EsPageVO<ProductSearchVO> spuPage(EsPageDTO pageDTO, ProductSearchDTO productSearchDTO) {
        productSearchDTO.setAppDisplay(Boolean.TRUE);
        SearchResponse response = productSearchRequestBuilder.pageSearchResult(pageDTO, productSearchDTO, Boolean.FALSE);
        return buildSearchResult(pageDTO, response);
    }

    /**
     * 获取搜索扩展信息
     *
     * @param pageDTO          分页数据
     * @param productSearchDTO 商品搜索条件
     * @return 搜索结果
     */
    public ProductSearchVO searchExtension(EsPageDTO pageDTO, ProductSearchDTO productSearchDTO) {
        ProductSearchDTO newProductSearchDTO = new ProductSearchDTO();
        newProductSearchDTO.setKeyword(productSearchDTO.getKeyword());
        newProductSearchDTO.setPrimaryCategoryId(productSearchDTO.getPrimaryCategoryId());
        newProductSearchDTO.setSecondaryCategoryId(productSearchDTO.getSecondaryCategoryId());
        newProductSearchDTO.setShopPrimaryCategoryId(productSearchDTO.getShopPrimaryCategoryId());
        newProductSearchDTO.setAppDisplay(Boolean.TRUE);
        pageDTO.setPageSize(0);
        SearchResponse response = productSearchRequestBuilder.pageSearchResult(pageDTO, newProductSearchDTO, Boolean.TRUE);
        return productSearchResponseBuilder.getProductSearchList(response).get(0);
    }

    /**
     * 商品管理分页搜索es数据的信息
     *
     * @param pageDTO          分页数据
     * @param productSearchDTO 商品搜索条件
     * @return 搜索结果
     */
    public EsPageVO<SpuAdminVO> adminPage(EsPageDTO pageDTO, ProductSearchDTO productSearchDTO) {
        adminSearchHandle(productSearchDTO);
        EsPageVO<SpuAdminVO> result = new EsPageVO<>();
        SearchResponse response = productSearchRequestBuilder.pageSearchResult(pageDTO, productSearchDTO, Boolean.FALSE);
        // 商品信息
        result.setList(productSearchResponseBuilder.buildSpuAdminList(response));
        // 分页信息
        productSearchResponseBuilder.buildSearchPage(pageDTO, result, response);
        return result;
    }

    /**
     * 根据spuId列表，获取spu信息
     *
     * @param productSearchDTO 商品搜索条件
     * @return spu列表
     */
    public List<SpuSearchVO> listSpuBySpuIds(ProductSearchDTO productSearchDTO) {
        EsPageDTO pageDTO = null;
        if (Objects.nonNull(productSearchDTO.getSpuIds())) {
            pageDTO = new EsPageDTO();
            pageDTO.setPageNum(1);
            pageDTO.setPageSize(productSearchDTO.getSpuIds().size());
        }
        productSearchDTO.setDataType(DataType.ALL_PROD.value());
        SearchResponse response = productSearchRequestBuilder.pageSearchResult(pageDTO, productSearchDTO, Boolean.FALSE);
        return productSearchResponseBuilder.buildSpuSearchList(response.getHits());
    }

    /**
     * 构建搜索结果数据
     *
     * @param pageDTO
     * @param response
     * @return
     */
    private EsPageVO<ProductSearchVO> buildSearchResult(EsPageDTO pageDTO, SearchResponse response) {
        EsPageVO<ProductSearchVO> esPageVO = new EsPageVO<>();

        // 1、返回的所有查询到的商品
        List<ProductSearchVO> productSearchs = productSearchResponseBuilder.getProductSearchList(response);
        esPageVO.setList(productSearchs);

        // 2、分页信息
        productSearchResponseBuilder.buildSearchPage(pageDTO, esPageVO, response);
        return esPageVO;
    }

    /**
     * 根据店铺id列表获取每个店铺的spu列表
     *
     * @param productSearchLimitDTO 店铺id列表
     * @return
     */
    public List<SpuSearchVO> limitSpuList(ProductSearchLimitDTO productSearchLimitDTO) {
        SearchResponse response = productSearchRequestBuilder.getLimitSpuResponse(productSearchLimitDTO);
        List<SpuSearchVO> spuList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        if (Objects.isNull(response)) {
            return spuList;
        }
        Map<Long, List<SpuSearchVO>> spuMap = productSearchResponseBuilder.loadSpuMapByAggregations(response);
        for (Long id : spuMap.keySet()) {
            spuList.addAll(spuMap.get(id));
        }
        return spuList;
    }

    /**
     * 查询商品信息，并对响应的数据进行分组
     *
     * @param productSearchLimitDTO
     * @return
     */
    public Map<Long, List<SpuSearchVO>> limitSpuMap(ProductSearchLimitDTO productSearchLimitDTO) {
        SearchResponse response = productSearchRequestBuilder.getLimitSpuResponse(productSearchLimitDTO);
        if (Objects.isNull(response)) {
            return new HashMap<>(0);
        }
        return productSearchResponseBuilder.loadSpuMapByAggregations(response);
    }

    /**
     * 获取商品活动信息(满减、优惠券)
     *
     * @param shopId
     * @param spuId
     * @return
     */
    @Cacheable(cacheNames = CacheNames.SPU_ACTIVITY_KEY, key = "#spuId", sync = true)
    public SpuActivityAppVO spuActivityBySpuId(Long shopId, Long spuId) {
        ServerResponseEntity<SpuActivityAppVO> spuResponse = spuFeignClient.spuActivityBySpuId(shopId, spuId);
        return spuResponse.getData();
    }

    /**
     * 获取商品团购活动信息
     *
     * @param spuList
     * @return
     */
    public void getGroupActivity(List<SpuSearchVO> spuList) {
        long currentTimeMillis = System.currentTimeMillis();
        // 获取团购商品id
        List<Long> spuIds = spuList.stream()
                .filter(spu ->
                        Objects.equals(spu.getSpuType(), SpuType.GROUP.value()) &&
                                Objects.nonNull(spu.getActivityStartTime()) &&
                                currentTimeMillis > spu.getActivityStartTime()
                )
                .map(SpuSearchVO::getSpuId)
                .collect(Collectors.toList()
                );
        if (CollUtil.isEmpty(spuIds)) {
            return;
        }
        ServerResponseEntity<List<GroupActivitySpuVO>> activityList = groupFeignClient.groupSpuListBySpuIds(spuIds);
        Map<Long, GroupActivitySpuVO> groupMap = activityList.getData().stream().collect(Collectors.toMap(GroupActivitySpuVO::getSpuId, g -> g));
        log.info("团购活动数据：{}", Json.toJsonString(groupMap));
        if (MapUtil.isEmpty(groupMap)) {
            return;
        }
        for (SpuSearchVO spuSearchVO : spuList) {
            if (!groupMap.containsKey(spuSearchVO.getSpuId())) {
                continue;
            }
            if (Objects.isNull(spuSearchVO.getActivityStartTime()) || (currentTimeMillis < spuSearchVO.getActivityStartTime())){
                continue;
            }
            SpuActivityAppVO spuActivityAppVO = new SpuActivityAppVO();
            spuActivityAppVO.setGroupActivity(groupMap.get(spuSearchVO.getSpuId()));
            spuSearchVO.setActivityStatus(spuActivityAppVO.getGroupActivity().getStatus());
            spuSearchVO.setSpuActivity(spuActivityAppVO);
        }
    }

    /**
     * 获取商品秒杀活动信息
     *
     * @param selectedLot
     * @param spuList
     */
    public void getSeckillActivity(Integer selectedLot, List<SpuSearchVO> spuList) {
        List<Long> spuIds = spuList.stream()
                .filter(spu ->
                        Objects.equals(spu.getSpuType(), SpuType.SECKILL.value())
                )
                .map(SpuSearchVO::getSpuId)
                .collect(Collectors.toList()
                );

        if (CollUtil.isEmpty(spuIds)) {
            return;
        }

        ServerResponseEntity<List<SekillActivitySpuVO>> activityList = seckillFeignClient.seckillSpuListBySpuIds(selectedLot, spuIds);
        Map<Long, SekillActivitySpuVO> seckillMap = activityList.getData().stream().collect(Collectors.toMap(SekillActivitySpuVO::getSpuId, g -> g));
        for (SpuSearchVO spuSearchVO : spuList) {
            if (!seckillMap.containsKey(spuSearchVO.getSpuId())) {
                continue;
            }
            if (Objects.isNull(spuSearchVO.getActivityStartTime())) {
                continue;
            }
            SpuActivityAppVO spuActivityAppVO = new SpuActivityAppVO();
            spuActivityAppVO.setSekillActivitySpuVO(seckillMap.get(spuSearchVO.getSpuId()));
            spuSearchVO.setActivityStatus(spuActivityAppVO.getSekillActivitySpuVO().getStatus());
            spuSearchVO.setSpuActivity(spuActivityAppVO);
        }
    }

    /**
     * 装修接口搜索商品
     */
    public EsPageVO<ProductSearchVO> renovationPage(EsPageDTO pageDTO, ProductSearchDTO productSearchDTO, Long size) {
        if (Objects.isNull(pageDTO.getPageSize()) || pageDTO.getPageSize() == 0) {
            return new EsPageVO<>();
        }
        productSearchDTO.setFetchSource(EsConstant.RENOVATION_FETCH_SOURCE);
        // 不需要积分商品
        if (Objects.isNull(productSearchDTO.getSpuType())) {
            List<Integer> types = new ArrayList<>(Constant.INITIAL_CAPACITY);
            types.add(SpuType.SCORE.value());
            productSearchDTO.setMustNotProdTypes(types);
        }

        // 如果不是搜索指定商品，就只查询可以在用户端显示的商品
        if (CollUtil.isEmpty(productSearchDTO.getSpuIds())) {
            productSearchDTO.setAppDisplay(Boolean.TRUE);
        }
        SearchResponse response = productSearchRequestBuilder.pageSearchResult(pageDTO, productSearchDTO, Boolean.TRUE);
        EsPageVO<ProductSearchVO> result = buildSearchResult(pageDTO, response);
        loadData(productSearchDTO, result.getList());

        // 处理下瀑布流商品排序
        handleProdSort(productSearchDTO, result, size);
        return result;
    }

    /**
     * 处理下瀑布流商品排序
     *
     * @param productSearchDTO
     * @param searchPage
     * @param size
     */
    private void handleProdSort(ProductSearchDTO productSearchDTO, EsPageVO<ProductSearchVO> searchPage, Long size) {
        if (!Objects.equals(productSearchDTO.getShowSpuType(), 1) || CollectionUtils.isEmpty(productSearchDTO.getSpuIds())) {
            return;
        }
        searchPage.setTotal(Objects.isNull(size) ? searchPage.getTotal() : size);
        searchPage.setPages(Objects.isNull(size) ? searchPage.getPages() : PageUtil.getPages(searchPage.getTotal(), productSearchDTO.getPageSize()));
        List<SpuSearchVO> productSearchList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        ProductSearchVO productSearchVO = searchPage.getList().get(0);
        Map<Long, SpuSearchVO> prodMap = productSearchVO.getSpus().stream().collect(Collectors.toMap(SpuSearchVO::getSpuId, spuSearchVO -> spuSearchVO));
        for (Object prodId : productSearchDTO.getSpuIds()) {
            if (!prodMap.containsKey(Long.valueOf(String.valueOf(prodId)))) {
                continue;
            }
            productSearchList.add(prodMap.get(Long.valueOf(String.valueOf(prodId))));
        }
        productSearchVO.setSpus(productSearchList);
    }

    /**
     * 切割属性信息
     */
    public Map<String, List<String>> splitAttr(String attrStr) {
        Map<String, List<String>> attrMap = null;
        if (StrUtil.isNotBlank(attrStr)) {
            String attrLink = "\\^";
            String[] attrArray = attrStr.split(attrLink);
            attrMap = new HashMap<>(attrArray.length);
            for (String s : attrArray) {
                String[] ids = s.split(Constant.UNDERLINE);
                String[] split = ids[1].split(Constant.COMMA);
                List<String> attrValueIds = Arrays.asList(split);
                attrMap.put(ids[0], attrValueIds);
            }
        }
        return attrMap;
    }

    /**
     * 处理搜索数据
     */
    public void loadData(ProductSearchDTO productSearchDTO, List<ProductSearchVO> list) {
        if (CollUtil.isEmpty(list)) {
            return;
        }
        ProductSearchVO productSearch = list.get(0);
        for (ProductSearchVO productSearchVO : list) {
            loadShopData(productSearchVO);
            if (StrUtil.isNotBlank(productSearchDTO.getBrandIds())) {
                loadSearchBrandData(productSearchVO);
            }

            // 获取商品秒杀、团购活动信息
            getGroupActivity(productSearchVO.getSpus());
            getSeckillActivity(productSearchDTO.getSelectedLot(), productSearchVO.getSpus());

            if (Objects.equals(productSearchDTO.getNeedActivity(), 1)) {
                loadActivity(productSearchVO);
            }
            if (CollUtil.isNotEmpty(productSearch.getAttrs())) {
                loadAttr(productSearchVO, productSearchDTO.getAttrMap());
            }

            for (SpuSearchVO spus : productSearchVO.getSpus()) {
                spus.setActivityStartTime(null);
            }
        }
    }

    /**
     * 获取店铺数据
     */
    public void loadShopData(ProductSearchVO productSearchVO) {
        if (Objects.isNull(productSearchVO.getShopInfo()) || Objects.isNull(productSearchVO.getShopInfo().getShopId())) {
            return;
        }
        ServerResponseEntity<EsShopDetailBO> shopDataResponse = shopDetailFeignClient.shopExtensionData(productSearchVO.getShopInfo().getShopId());
        if (Objects.isNull(shopDataResponse.getData())) {
            productSearchVO.setShopInfo(null);
            return;
        }
        if (Objects.equals(shopDataResponse.getCode(), ResponseEnum.OK.value())) {
            EsShopDetailBO esShopDetailBO = shopDataResponse.getData();
            ShopInfoSearchVO shopInfo = productSearchVO.getShopInfo();
            shopInfo.setShopLogo(esShopDetailBO.getShopLogo());
            shopInfo.setShopName(esShopDetailBO.getShopName());
            shopInfo.setSaleNum(esShopDetailBO.getSaleNum());
            shopInfo.setType(esShopDetailBO.getType());
            shopInfo.setCollectionNum(esShopDetailBO.getCollectionNum());
        }
    }

    /**
     * 获取品牌项信息
     */
    public void loadSearchBrandData(ProductSearchVO productSearchVO) {
        if (CollUtil.isEmpty(productSearchVO.getBrands())) {
            return;
        }
        productSearchVO.setSearchItem(new SearchItemVO());
        productSearchVO.getSearchItem().setBrands(productSearchVO.getBrands());
        productSearchVO.setBrands(null);
    }

    /**
     * 获取商品活动信息(满减、优惠券)
     */
    public void loadActivity(ProductSearchVO productSearchVO) {
        for (SpuSearchVO spu : productSearchVO.getSpus()) {
            SpuActivityAppVO spuActivityAppVO = spuActivityBySpuId(spu.getShopId(), spu.getSpuId());
            if (Objects.isNull(spuActivityAppVO)) {
                continue;
            }
            if (Objects.nonNull(spu.getSpuActivity())) {
                spuActivityAppVO.setGroupActivity(spu.getSpuActivity().getGroupActivity());
                spuActivityAppVO.setSekillActivitySpuVO(spu.getSpuActivity().getSekillActivitySpuVO());
            }
            spu.setSpuActivity(spuActivityAppVO);
        }
    }


    /**
     * 获取属性信息
     */
    public void loadAttr(ProductSearchVO productSearchVO, Map<String, List<String>> attrMap) {

        Iterator<AttrSearchVO> iterator = productSearchVO.getAttrs().iterator();
        int oneAttr = 1;
        while (iterator.hasNext()) {
            AttrSearchVO attr = iterator.next();
            // 属性值小于等于一个属性，不显示该属性
            if (!Objects.isNull(attr)) {
                if (attr.getAttrValues().size() <= oneAttr) {
                    iterator.remove();
                    continue;
                }
                //  属性值作为pc端搜索参数时，不显示该属性
                if (CollectionUtil.isNotEmpty(attrMap) && attrMap.containsKey(attr.getAttrId().toString())) {
                    iterator.remove();
                }
                attr.getAttrValues().sort(Comparator.comparing(AttrValueSearchVO::getAttrValueName).reversed());
            } else {
                iterator.remove();
            }
        }
    }


    /**
     * 商品管理查询处理（商家端、平台端）
     *
     * @param productSearchDTO
     */
    private void adminSearchHandle(ProductSearchDTO productSearchDTO) {
        if (Objects.isNull(productSearchDTO) || Objects.isNull(productSearchDTO.getDataType())) {
            return;
        }
        Integer dataType = productSearchDTO.getDataType();
        // 销售中
        if (Objects.equals(DataType.SALE.value(), dataType)) {
            productSearchDTO.setSpuStatus(StatusEnum.ENABLE.value());
        }
        // 已售罄
        else if (Objects.equals(DataType.SOLD_OUT.value(), dataType)) {
            if (Objects.equals(AuthUserContext.get().getSysType(), SysTypeEnum.MULTISHOP.value())) {
                productSearchDTO.setSupplierDeliveryType(SupplierDeliveryType.SHOP_DELIVERY.value());
            }
            productSearchDTO.setHasStock(0);
        }
    }

    public void addRenovationSpuCache(String key, ProductSearchDTO productSearchDTO, Long shopId, Integer expireTime) {
        //TODO 后续优化
        if (Objects.isNull(productSearchDTO.getEsTimeRange()) && Objects.isNull(productSearchDTO.getEsRenovationSpuSort())) {
            return;
        }
        // 计算时间
        int dayNum = 0;
        switch (productSearchDTO.getEsTimeRange()) {
            case 1:
                dayNum = 365;
                break;
            case 2:
                dayNum = 90;
                break;
            case 3:
                dayNum = 30;
                break;
            case 4:
                dayNum = 7;
                break;
            default:
                break;
        }
        ServerResponseEntity<List<Long>> spuIdsResp;
        // 1.获取根据条件的商品ids
        if (Objects.equals(productSearchDTO.getEsRenovationSpuSort(), EsRenovationProductSortEnum.COMMENT_NUM_DESC.value()) || Objects.equals(productSearchDTO.getEsRenovationSpuSort(), EsRenovationProductSortEnum.COMMENT_NUM_ASC.value())) {
            // 获取时间范围内的评论数排序,放入redis
            spuIdsResp = spuCommFeignClient.getCommNumRankSpuIdsByShopIdAndTime(key, shopId, dayNum, expireTime, productSearchDTO.getEsRenovationSpuSort(), productSearchDTO.getPrimaryCategoryId());
        } else {
            // 获取时间范围内的销量排序，放入redis
            spuIdsResp = orderFeignClient.getSoldNumRankByShopIdAndTime(key, shopId, dayNum, expireTime, productSearchDTO.getEsRenovationSpuSort(), productSearchDTO.getPrimaryCategoryId());
        }
        // 2.判断数量是否为1000个，没有就按创建时间排序补充剩余
        if (!spuIdsResp.isSuccess()) {
            throw new LuckException(spuIdsResp.getMsg());
        }
        List<Long> spuIds = spuIdsResp.getData();
        if (Objects.isNull(spuIds) || CollUtil.isEmpty(spuIds) || Objects.isNull(spuIds.get(0))) {
            spuIds = new ArrayList<>();
        }
        log.info("spuIds:{}", spuIds);
        // 过滤掉商品状态不是正常的商品
        List<Long> filterSpuIds = getFilterSpuIds(spuIds, productSearchDTO.getPrimaryCategoryId());
        log.info("filterSpuIds:{}", filterSpuIds);
        if (filterSpuIds.size() >= EsConstant.RENOVATION_PRODUCT_IDS_LIMIT) {
            return;
        }
        // 不破坏原来的排序
        if (CollUtil.isNotEmpty(filterSpuIds)) {
            spuIds.removeIf(spuId -> !filterSpuIds.contains(spuId));
        } else {
            spuIds = new ArrayList<>(100);
        }
        log.info("remove-spuIds:{}", spuIds);
        int surplusNum = EsConstant.RENOVATION_PRODUCT_IDS_LIMIT - spuIds.size();
        EsPageDTO pageDTO = new EsPageDTO();
        pageDTO.setPageNum(1);
        pageDTO.setPageSize(surplusNum);
        ProductSearchDTO productSearch = BeanUtil.map(productSearchDTO, ProductSearchDTO.class);
        productSearch.setSpuIdsExclude(spuIds);
        productSearch.setShowSpuType(0);
        productSearch.setAppDisplay(true);
        EsPageVO<ProductSearchVO> searchPage = renovationPage(pageDTO, productSearch, null);
        List<SpuSearchVO> spuList = searchPage.getList().get(0).getSpus();
        List<Long> esSpuIds = spuList.stream().map(SpuSearchVO::getSpuId).collect(Collectors.toList());
        log.info("esSpuIds:{}", esSpuIds);
        // 判断是怎么排序的 降序的话添加到最后 正序的话添加到最前面
        if (Objects.equals(productSearchDTO.getEsRenovationSpuSort(), EsRenovationProductSortEnum.COMMENT_NUM_DESC.value())
                || Objects.equals(productSearchDTO.getEsRenovationSpuSort(), EsRenovationProductSortEnum.SALE_NUM_DESC.value())) {
            spuIds.addAll(esSpuIds);
        } else {
            spuIds.addAll(0, esSpuIds);
        }
        log.info("redis-spuIds:{}", spuIds);
        // 放入es缓存
        RedisUtil.setRightPushAll(key, spuIds, expireTime);
    }

    private List<Long> getFilterSpuIds(List<Long> spuIds, Long primaryCategoryId) {
        if (CollUtil.isEmpty(spuIds)) {
            return new ArrayList<>(0);
        }
        EsPageDTO filterPage = new EsPageDTO();
        filterPage.setPageNum(1);
        filterPage.setPageSize(spuIds.size());
        ProductSearchDTO filterSearch = new ProductSearchDTO();
        filterSearch.setSpuIds(spuIds);
        filterSearch.setSpuStatus(SpuStatus.PUT_SHELF.value());
        filterSearch.setShowSpuType(0);
        filterSearch.setAppDisplay(true);
        if (Objects.nonNull(primaryCategoryId)) {
            filterSearch.setPrimaryCategoryId(primaryCategoryId);
        }
        EsPageVO<ProductSearchVO> filterSearchPage = renovationPage(filterPage, filterSearch, null);
        if (CollUtil.isEmpty(filterSearchPage.getList())) {
            return new ArrayList<>(0);
        }
        List<SpuSearchVO> filterSpuList = filterSearchPage.getList().get(0).getSpus();
        return filterSpuList.stream().map(SpuSearchVO::getSpuId).collect(Collectors.toList());
    }

    public EsPageVO<ProductSearchVO> showSpuTypeRenovationPage(EsPageDTO pageDTO, ProductSearchDTO productSearchDTO) {
        Long size = null;
        if (Objects.equals(productSearchDTO.getShowSpuType(), 1)) {
            if (Objects.equals(productSearchDTO.getEsRenovationSpuSort(), EsRenovationProductSortEnum.CREATE_TIME_ASC.value()) || Objects.equals(productSearchDTO.getEsRenovationSpuSort(), EsRenovationProductSortEnum.CREATE_TIME_DESC.value())) {
                productSearchDTO.setSort(productSearchDTO.getEsRenovationSpuSort());
            } else {
                // 获取指定规则的商品ids
                size = getSpuIds(pageDTO, productSearchDTO);
            }
        }
        EsPageVO<ProductSearchVO> searchPage = renovationPage(pageDTO, productSearchDTO, size);
        loadData(productSearchDTO, searchPage.getList());
        return searchPage;
    }

    @SuppressWarnings("unchecked")
    private Long getSpuIds(EsPageDTO pageDTO, ProductSearchDTO productSearchDTO) {
        Long shopId = Objects.isNull(productSearchDTO.getShopId()) ? 0L : productSearchDTO.getShopId();
        String key = EsConstant.RENOVATION_PRODUCT_IDS_CACHE + CacheNames.UNION + shopId +
                CacheNames.UNION_KEY + productSearchDTO.getEsTimeRange() + CacheNames.UNION_KEY + productSearchDTO.getEsRenovationSpuSort()
                + CacheNames.UNION_KEY + productSearchDTO.getPrimaryCategoryId();
        if (!RedisUtil.hasKey(key)) {
            addRenovationSpuCache(key, productSearchDTO, shopId, EsConstant.RENOVATION_PRODUCT_IDS_CACHE_TIME);
        }
        Long size = RedisUtil.getListSize(key);
        long startNum = (long) (pageDTO.getPageNum() - 1) * pageDTO.getPageSize();
        long endNum = (long) pageDTO.getPageNum() * pageDTO.getPageSize() - 1;
        endNum = Math.min(endNum, size - 1);
        List<Long> spuIds = RedisUtil.getListRange(key, startNum, endNum);
        productSearchDTO.setSpuIds(spuIds);
        return size;
    }
}
