package cn.lili.modules.goods.serviceimpl;

import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.goods.entity.dos.Category;
import cn.lili.modules.goods.entity.dos.CategoryParameterGroup;
import cn.lili.modules.goods.entity.vos.CategoryVO;
import cn.lili.modules.goods.entity.vos.GoodsParamsGroupVO;
import cn.lili.modules.goods.entity.vos.GoodsParamsVO;
import cn.lili.modules.goods.mapper.CategoryMapper;
import cn.lili.modules.goods.service.CategoryBrandService;
import cn.lili.modules.goods.service.CategoryParameterGroupService;
import cn.lili.modules.goods.service.CategoryService;
import cn.lili.modules.goods.service.CategorySpecificationService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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 pikachu
 * @since 2020-02-23 15:18:56
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {

    private static final String DELETE_FLAG_COLUMN = "delete_flag";
    /**
     * 缓存
     */
    @Autowired
    private Cache cache;

    @Autowired
    private CategoryBrandService categoryBrandService;

    @Autowired
    private CategoryParameterGroupService categoryParameterGroupService;

    @Autowired
    private CategorySpecificationService categorySpecificationService;

    @Override
    public List<Category> dbList(String parentId) {
        return this.list(new LambdaQueryWrapper<Category>().eq(Category::getParentId, parentId));
    }

    /**
     * 根据分类id集合获取所有分类根据层级排序
     *
     * @param ids 分类ID集合
     * @return 商品分类列表
     */
    @Override
    public List<Category> listByIdsOrderByLevel(List<String> ids) {
        return this.list(new LambdaQueryWrapper<Category>().in(Category::getId, ids).orderByAsc(Category::getLevel));
    }

    @Override
    public List<CategoryVO> categoryTree() {
        List<CategoryVO> categoryVOList = (List<CategoryVO>) cache.get(CachePrefix.CATEGORY.getPrefix());
        if (categoryVOList != null) {
            return categoryVOList;
        }

        //获取全部分类
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Category::getDeleteFlag, false);
        List<Category> list = this.list(queryWrapper);

        //构造分类树
        categoryVOList = new ArrayList<>();
        for (Category category : list) {
            if ("0".equals(category.getParentId())) {
                CategoryVO categoryVO = new CategoryVO(category);
                categoryVO.setChildren(findChildren(list, categoryVO));
                categoryVOList.add(categoryVO);
            }
        }
        categoryVOList.sort(Comparator.comparing(Category::getSortOrder));
        if (!categoryVOList.isEmpty()) {
            cache.put(CachePrefix.CATEGORY.getPrefix(), categoryVOList);
            cache.put(CachePrefix.CATEGORY_ARRAY.getPrefix(), list);
        }
        return categoryVOList;
    }

    @Override
    public List<CategoryVO> getStoreCategory(String[] categories) {
        List<String> arr = Arrays.asList(categories.clone());
        return categoryTree().stream()
                .filter(item -> arr.contains(item.getId())).collect(Collectors.toList());
    }

    @Override
    public List<Category> firstCategory() {
        QueryWrapper<Category> queryWrapper = Wrappers.query();
        queryWrapper.eq("level", 0);
        return list(queryWrapper);
    }

    @Override
    public List<CategoryVO> listAllChildren(String parentId) {
        if ("0".equals(parentId)) {
            return categoryTree();
        }
        //循环代码，找到对象，把他的子分类返回
        List<CategoryVO> topCatList = categoryTree();
        for (CategoryVO item : topCatList) {
            if (item.getId().equals(parentId)) {
                return item.getChildren();
            } else {
                return getChildren(parentId, item.getChildren());
            }
        }
        return new ArrayList<>();
    }

    @Override
    public List<CategoryVO> listAllChildren() {

        //获取全部分类
        List<Category> list = this.list();

        //构造分类树
        List<CategoryVO> categoryVOList = new ArrayList<>();
        for (Category category : list) {
            if (("0").equals(category.getParentId())) {
                CategoryVO categoryVO = new CategoryVO(category);
                categoryVO.setChildren(findChildren(list, categoryVO));
                categoryVOList.add(categoryVO);
            }
        }
        categoryVOList.sort(Comparator.comparing(Category::getSortOrder));
        return categoryVOList;
    }

    /**
     * 获取指定分类的分类名称
     *
     * @param ids 指定分类id集合
     * @return 分类名称集合
     */
    @Override
    public List<String> getCategoryNameByIds(List<String> ids) {
        List<String> categoryName = new ArrayList<>();
        List<Category> categoryVOList = (List<Category>) cache.get(CachePrefix.CATEGORY_ARRAY.getPrefix());
        //如果缓存中为空，则重新获取缓存
        if (categoryVOList == null) {
            categoryTree();
            categoryVOList = (List<Category>) cache.get(CachePrefix.CATEGORY_ARRAY.getPrefix());
        }
        //还为空的话，直接返回
        if (categoryVOList == null) {
            return new ArrayList<>();
        }
        //循环顶级分类
        for (Category category : categoryVOList) {
            //循环查询的id匹配
            for (String id : ids) {
                if (category.getId().equals(id)) {
                    //写入商品分类
                    categoryName.add(category.getName());
                }
            }
        }
        return categoryName;
    }

    @Override
    public List<Category> findByAllBySortOrder(Category category) {
        QueryWrapper<Category> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(category.getLevel() != null, "level", category.getLevel())
                .eq(CharSequenceUtil.isNotBlank(category.getName()), "name", category.getName())
                .eq(category.getParentId() != null, "parent_id", category.getParentId())
                .ne(category.getId() != null, "id", category.getId())
                .eq(DELETE_FLAG_COLUMN, false)
                .orderByAsc("sort_order");
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public boolean saveCategory(Category category) {
        //判断分类佣金是否正确
        if (category.getCommissionRate() < 0) {
            throw new ServiceException(ResultCode.CATEGORY_COMMISSION_RATE_ERROR);
        }
        //子分类与父分类的状态一致
        if (category.getParentId() != null && !("0").equals(category.getParentId())) {
            Category parentCategory = this.getById(category.getParentId());
            category.setDeleteFlag(parentCategory.getDeleteFlag());
        }
        this.save(category);
        removeCache();
        return true;
    }

    @Override
    public void updateCategory(Category category) {
        //判断分类佣金是否正确
        if (category.getCommissionRate() < 0) {
            throw new ServiceException(ResultCode.CATEGORY_COMMISSION_RATE_ERROR);
        }
        //判断父分类与子分类的状态是否一致
        if (category.getParentId() != null && !"0".equals(category.getParentId())) {
            Category parentCategory = this.getById(category.getParentId());
            if (!parentCategory.getDeleteFlag().equals(category.getDeleteFlag())) {
                throw new ServiceException(ResultCode.CATEGORY_DELETE_FLAG_ERROR);
            }
        }
        UpdateWrapper<Category> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", category.getId())
                .set("name", category.getName())
                .set("image", category.getImage())
                .set("sort_order", category.getSortOrder())
                .set(DELETE_FLAG_COLUMN, category.getDeleteFlag())
                .set("commission_rate", category.getCommissionRate());
        this.baseMapper.update(category, updateWrapper);
        removeCache();
    }


    @Override
    public void delete(String id) {
        this.removeById(id);
        removeCache();
        //删除关联关系
        categoryBrandService.deleteByCategoryId(id);
        categoryParameterGroupService.deleteByCategoryId(id);
        categorySpecificationService.deleteByCategoryId(id);
    }

    @Override
    public void updateCategoryStatus(String categoryId, Boolean enableOperations) {
        //禁用子分类
        CategoryVO categoryVO = new CategoryVO(this.getById(categoryId));
        List<String> ids = new ArrayList<>();
        ids.add(categoryVO.getId());
        this.findAllChild(categoryVO);
        this.findAllChildIds(categoryVO, ids);
        LambdaUpdateWrapper<Category> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(Category::getId, ids);
        updateWrapper.set(Category::getDeleteFlag, enableOperations);
        this.update(updateWrapper);
        removeCache();
    }

    /**
     * 递归树形VO
     *
     * @param categories 分类列表
     * @param categoryVO 分类VO
     * @return 分类VO列表
     */
    private List<CategoryVO> findChildren(List<Category> categories, CategoryVO categoryVO) {
        List<CategoryVO> children = new ArrayList<>();
        categories.forEach(item -> {
            if (item.getParentId().equals(categoryVO.getId())) {
                CategoryVO temp = new CategoryVO(item);
                temp.setChildren(findChildren(categories, temp));
                children.add(temp);
            }
        });

        return children;
    }

    /**
     * 条件查询分类
     *
     * @param category 分类VO
     */
    private void findAllChild(CategoryVO category) {
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Category::getParentId, category.getId());
        List<Category> categories = this.list(queryWrapper);
        List<CategoryVO> categoryVOList = new ArrayList<>();
        for (Category category1 : categories) {
            categoryVOList.add(new CategoryVO(category1));
        }
        category.setChildren(categoryVOList);
        if (!categoryVOList.isEmpty()) {
            categoryVOList.forEach(this::findAllChild);
        }
    }

    /**
     * 拼装返回值
     *
     * @param paramList 参数列表
     * @return 拼装后的返回值
     */
    private List<GoodsParamsGroupVO> convertParamList(List<CategoryParameterGroup> groupList, List<GoodsParamsVO> paramList) {
        Map<String, List<GoodsParamsVO>> map = new HashMap<>(16);
        for (GoodsParamsVO param : paramList) {
            if (map.get(param.getGroupId()) != null) {
                map.get(param.getGroupId()).add(param);
            } else {
                List<GoodsParamsVO> list = new ArrayList<>();
                list.add(param);
                map.put(param.getGroupId(), list);
            }
        }
        List<GoodsParamsGroupVO> resList = new ArrayList<>();
        for (CategoryParameterGroup group : groupList) {
            GoodsParamsGroupVO list = new GoodsParamsGroupVO();
            list.setGroupName(group.getGroupName());
            list.setGroupId(group.getId());
            list.setParams(map.get(group.getId()));
            resList.add(list);
        }
        return resList;
    }

    /**
     * 获取所有的子分类ID
     *
     * @param category 分类
     * @param ids      ID列表
     */
    private void findAllChildIds(CategoryVO category, List<String> ids) {
        if (category.getChildren() != null && !category.getChildren().isEmpty()) {
            for (CategoryVO child : category.getChildren()) {
                ids.add(child.getId());
                this.findAllChildIds(child, ids);
            }
        }
    }

    /**
     * 递归自身，找到id等于parentId的对象，获取他的children 返回
     *
     * @param parentId       父ID
     * @param categoryVOList 分类VO
     * @return 子分类列表VO
     */
    private List<CategoryVO> getChildren(String parentId, List<CategoryVO> categoryVOList) {
        for (CategoryVO item : categoryVOList) {
            if (item.getId().equals(parentId)) {
                return item.getChildren();
            }
            if (item.getChildren() != null && !item.getChildren().isEmpty()) {
                return getChildren(parentId, categoryVOList);
            }
        }
        return categoryVOList;
    }

    /**
     * 清除缓存
     */
    private void removeCache() {
        cache.remove(CachePrefix.CATEGORY.getPrefix());
    }
}