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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.tmerclub.cloud.api.product.bo.PlatformCommissionOrderItemBO;
import com.tmerclub.cloud.api.product.constant.CategoryLevel;
import com.tmerclub.cloud.api.product.util.ProductLangUtil;
import com.tmerclub.cloud.api.user.feign.PopupFeignClient;
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.JumpType;
import com.tmerclub.cloud.common.constant.StatusEnum;
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.product.vo.CategoryLangVO;
import com.tmerclub.cloud.common.product.vo.CategoryVO;
import com.tmerclub.cloud.common.product.vo.ParentCategoryVO;
import com.tmerclub.cloud.common.product.vo.app.CategoryAppVO;
import com.tmerclub.cloud.common.product.vo.app.CategorySearchAppVO;
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.product.bo.CategoryRateBO;
import com.tmerclub.cloud.product.dto.CategoryDTO;
import com.tmerclub.cloud.product.mapper.CategoryMapper;
import com.tmerclub.cloud.product.model.Category;
import com.tmerclub.cloud.product.service.*;
import com.tmerclub.cloud.product.service.*;
import com.tmerclub.cloud.product.vo.CategoryExcelVO;
import com.tmerclub.cloud.product.vo.CategoryPlatformExcelVO;
import com.tmerclub.cloud.product.vo.CategoryUseNumVO;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 分类信息
 *
 * @author tmerclub
 * @date 2020-10-28 15:27:24
 */
