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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import com.tmerclub.cloud.api.product.util.ProductLangUtil;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.i18n.I18nMessage;
import com.tmerclub.cloud.common.product.vo.BrandVO;
import com.tmerclub.cloud.common.product.vo.CategoryVO;
import com.tmerclub.cloud.common.product.vo.ParentCategoryVO;
import com.tmerclub.cloud.common.util.BeanUtil;
import com.tmerclub.cloud.product.mapper.CategoryBrandMapper;
import com.tmerclub.cloud.product.mapper.CategoryMapper;
import com.tmerclub.cloud.product.model.CategoryBrand;
import com.tmerclub.cloud.product.service.CategoryBrandService;
import com.tmerclub.cloud.product.vo.BrandShopVO;
import org.springframework.beans.factory.annotation.Autowired;
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 CategoryBrandServiceImpl implements CategoryBrandService {

    @Autowired
    private CategoryBrandMapper categoryBrandMapper;

    @Autowired
    private CategoryMapper categoryMapper;


    @Override
    public void deleteByBrandIdList(List<Long> brandIdList) {
        categoryBrandMapper.deleteByBrandId(brandIdList);
    }

    @Override
    public void saveByCategoryIds(Long brandId, List<Long> categoryIds) {
        List<CategoryBrand> categoryBrandList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        categoryIds.forEach(categoryId -> {
            CategoryBrand categoryBrand = new CategoryBrand();
            categoryBrand.setBrandId(brandId);
            categoryBrand.setCategoryId(categoryId);
            categoryBrandList.add(categoryBrand);
        });
        categoryBrandMapper.saveBatch(categoryBrandList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateByCategoryIds(Long brandId, List<Long> categoryIds) {
        List<Long> categoryIdDb = getCategoryIdBrandId(brandId);
        // 删除分类或者没有绑定分类
        if (CollUtil.isEmpty(categoryIds)) {
            if (CollUtil.isNotEmpty(categoryIdDb)) {
                categoryBrandMapper.deleteByBrandIdAndCategoryIds(brandId, categoryIdDb);
            }
            return;
        }
        // 新增绑定分类或者更新
        List<Long> addList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        categoryIds.forEach(categoryId -> {
            if (!categoryIdDb.contains(categoryId)) {
                addList.add(categoryId);
            }
        });
        if (CollUtil.isNotEmpty(addList)) {
            saveByCategoryIds(brandId, addList);
        }
        categoryIdDb.removeAll(categoryIds);
        if (CollUtil.isNotEmpty(categoryIdDb)) {
            categoryBrandMapper.deleteByBrandIdAndCategoryIds(brandId, categoryIdDb);
        }
    }

    @Override
    public List<Long> getCategoryIdBrandId(Long brandId) {
        return categoryBrandMapper.getCategoryIdsByBrandId(brandId);
    }

    @Override
    public List<CategoryVO> getCategoryByBrandId(Long brandId) {
        List<CategoryVO> categoryVO = categoryBrandMapper.getCategoryByBrandId(brandId, I18nMessage.getLang());
        ProductLangUtil.categoryList(categoryVO);
        return categoryVO;
    }

    @Override
    public int countByBrandIdAndCategoryId(Long brandId, Long categoryId) {
        return categoryBrandMapper.countByBrandIdAndCategoryId(brandId, categoryId);
    }

    @Override
    public void loadCategoryToBrandVO(List<BrandVO> brandList) {
        if (CollUtil.isEmpty(brandList)) {
            return;
        }

        Set<Long> categoryIds = new HashSet<>(Constant.INITIAL_CAPACITY);
        for (BrandVO brandVO : brandList) {
            if (CollUtil.isNotEmpty(brandVO.getCategoryIds())) {
                categoryIds.addAll(brandVO.getCategoryIds());
            }
        }

        Map<Long, CategoryVO> categoryMap = getCategoryAndParentMap(categoryIds);
        for (BrandVO brandVO : brandList) {
            brandVO.setCategories(loadBrandCategoryList(brandVO.getCategoryIds(), categoryMap));
            brandVO.setCategoryIds(null);
        }
    }

    @Override
    public void loadCategoryToBrandSigningVO(List<BrandShopVO> brandList) {
        if (CollUtil.isEmpty(brandList)) {
            return;
        }

        Set<Long> categoryIds = new HashSet<>(Constant.INITIAL_CAPACITY);
        for (BrandShopVO brandVO : brandList) {
            if (CollUtil.isNotEmpty(brandVO.getCategoryIds())) {
                categoryIds.addAll(brandVO.getCategoryIds());
            }
        }

        Map<Long, CategoryVO> categoryMap = getCategoryAndParentMap(categoryIds);
        for (BrandShopVO brandVO : brandList) {
            brandVO.setCategories(loadBrandCategoryList(brandVO.getCategoryIds(), categoryMap));
            brandVO.setCategoryIds(null);
        }
    }

    private Map<Long, CategoryVO> getCategoryAndParentMap(Set<Long> categoryIds) {
        Map<Long, CategoryVO> categoryMap = new HashMap<>(Constant.INITIAL_CAPACITY);
        List<CategoryVO> categoryVOList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        if (CollUtil.isNotEmpty(categoryIds)) {
            categoryVOList = categoryMapper.listCategoryAndParentInfo(categoryIds);
        }
        if (CollUtil.isEmpty(categoryVOList)) {
            return categoryMap;
        }
        ProductLangUtil.categoryList(categoryVOList);
        categoryMap = categoryVOList.stream().collect(Collectors.toMap(CategoryVO::getCategoryId, c -> c));
        return categoryMap;
    }

    @Override
    public void saveBatch(List<CategoryBrand> categoryBrands) {
        if (CollUtil.isEmpty(categoryBrands)) {
            return;
        }
        categoryBrandMapper.saveBatch(categoryBrands);
    }

    private List<CategoryVO> loadBrandCategoryList(List<Long> categoryIds, Map<Long, CategoryVO> categoryMap) {
        if (CollUtil.isEmpty(categoryIds)) {
            return null;
        }
        List<CategoryVO> categoryList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (Long categoryId : categoryIds) {
            if (!categoryMap.containsKey(categoryId)) {
                continue;
            }
            CategoryVO category = categoryMap.get(categoryId);
            category.setCategories(new ArrayList<>(0));
            String[] parentIds = category.getPath().split(Constant.CATEGORY_INTERVAL);
            if (ArrayUtil.isEmpty(parentIds)) {
                continue;
            }
            for (String parentId : parentIds) {
                Long parentCategoryId = Long.valueOf(parentId);
                if (!categoryMap.containsKey(parentCategoryId)) {
                    continue;
                }
                CategoryVO parentCategory = categoryMap.get(parentCategoryId);
                category.getCategories().add(BeanUtil.map(parentCategory, ParentCategoryVO.class));
            }
            categoryList.add(category);
        }
        return categoryList;
    }
}
