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

import cn.hutool.core.collection.CollUtil;
import com.tmerclub.cloud.api.auth.constant.SysTypeEnum;
import com.tmerclub.cloud.api.product.dto.CategoryShopDTO;
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.exception.LuckException;
import com.tmerclub.cloud.common.i18n.I18nMessage;
import com.tmerclub.cloud.common.i18n.LanguageEnum;
import com.tmerclub.cloud.common.product.constant.SpuStatus;
import com.tmerclub.cloud.common.security.AuthUserContext;
import com.tmerclub.cloud.product.bo.CategoryRateBO;
import com.tmerclub.cloud.product.mapper.CategoryShopMapper;
import com.tmerclub.cloud.product.model.CategoryShop;
import com.tmerclub.cloud.product.service.CategoryShopService;
import com.tmerclub.cloud.product.service.SpuService;
import com.tmerclub.cloud.product.vo.CategoryShopVO;
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 lth
 * @date 2021/4/25 14:34
 */
@Service
public class CategoryShopServiceImpl implements CategoryShopService {

    @Autowired
    private CategoryShopMapper categoryShopMapper;

    @Autowired
    private SpuService spuService;


    @Override
    public CategoryShop getById(Long categoryShopId) {
        return categoryShopMapper.getByCategoryShopId(categoryShopId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void signingCategory(List<CategoryShopDTO> categoryShopDTOList, Long shopId, Integer sysType) {
        if (categoryShopDTOList.size() > Constant.SIGNING_CATEGORY_LIMIT_NUM) {
            throw new LuckException("签约的分类信息不能超过" + Constant.SIGNING_CATEGORY_LIMIT_NUM);
        }
        // 处理分类扣率问题
        this.dealWithRate(categoryShopDTOList, shopId, sysType);
        // 删除已签约的平台分类信息
        categoryShopMapper.deleteByShopId(shopId, sysType);
        // 重新插入
        if (CollUtil.isNotEmpty(categoryShopDTOList)) {
            categoryShopMapper.saveBatch(categoryShopDTOList, shopId, sysType);
        }
        // 更新缓存
        this.removeCacheByShopIds(Collections.singletonList(shopId), sysType);
    }


    @Override
    @Cacheable(cacheNames = CacheNames.SIGNING_CATEGORY_BY_SHOP_KEY, key = "#shopId + ':' + #sysType + ':' + #lang")
    public List<CategoryShopVO> listByShopId(Long shopId, Integer sysType, Integer lang) {
        return categoryShopMapper.listByShopId(shopId, lang, sysType);
    }

    @Override
    @Cacheable(cacheNames = CacheNames.CATEGORY_RATE, key = "#shopId + ':' + #sysType")
    public List<CategoryRateBO> listRateByShopId(Long shopId, Integer sysType) {
        List<CategoryRateBO> categoryRateList = categoryShopMapper.listRateByShopId(shopId, sysType);
        if (Objects.isNull(categoryRateList)) {
            categoryRateList = new ArrayList<>(0);
        }
        return categoryRateList;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByCategoryId(Long categoryId) {
        List<Long> shopIdList = categoryShopMapper.listShopIdByCategoryId(categoryId);
        categoryShopMapper.deleteByCategoryId(categoryId);
        // 清除缓存
        removeCacheByShopIds(shopIdList, AuthUserContext.get().getSysType());
    }

    @Override
    public void removeCacheByChangeCategoryId(Long categoryId) {
        if (Objects.isNull(categoryId)) {
            return;
        }
        List<Long> shopIdList = categoryShopMapper.listShopIdByCategoryId(categoryId);
        this.removeCacheByShopIds(shopIdList, AuthUserContext.get().getSysType());
    }

    @Override
    public void removeCacheByChangeCategoryIds(List<Long> categoryIds, Integer sysType) {
        if (CollUtil.isEmpty(categoryIds)) {
            return;
        }
        List<Long> shopIdList = categoryShopMapper.listShopIdByCategoryIds(categoryIds);
        this.removeCacheByShopIds(shopIdList, sysType);
    }

    @Override
    public CategoryShopVO getByShopIdAndCategoryId(Long shopId, Long categoryId, Integer sysType) {
        return categoryShopMapper.getByShopIdAndCategoryId(shopId, categoryId, sysType);
    }

    @Override
    public List<Long> getSupplierIdsByShopId(Long shopId) {
        return categoryShopMapper.getSupplierIdsByShopId(shopId);
    }

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

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteSigningCategory(CategoryShop categoryShop) {
        if (Objects.isNull(categoryShop)) {
            return;
        }
        Long categoryId = categoryShop.getCategoryId();
        int spuCount = spuService.countByCategoryAndShopId(categoryId, categoryShop.getShopId(), categoryShop.getSysType());
        if (spuCount > 0) {
            throw new LuckException("该分类下还有商品正在出售，请先删除此分类下的商品");
        }
        spuService.batchChangeSpuStatusByCidListAndShopId(Collections.singletonList(categoryId), SpuStatus.OFF_SHELF.value(), categoryShop.getShopId(), categoryShop.getSysType());
        categoryShopMapper.deleteById(categoryShop.getCategoryShopId());
        this.removeCacheByShopIds(Collections.singletonList(categoryShop.getShopId()), categoryShop.getSysType());
    }

    @Override
    public List<Long> getCategoryIdsByShopId(Long shopId, Integer sysType) {
        return categoryShopMapper.getCategoryIdsByShopId(shopId, sysType);
    }

    /**
     * 根据店铺id列表清除缓存
     *
     * @param shopIdList
     */
    private void removeCacheByShopIds(List<Long> shopIdList, Integer sysType) {
        if (CollUtil.isEmpty(shopIdList)) {
            return;
        }
        List<String> keyList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        // 此前传递的sysType参数在某些情况下实际上无法起作用，因为大部分对分类信息的操作都在平台端进行，此时传递的sysType为平台端，而我们的目的是删除商家端和供应商端的缓存记录
        shopIdList.forEach(shopId -> {
            keyList.add(CacheNames.CATEGORY_RATE + CacheNames.UNION + shopId + CacheNames.UNION_KEY + SysTypeEnum.SUPPLIER.value());
            keyList.add(CacheNames.CATEGORY_RATE + CacheNames.UNION + shopId + CacheNames.UNION_KEY + SysTypeEnum.PLATFORM.value());
            keyList.add(CacheNames.CATEGORY_RATE + CacheNames.UNION + shopId + CacheNames.UNION_KEY + SysTypeEnum.MULTISHOP.value());
            keyList.add(CacheNames.CATEGORY_LIST_OF_SHOP + CacheNames.UNION + shopId + CacheNames.UNION_KEY + LanguageEnum.LANGUAGE_ZH_CN.getLang());
            keyList.add(CacheNames.CATEGORY_LIST_OF_SHOP + CacheNames.UNION + shopId + CacheNames.UNION_KEY + LanguageEnum.LANGUAGE_EN.getLang());
            // 商家端
            keyList.add(CacheNames.SIGNING_CATEGORY_BY_SHOP_KEY + CacheNames.UNION + shopId + CacheNames.UNION_KEY + SysTypeEnum.MULTISHOP.value() + CacheNames.UNION_KEY + LanguageEnum.LANGUAGE_ZH_CN.getLang());
            keyList.add(CacheNames.SIGNING_CATEGORY_BY_SHOP_KEY + CacheNames.UNION + shopId + CacheNames.UNION_KEY + SysTypeEnum.MULTISHOP.value() + CacheNames.UNION_KEY + LanguageEnum.LANGUAGE_EN.getLang());
            keyList.add(CacheNames.LIST_SIGNING_CATEGORY + CacheNames.UNION + shopId + CacheNames.UNION_KEY + SysTypeEnum.MULTISHOP.value() + CacheNames.UNION_KEY + LanguageEnum.LANGUAGE_ZH_CN.getLang());
            keyList.add(CacheNames.LIST_SIGNING_CATEGORY + CacheNames.UNION + shopId + CacheNames.UNION_KEY + SysTypeEnum.MULTISHOP.value() + CacheNames.UNION_KEY + LanguageEnum.LANGUAGE_EN.getLang());
            // 供应商端
            keyList.add(CacheNames.SIGNING_CATEGORY_BY_SHOP_KEY + CacheNames.UNION + shopId + CacheNames.UNION_KEY + SysTypeEnum.SUPPLIER.value() + CacheNames.UNION_KEY + LanguageEnum.LANGUAGE_ZH_CN.getLang());
            keyList.add(CacheNames.SIGNING_CATEGORY_BY_SHOP_KEY + CacheNames.UNION + shopId + CacheNames.UNION_KEY + SysTypeEnum.SUPPLIER.value() + CacheNames.UNION_KEY + LanguageEnum.LANGUAGE_EN.getLang());
            keyList.add(CacheNames.LIST_SIGNING_CATEGORY + CacheNames.UNION + shopId + CacheNames.UNION_KEY + SysTypeEnum.SUPPLIER.value() + CacheNames.UNION_KEY + LanguageEnum.LANGUAGE_ZH_CN.getLang());
            keyList.add(CacheNames.LIST_SIGNING_CATEGORY + CacheNames.UNION + shopId + CacheNames.UNION_KEY + SysTypeEnum.SUPPLIER.value() + CacheNames.UNION_KEY + LanguageEnum.LANGUAGE_EN.getLang());

        });
        if (CollUtil.isNotEmpty(keyList)) {
            RedisUtil.deleteBatch(keyList);
        }
    }

    @Override
    public void insertBatchByShopId(List<CategoryShopDTO> categoryShopDTOList, Long shopId, Integer sysType) {
        if (CollUtil.isEmpty(categoryShopDTOList)) {
            return;
        }
        int signedCount = categoryShopMapper.countByShopIdAndCategoryId(shopId, null, sysType);
        if (signedCount + categoryShopDTOList.size() > Constant.SIGNING_CATEGORY_LIMIT_NUM) {
            throw new LuckException("签约的分类信息不能超过" + Constant.SIGNING_CATEGORY_LIMIT_NUM);
        }
        categoryShopMapper.saveBatch(categoryShopDTOList, shopId, sysType);
    }

    private void dealWithRate(List<CategoryShopDTO> categoryShopDTOList, Long shopId, Integer sysType) {
        //查找以前签约的分类信息列表
        List<CategoryShopVO> oldCategoryShopList = categoryShopMapper.listByShopId(shopId, I18nMessage.getLang(), sysType);
        Map<Long, CategoryShopVO> oldCategoryShopMap = oldCategoryShopList.stream().collect(Collectors.toMap(CategoryShopVO::getCategoryId, categoryShopVO -> categoryShopVO));

        categoryShopDTOList.forEach(categoryShopDTO -> {
            // 平台端管理员操作
            if (Objects.equals(AuthUserContext.get().getSysType(), SysTypeEnum.PLATFORM.value())) {
                if (oldCategoryShopMap.containsKey(categoryShopDTO.getCategoryId())) {
                    categoryShopDTO.setCategoryShopId(oldCategoryShopMap.get(categoryShopDTO.getCategoryId()).getCategoryShopId());
                    oldCategoryShopMap.remove(categoryShopDTO.getCategoryId());
                }
                // 店铺或供应商的请求操作
            } else if (Objects.equals(AuthUserContext.get().getSysType(), SysTypeEnum.MULTISHOP.value()) || Objects.equals(AuthUserContext.get().getSysType(), SysTypeEnum.SUPPLIER.value())) {
                if (oldCategoryShopMap.containsKey(categoryShopDTO.getCategoryId())) {
                    categoryShopDTO.setCategoryShopId(oldCategoryShopMap.get(categoryShopDTO.getCategoryId()).getCategoryShopId());
                    // 非平台端操作需要把用户非法添加的自定义扣率清除
                    categoryShopDTO.setRate(oldCategoryShopMap.get(categoryShopDTO.getCategoryId()).getCustomizeRate());
                    oldCategoryShopMap.remove(categoryShopDTO.getCategoryId());
                } else {
                    // 非平台端操作需要把用户非法添加的自定义扣率清除
                    categoryShopDTO.setRate(null);
                }
            } else {
                throw new LuckException("您无权进行此操作");
            }
        });
        this.dealWithDeleteCategoryList(new ArrayList<>(oldCategoryShopMap.keySet()), shopId, sysType);
    }

    /**
     * 处理删除的分类
     *
     * @param categoryIdList
     * @param shopId
     */
    private void dealWithDeleteCategoryList(List<Long> categoryIdList, Long shopId, Integer sysType) {
        spuService.batchChangeSpuStatusByCidListAndShopId(categoryIdList, SpuStatus.OFF_SHELF.value(), shopId, sysType);
    }


    @Override
    public List<Long> getSupplyIdByCategoryIds(List<Long> categoryIds) {
        return categoryShopMapper.getSupplyIdByCategoryIds(categoryIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addSigningCategory(List<CategoryShopDTO> categoryShopDTOList, Long shopId, Integer sysType) {
        if (CollUtil.isEmpty(categoryShopDTOList)) {
            return;
        }
        CategoryShopServiceImpl categoryShopService = (CategoryShopServiceImpl) AopContext.currentProxy();
        List<Long> signingCategoryIdList = categoryShopService.getCategoryIdsByShopId(shopId, sysType);
        Set<Long> signingCategoryIdSet = new HashSet<>(signingCategoryIdList);
        Iterator<CategoryShopDTO> categoryShopIterator = categoryShopDTOList.iterator();
        while (categoryShopIterator.hasNext()) {
            CategoryShopDTO categoryShopDTO = categoryShopIterator.next();
            // 若新增分类列表中存在已签约成功的分类，则将其剔除
            categoryShopDTO.setRate(null);
            if (signingCategoryIdSet.contains(categoryShopDTO.getCategoryId())) {
                categoryShopIterator.remove();
            }
        }
        if (signingCategoryIdList.size() + categoryShopDTOList.size() > Constant.SIGNING_CATEGORY_LIMIT_NUM) {
            throw new LuckException("签约分类的总数不能超过200");
        }
        if (CollUtil.isEmpty(categoryShopDTOList)) {
            return;
        }
        categoryShopMapper.saveBatch(categoryShopDTOList, shopId, sysType);
        this.removeCacheByShopIds(Collections.singletonList(shopId), sysType);

    }
}