@Service
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private CategoryLangService categoryLangService;
    @Autowired
    private SpuTagReferenceService spuTagReferenceService;
    @Autowired
    private SpuOfflineService spuOfflineService;
    @Autowired
    private CategoryShopService categoryShopService;
    @DubboReference
    private PopupFeignClient popupFeignClient;

    private static final String PRIMARY_CATEGORY = "一级分类";
    private static final String SECONDARY_CATEGORY = "二级分类";
    private static final String TERTIARY_CATEGORY = "三级分类";

    @Override
    public CategoryVO getInfo(Long categoryId) {
        CategoryVO category = categoryMapper.getById(categoryId);
        if (Objects.isNull(category)) {
            return null;
        }
        List<CategoryVO> paths = new ArrayList<>(Constant.INITIAL_CAPACITY);
        paths.add(category);
        getPathNames(paths);
        if (CollUtil.isEmpty(category.getCategories())) {
            category.setCategories(new ArrayList<>(0));
        }
        return category;
    }


    @Override
    @Cacheable(cacheNames = CacheNames.CATEGORY_INFO, key = "#categoryId")
    public CategoryVO getById(Long categoryId) {
        CategoryVO category = categoryMapper.getById(categoryId);
        if (Objects.isNull(category)) {
            throw new LuckException("分类不存在");
        }
        // 如果是三级分类，添加一级分类id
        if (Objects.equals(category.getLevel(), CategoryLevel.THIRD.value())) {
            CategoryVO categoryVO = categoryMapper.getById(category.getParentId());
            category.setPrimaryCategoryId(categoryVO.getParentId());
        }
        return category;
    }

    @Override
    @Cacheable(cacheNames = CacheNames.CATEGORY_INFO, key = "#categoryId")
    public CategoryVO getByCategoryId(Long categoryId) {
        CategoryVO category = categoryMapper.getById(categoryId);
        if (Objects.isNull(category)) {
            return null;
        }
        // 如果是三级分类，添加一级分类id
        if (Objects.equals(category.getLevel(), CategoryLevel.THIRD.value())) {
            CategoryVO categoryVO = categoryMapper.getById(category.getParentId());
            category.setPrimaryCategoryId(categoryVO.getParentId());
        }
        return category;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long save(CategoryDTO categoryDTO) {
        categoryDTO.setCategoryId(null);
        Category category = BeanUtil.map(categoryDTO, Category.class);
        categoryLangService.existCategoryName(categoryDTO);
        String path = "";
        if (!Objects.equals(CategoryLevel.First.value(), category.getLevel())) {
            String parentId = String.valueOf(category.getParentId());
            CategoryVO categoryDb = categoryMapper.getById(category.getParentId());
            category.setStatus(categoryDb.getStatus());
            if (StrUtil.isBlank(categoryDb.getPath())) {
                path = parentId;
            } else {
                path = categoryDb.getPath() + Constant.CATEGORY_INTERVAL + parentId;
            }
        }
        category.setPath(path);
        categoryMapper.save(category);
        categoryLangService.save(categoryDTO.getCategoryLangList(), category.getCategoryId());
        return category.getCategoryId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(CategoryDTO categoryDTO) {
        Integer sysType = AuthUserContext.get().getSysType();
        Category category = BeanUtil.map(categoryDTO, Category.class);
        CategoryVO categoryDb = categoryMapper.getById(category.getCategoryId());
        if (Objects.equals(categoryDb.getCategoryId(), category.getParentId())) {
            throw new LuckException("分类不能成为本身的上级分类");
        }
        categoryLangService.existCategoryName(categoryDTO);
        categoryMapper.update(category);
        categoryLangService.update(categoryDTO.getCategoryLangList(), categoryDb);
        if (Objects.equals(categoryDb.getShopId(), Constant.PLATFORM_SHOP_ID)) {
            if (Objects.equals(categoryDTO.getLevel(), CategoryLevel.SECOND.value())) {
                List<Long> categoryIds = categoryMapper.listCategoryIdByShopIdAndParentId(Constant.PLATFORM_SHOP_ID, category.getCategoryId());
                categoryShopService.removeCacheByChangeCategoryIds(categoryIds, sysType);
            } else if (Objects.equals(categoryDTO.getLevel(), CategoryLevel.THIRD.value())) {
                // 如果更新的分类为三级分类，需要更新店铺签约分类缓存
                categoryShopService.removeCacheByChangeCategoryId(categoryDTO.getCategoryId());
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void deleteById(Long categoryId, Long shopId) {
        CategoryVO categoryVO = getById(categoryId);
        if (Objects.isNull(categoryVO)) {
            throw new LuckException("当前分类不存在，请刷新后重试");
        }
        List<CategoryUseNumVO> numList = categoryMapper.getCategoryUseNum(categoryId, shopId);
        verifyCategoryUseNum(numList);
        categoryMapper.deleteById(categoryId);
        if (Objects.equals(categoryVO.getLevel(), CategoryLevel.THIRD.value())) {
            // 如果删除的分类是三级分类需要删除店铺分类关联关系表中该分类的数据
            categoryShopService.deleteByCategoryId(categoryId);
        }
        if (categoryVO.getLevel() > CategoryLevel.First.value()) {
            // 失效弹窗
            ServerResponseEntity<Void> response = popupFeignClient.deleteLink(null, categoryVO.getShopId(), JumpType.CATEGORY.value(), Collections.singletonList(categoryId));
            if (!response.isSuccess()) {
                throw new LuckException(response.getMsg());
            }
        }
    }

    /**
     * 检查分类的使用数量
     *
     * @param numList
     */
    private void verifyCategoryUseNum(List<CategoryUseNumVO> numList) {
        StringBuilder stringBuilder = new StringBuilder("还有");
        int count = 0;
        for (CategoryUseNumVO categoryUseNumVO : numList) {
            if (categoryUseNumVO.getNum() > 0) {
                switch (categoryUseNumVO.getType()) {
                    case 1:
                        stringBuilder.append(categoryUseNumVO.getNum()).append("个分类,");
                        break;
                    case 2:
                        stringBuilder.append(categoryUseNumVO.getNum()).append("个属性,");
                        break;
                    case 3:
                        stringBuilder.append(categoryUseNumVO.getNum()).append("个品牌,");
                        break;
                    case 4:
                        stringBuilder.append(categoryUseNumVO.getNum()).append("件商品,");
                        break;
                    default:
                }
            }
            count = count + categoryUseNumVO.getNum();
        }
        if (count > 0) {
            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
            stringBuilder.append("在使用该分类，不能进行删除操作");
            throw new LuckException(stringBuilder.toString());
        }
    }

    @Override
    public List<CategoryAppVO> list(Long shopId) {
        List<CategoryVO> list = categoryMapper.list(shopId, null);
        ProductLangUtil.categoryList(list);
        return BeanUtil.mapAsList(list, CategoryAppVO.class);
    }

    @Override
    public void removeCategoryCache(Long shopId, Long categoryId, Integer sysType) {
        List<String> key = new ArrayList<>(Constant.INITIAL_CAPACITY);
        if (Objects.nonNull(categoryId)) {
            key.add(CacheNames.CATEGORY_INFO + CacheNames.UNION + categoryId);
        }
        if (Objects.equals(shopId, Constant.PLATFORM_SHOP_ID)) {
            key.add(CacheNames.CATEGORY_RATE + CacheNames.UNION + "0");
        }
        key.add(CacheNames.CATEGORY_LIST_OF_SHOP + CacheNames.UNION + shopId + Constant.COLON + LanguageEnum.LANGUAGE_ZH_CN.getLang());
        key.add(CacheNames.CATEGORY_LIST_OF_SHOP + CacheNames.UNION + shopId + Constant.COLON + LanguageEnum.LANGUAGE_EN.getLang());
        if (CollUtil.isNotEmpty(key)) {
            RedisUtil.deleteBatch(key);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public List<Long> categoryEnableOrDisable(CategoryDTO categoryDTO, Integer sysType) {
        CategoryVO categoryDb = getById(categoryDTO.getCategoryId());
        if (!Objects.equals(categoryDb.getShopId(), Constant.PLATFORM_SHOP_ID) &&
                !Objects.equals(categoryDb.getShopId(), AuthUserContext.get().getTenantId())) {
            throw new LuckException(ResponseEnum.UNAUTHORIZED);
        }
        // 如果是重复提交，则直接返回
        if (Objects.equals(categoryDb.getStatus(), categoryDTO.getStatus())) {
            return Collections.singletonList(categoryDTO.getCategoryId());
        }
        // 如果该分类不是一级分类，并且是上架操作，需要校验该分类的上级分类是否为上架状态
        if (!Objects.equals(categoryDb.getLevel(), CategoryLevel.First.value()) && Objects.equals(categoryDTO.getStatus(), StatusEnum.ENABLE.value())) {
            CategoryVO parentCategoryVO = getById(categoryDb.getParentId());
            if (!Objects.equals(parentCategoryVO.getStatus(), StatusEnum.ENABLE.value())) {
                throw new LuckException("上架该分类前，需要把该分类的上级分类上架");
            }
        }
        List<Long> updateList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        List<Long> thirdIdList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        List<Long> platformThirdIdList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        if (!categoryDb.getLevel().equals(CategoryLevel.THIRD.value())) {
            // 如果是店铺的二级还需要将分类id放进去
            if (!Objects.equals(categoryDb.getShopId(), Constant.PLATFORM_SHOP_ID)) {
                thirdIdList.add(categoryDb.getCategoryId());
            }
            if (Objects.equals(categoryDTO.getStatus(), StatusEnum.DISABLE.value()) || Objects.equals(categoryDTO.getStatus(), StatusEnum.OFFLINE.value())) {
                List<Category> categoryList = categoryMapper.getChildCategory(categoryDb.getCategoryId());
                categoryList.forEach(category -> {
                    updateList.add(category.getCategoryId());
                    if (Objects.equals(categoryDb.getShopId(), Constant.PLATFORM_SHOP_ID) && Objects.equals(category.getLevel(), CategoryLevel.THIRD.value())) {
                        thirdIdList.add(category.getCategoryId());
                        platformThirdIdList.add(category.getCategoryId());
                    } else if (!Objects.equals(categoryDb.getShopId(), Constant.PLATFORM_SHOP_ID) && Objects.equals(category.getLevel(), CategoryLevel.SECOND.value())) {
                        thirdIdList.add(category.getCategoryId());
                    }
                });
            }
        } else {
            updateList.add(categoryDb.getCategoryId());
            thirdIdList.add(categoryDb.getCategoryId());
            platformThirdIdList.add(categoryDb.getCategoryId());
        }
        // 更新该分类的下级分类状态
        updateList.add(categoryDb.getCategoryId());
        categoryMapper.updateBatchOfStatus(updateList, categoryDTO.getStatus());

        // 更新店铺签约分类缓存
        categoryShopService.removeCacheByChangeCategoryIds(platformThirdIdList, sysType);

        // 分类下架后， 下架分类中的商品
        if (Objects.equals(categoryDTO.getStatus(), StatusEnum.DISABLE.value()) || Objects.equals(categoryDTO.getStatus(), StatusEnum.OFFLINE.value())) {
            if (CollUtil.isEmpty(thirdIdList)) {
                return updateList;
            }
            // 查询出秒杀or团购的商品进行下线
            // 下线掉关联商品的活动
            spuOfflineService.offlineSpuStatusAndActivity(2, null, categoryDb.getShopId(), thirdIdList, null, null);
            spuTagReferenceService.deleteSpuTagByShopIdAndCategoryIds(categoryDb.getShopId(), thirdIdList);
            // 失效弹窗
            ServerResponseEntity<Void> response = popupFeignClient.deleteLink(null, categoryDb.getShopId(), JumpType.CATEGORY.value(), thirdIdList);
            if (!response.isSuccess()) {
                throw new LuckException(response.getMsg());
            }
        }
        return updateList;
    }

    @Override
    public void getPathNames(List<CategoryVO> categories) {
        if (CollUtil.isEmpty(categories)) {
            return;
        }
        // 获取分类的所有上级分类id集合
        Set<Long> paths = new HashSet<>(Constant.INITIAL_CAPACITY);
        for (CategoryVO category : categories) {
            if (Objects.isNull(category) || StrUtil.isBlank(category.getPath())) {
                continue;
            }
            String[] parentIds = category.getPath().split(Constant.CATEGORY_INTERVAL);
            for (String parentId : parentIds) {
                paths.add(Long.valueOf(parentId));
            }
        }
        if (CollUtil.isEmpty(paths)) {
            return;
        }

        // 获取所有上级分类id列表
        List<CategoryVO> categoryList = categoryMapper.getListByCategoryIds(paths);
        ProductLangUtil.categoryList(categoryList);
        List<ParentCategoryVO> parentCategoryList = BeanUtil.mapAsList(categoryList, ParentCategoryVO.class);
        Map<Long, ParentCategoryVO> categoryMap = parentCategoryList.stream().collect(Collectors.toMap(ParentCategoryVO::getCategoryId, c -> c));
        // 获取每个分类的上级分类名称集合
        for (CategoryVO category : categories) {
            if (StrUtil.isBlank(category.getPath())) {
                continue;
            }
            String[] parentIdArray = category.getPath().split(Constant.CATEGORY_INTERVAL);
            category.setCategories(new ArrayList<>(0));
            for (String s : parentIdArray) {
                ParentCategoryVO categoryVO = categoryMap.get(Long.valueOf(s));
                category.getCategories().add(categoryVO);
            }
        }
    }

    @Override
    public List<CategoryAppVO> listByShopIdAndParenId(Long shopId, Long parentId, Integer lang) {
        CategoryServiceImpl categoryService = (CategoryServiceImpl) AopContext.currentProxy();
        List<CategoryAppVO> allList = categoryService.shopCategoryList(shopId, lang);
        List<CategoryAppVO> categoryList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (CategoryAppVO categoryVO : allList) {
            // 一级分类
            if (Objects.equals(parentId, Constant.DEFAULT_ID)) {
                categoryVO.setCategories(null);
                categoryList.add(categoryVO);
                continue;
            }
            // 二级分类
            if (Objects.equals(parentId, categoryVO.getCategoryId())) {
                for (CategoryAppVO category : categoryVO.getCategories()) {
                    category.setCategories(null);
                    categoryList.add(category);
                }
                return categoryList;
            }
            // 三级分类
            if (Objects.equals(shopId, Constant.PLATFORM_SHOP_ID)) {
                for (CategoryAppVO category : categoryVO.getCategories()) {
                    if (Objects.equals(parentId, category.getCategoryId())) {
                        categoryList.addAll(category.getCategories());
                        return categoryList;
                    }
                }
            }
        }
        return categoryList;
    }

    @Override
    @Cacheable(cacheNames = CacheNames.CATEGORY_LIST_OF_SHOP, key = "#shopId + ':' + #lang")
    public List<CategoryAppVO> shopCategoryList(Long shopId, Integer lang) {
        List<CategoryVO> list = categoryMapper.listByShopIdAndParenId(shopId, null);
        ProductLangUtil.categoryList(list);

        Map<Integer, List<CategoryAppVO>> categoryMap = BeanUtil.mapAsList(list, CategoryAppVO.class).stream().collect(Collectors.groupingBy(CategoryAppVO::getLevel));

        List<CategoryAppVO> secondCategories = categoryMap.get(CategoryLevel.SECOND.value());
        if (Objects.equals(shopId, Constant.PLATFORM_SHOP_ID)) {
            // 三级分类
            List<CategoryAppVO> thirdCategories = categoryMap.get(CategoryLevel.THIRD.value());
            //二级分类
            setChildCategory(secondCategories, thirdCategories);
        }
        //一级分类
        List<CategoryAppVO> firstCategories = categoryMap.get(CategoryLevel.First.value());
        setChildCategory(firstCategories, secondCategories);
        if (Objects.isNull(firstCategories)) {
            firstCategories = new ArrayList<>(0);
        }
        firstCategories.sort(Comparator.comparing(CategoryAppVO::getSeq).reversed().thenComparing(CategoryAppVO::getCategoryId));
        return firstCategories;
    }

    @Override
    @Cacheable(cacheNames = CacheNames.LIST_SIGNING_CATEGORY, key = "#shopId + ':' + #sysType + ':' + #lang")
    public List<CategoryAppVO> listSigningCategory(Long shopId, Integer sysType, Integer lang) {
        List<CategoryVO> threeCategoryList = categoryMapper.listSigningCategoryByShopIdAndStatus(shopId, sysType, null);
        if (Objects.isNull(threeCategoryList) || threeCategoryList.size() == 0) {
            // 签约分类为空时
            return new ArrayList<>(0);
        }
        ProductLangUtil.categoryList(threeCategoryList);
        List<CategoryVO> twoCategoryList = categoryMapper.getListByCategoryIds(threeCategoryList.stream().map(CategoryVO::getParentId).collect(Collectors.toSet()));
        ProductLangUtil.categoryList(twoCategoryList);
        List<CategoryVO> oneCategoryList = categoryMapper.getListByCategoryIds(twoCategoryList.stream().map(CategoryVO::getParentId).collect(Collectors.toSet()));
        ProductLangUtil.categoryList(oneCategoryList);
        threeCategoryList.addAll(twoCategoryList);
        threeCategoryList.addAll(oneCategoryList);
        return BeanUtil.mapAsList(threeCategoryList, CategoryAppVO.class);
    }

    @Override
    public List<CategoryVO> listByCategoryIds(Set<Long> categoryIds) {
        if (CollUtil.isEmpty(categoryIds)) {
            return new ArrayList<>(0);
        }
        return categoryMapper.listByCategoryIds(categoryIds);
    }

    @Override
    public List<CategoryVO> listAndLangInfoByShopId(Long shopId) {
        return categoryMapper.list(shopId, CategoryLevel.SECOND.value());
    }

    @Override
    public List<CategoryVO> getShopSigningCategoryAndLangInfo(Long shopId) {
        return categoryMapper.listSigningCategoryByShopIdAndStatus(shopId, null, null);
    }

    @Override
    public List<CategoryAppVO> platformCategories() {
        List<CategoryAppVO> list = list(Constant.PLATFORM_SHOP_ID);
        // 排序规则：分类等级正序-> 分类序号倒序-> 分类id正序
        list.sort(Comparator.comparingInt(CategoryAppVO::getLevel)
                .thenComparingInt(CategoryAppVO::getSeq).reversed()
                .thenComparingLong(CategoryAppVO::getCategoryId)
        );
        return list;
    }

    @Override
    public List<Long> getParentIdsByCategoryId(List<Long> categoryIds) {
        if (CollUtil.isEmpty(categoryIds)) {
            return null;
        }
        return categoryMapper.getParentIdsByCategoryId(categoryIds);
    }

    @Override
    public List<PlatformCommissionOrderItemBO> listBySkuIds(List<PlatformCommissionOrderItemBO> platformCommissionOrderItems) {
        return categoryMapper.listBySkuIds(platformCommissionOrderItems);
    }

    @Override
    @Cacheable(cacheNames = CacheNames.CATEGORY_RATE, key = "'0'")
    public List<CategoryRateBO> listRate() {
        return categoryMapper.listRate();
    }

    private void setChildCategory(List<CategoryAppVO> categories, List<CategoryAppVO> childCategories) {
        if (CollUtil.isEmpty(categories)) {
            return;
        }
        if (CollUtil.isEmpty(childCategories)) {
            categories.clear();
            return;
        }
        Map<Long, List<CategoryAppVO>> secondCategoryMap = childCategories.stream().collect(Collectors.groupingBy(CategoryAppVO::getParentId));
        Iterator<CategoryAppVO> iterator = categories.iterator();
        while (iterator.hasNext()) {
            CategoryAppVO categoryVO = iterator.next();
            List<CategoryAppVO> categoryList = secondCategoryMap.get(categoryVO.getCategoryId());
            if (CollUtil.isEmpty(categoryList)) {
                iterator.remove();
                continue;
            }
            categoryList.forEach(item -> item.setParentName(categoryVO.getName()));
            categoryList.sort(Comparator.comparingInt(CategoryAppVO::getSeq).reversed().thenComparing(CategoryAppVO::getCategoryId));
            categoryVO.setCategories(categoryList);
        }
    }

    /**
     * 处理分类名称
     *
     * @param categoryLangList 分类国际化信息
     * @param lang             语言
     * @return 分类名称
     */
    private String handleCategoryName(List<CategoryLangVO> categoryLangList, Integer lang) {
        if (CollUtil.isEmpty(categoryLangList)) {
            return null;
        }
        String categoryName = null;
        for (CategoryLangVO categoryLangVO : categoryLangList) {
            if (Objects.equals(categoryLangVO.getLang(), lang)) {
                categoryName = categoryLangVO.getName();
                break;
            }
        }
        return categoryName;
    }

    @Override
    public List<CategoryAppVO> listPlatformCategoryByShopIdAndParenId(Long shopId, Long parentId, Integer lang) {
        CategoryServiceImpl categoryService = (CategoryServiceImpl) AopContext.currentProxy();
        List<CategoryAppVO> allList = categoryService.shopCategoryList(shopId, lang);
        List<CategoryAppVO> categoryList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (CategoryAppVO categoryVO : allList) {
            boolean flag = false;
            // 只返回 包含并且处于启用状态的三级分类 的一级分类
            outerLoop:
            for (CategoryAppVO secondCategory : categoryVO.getCategories()) {
                for (CategoryAppVO thirdCategory : secondCategory.getCategories()) {
                    if (Objects.equals(thirdCategory.getStatus(), 1)) {
                        flag = true;
                        break outerLoop;
                    }
                }
            }
            categoryVO.setCategories(null);
            if (flag) {
                categoryList.add(categoryVO);
            }
        }
        return categoryList;
    }

    @Override
    public List<CategoryVO> listEnable(Long shopId) {
        return categoryMapper.listEnable(shopId, CategoryLevel.SECOND.value());
    }

    @Override
    public CategorySearchAppVO categorySearchItem(Long categoryId) {
        CategorySearchAppVO categorySearch = new CategorySearchAppVO();
        CategoryServiceImpl categoryService = (CategoryServiceImpl) AopContext.currentProxy();
        CategoryVO category = categoryService.getById(categoryId);
        if (Objects.isNull(category)) {
            return categorySearch;
        }
        Integer lang = I18nMessage.getLang();
        categorySearch.setCategoryVO(new ArrayList<>(0));
        List<CategoryAppVO> allList = categoryService.shopCategoryList(category.getShopId(), lang);
        for (CategoryAppVO categoryVO : allList) {
            boolean notThisFirst = Objects.equals(category.getLevel(), CategoryLevel.First.value()) && !Objects.equals(category.getCategoryId(), categoryVO.getCategoryId());
            boolean notThisSecond = Objects.equals(category.getLevel(), CategoryLevel.SECOND.value()) && !Objects.equals(category.getParentId(), categoryVO.getCategoryId());
            // 不包含该一、二级分类
            if (notThisFirst || notThisSecond || CollUtil.isEmpty(categoryVO.getCategories())) {
                continue;
            }

            List<CategoryAppVO> secondaryCategories = categoryVO.getCategories();

            List<Long> secondaryCategoryIds = secondaryCategories.stream().map(CategoryAppVO::getCategoryId).collect(Collectors.toList());

            // 不包含该三级分类
            if (Objects.equals(category.getLevel(), CategoryLevel.THIRD.value()) && !secondaryCategoryIds.contains(category.getParentId())) {
                continue;
            }

            // 查询一、二级分类
            categorySearch.setPrimaryCategory(categoryVO);
            categorySearch.setSecondaryCategory(categoryVO.getCategories());

            if (Objects.equals(category.getLevel(), CategoryLevel.First.value())) {
                return categorySearch;
            }

            Map<Long, CategoryAppVO> secondaryCategoryMap = categoryVO.getCategories().stream().collect(Collectors.toMap(CategoryAppVO::getCategoryId, c -> c));
            CategoryAppVO secondaryCategory;
            // 查询二级分类
            if (Objects.equals(category.getLevel(), CategoryLevel.SECOND.value())) {
                secondaryCategory = secondaryCategoryMap.get(category.getCategoryId());
            }
            // 查询三级分类
            else {
                secondaryCategory = secondaryCategoryMap.get(category.getParentId());
            }
            if (Objects.isNull(secondaryCategory)) {
                return categorySearch;
            }
            categorySearch.setCategoryVO(secondaryCategory.getCategories());
            break;
        }
        return categorySearch;
    }

    @Override
    public List<CategoryVO> listApplySigningCategory(Long shopId, Integer sysType) {
        List<CategoryVO> thirdLevelplatformCategoryIdList = categoryMapper.listEnable(Constant.PLATFORM_SHOP_ID, CategoryLevel.THIRD.value());
        List<Long> shopSigningCategoryIdList = categoryShopService.getCategoryIdsByShopId(shopId, sysType);
        Set<Long> applyCategoryIdSet = new HashSet<>(shopSigningCategoryIdList);
        // 过滤已经签约的分类
        List<CategoryVO> resultCategoryList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (CategoryVO categoryVO : thirdLevelplatformCategoryIdList) {
            if (!applyCategoryIdSet.contains(categoryVO.getCategoryId())) {
                resultCategoryList.add(categoryVO);
            }
        }
        if (resultCategoryList.size() == 0) {
            return resultCategoryList;
        }
        ProductLangUtil.categoryList(resultCategoryList);
        // 二级分类
        List<CategoryVO> secondLevelCategoryList = categoryMapper.getListByCategoryIds(resultCategoryList.stream().map(CategoryVO::getParentId).collect(Collectors.toSet()));
        ProductLangUtil.categoryList(secondLevelCategoryList);
        resultCategoryList.addAll(secondLevelCategoryList);
        // 一级分类
        List<CategoryVO> firstLevelCategoryList = categoryMapper.getListByCategoryIds(secondLevelCategoryList.stream().map(CategoryVO::getParentId).collect(Collectors.toSet()));
        ProductLangUtil.categoryList(firstLevelCategoryList);
        resultCategoryList.addAll(firstLevelCategoryList);

        return resultCategoryList;
    }

    @Override
    public List<CategoryPlatformExcelVO> listExcelPlatform() {
        List<CategoryPlatformExcelVO> categoryAndLangList = categoryMapper.listPlatformCategoryAndLangList();
        if (CollUtil.isEmpty(categoryAndLangList)) {
            return new ArrayList<>(0);
        }
        for (CategoryPlatformExcelVO categoryPlatformExcelVO : categoryAndLangList) {
            Map<Integer, String> map = categoryPlatformExcelVO.getCategoryLangList().stream().collect(Collectors.toMap(CategoryLangVO::getLang, CategoryLangVO::getName));
            categoryPlatformExcelVO.setNameZh(map.get(LanguageEnum.LANGUAGE_ZH_CN.getLang()));
        }
        Map<Long, List<CategoryPlatformExcelVO>> categoryMap = categoryAndLangList.stream().filter(category -> Objects.nonNull(category.getParentId())).collect(Collectors.groupingBy(CategoryPlatformExcelVO::getParentId));
        if (CollUtil.isEmpty(categoryMap.get(0L))) {
            return new ArrayList<>(0);
        }
        List<CategoryPlatformExcelVO> result = new ArrayList<>(Constant.INITIAL_CAPACITY);
        getCategoryToExcel(categoryMap.get(0L), "", categoryMap, result);
        return result;
    }

    @Override
    public List<CategoryExcelVO> listExcel(Long shopId) {
        List<CategoryExcelVO> categoryAndLangList = categoryMapper.listShopCategoryAndLangList(shopId);
        if (CollUtil.isEmpty(categoryAndLangList)) {
            return new ArrayList<>(0);
        }
        for (CategoryExcelVO categoryExcelVO : categoryAndLangList) {
            Map<Integer, String> map = categoryExcelVO.getCategoryLangList().stream().collect(Collectors.toMap(CategoryLangVO::getLang, CategoryLangVO::getName));
            categoryExcelVO.setNameZh(map.get(LanguageEnum.LANGUAGE_ZH_CN.getLang()));
        }
        Map<Long, List<CategoryExcelVO>> categoryMap = categoryAndLangList.stream().filter(category -> Objects.nonNull(category.getParentId())).collect(Collectors.groupingBy(CategoryExcelVO::getParentId));
        if (CollUtil.isEmpty(categoryMap.get(0L))) {
            return new ArrayList<>(0);
        }
        List<CategoryExcelVO> result = new ArrayList<>(Constant.INITIAL_CAPACITY);
        getShopCategoryToExcel(categoryMap.get(0L), "", categoryMap, result);
        return result;
    }

    private void getShopCategoryToExcel(List<CategoryExcelVO> categories, String parentCategoryNames, Map<Long, List<CategoryExcelVO>> categoryMap, List<CategoryExcelVO> result) {
        if (CollUtil.isEmpty(categories)) {
            return;
        }
        for (CategoryExcelVO category : categories) {
            CategoryExcelVO shopExcelVO = new CategoryExcelVO();
            shopExcelVO.setNameZh(category.getNameZh());
            String categoryGrade = PRIMARY_CATEGORY;
            if (Objects.equals(category.getLevel(), CategoryLevel.SECOND.value())) {
                categoryGrade = SECONDARY_CATEGORY;
            }
            shopExcelVO.setGrade(categoryGrade);
            shopExcelVO.setParentName(parentCategoryNames);
            shopExcelVO.setCategoryStatus(Objects.equals(category.getStatus(), 1) ? "启用" : "禁用");
            shopExcelVO.setSeq(category.getSeq());
            result.add(shopExcelVO);
            if (categoryMap.containsKey(category.getCategoryId())) {
                // 写入该分类的下级分类
                String parentNames = parentCategoryNames.length() == 0 ? category.getNameZh() : parentCategoryNames + "/" + category.getNameZh();
                getShopCategoryToExcel(categoryMap.get(category.getCategoryId()), parentNames, categoryMap, result);
            }
        }
    }

    private void getCategoryToExcel(List<CategoryPlatformExcelVO> categories, String parentCategoryNames, Map<Long, List<CategoryPlatformExcelVO>> categoryMap, List<CategoryPlatformExcelVO> result) {
        if (CollUtil.isEmpty(categories)) {
            return;
        }
        for (CategoryPlatformExcelVO category : categories) {
            CategoryPlatformExcelVO platformExcelVO = new CategoryPlatformExcelVO();
            platformExcelVO.setNameZh(category.getNameZh());
            platformExcelVO.setPlatformRate(Objects.equals(category.getLevel(), CategoryLevel.THIRD.value()) ? category.getPlatformRate() : null);
            String categoryGrade = PRIMARY_CATEGORY;
            if (Objects.equals(category.getLevel(), CategoryLevel.SECOND.value())) {
                categoryGrade = SECONDARY_CATEGORY;
            } else if (Objects.equals(category.getLevel(), CategoryLevel.THIRD.value())) {
                categoryGrade = TERTIARY_CATEGORY;
            }
            platformExcelVO.setGrade(categoryGrade);
            platformExcelVO.setParentName(parentCategoryNames);
            platformExcelVO.setCategoryStatus(Objects.equals(category.getStatus(), 1) ? "启用" : "禁用");
            platformExcelVO.setSeq(category.getSeq());
            result.add(platformExcelVO);
            if (categoryMap.containsKey(category.getCategoryId())) {
                // 写入该分类的下级分类
                String parentNames = parentCategoryNames.length() == 0 ? category.getNameZh() : parentCategoryNames + "/" + category.getNameZh();
                getCategoryToExcel(categoryMap.get(category.getCategoryId()), parentNames, categoryMap, result);
            }
        }
    }
}
