package com.corewing.app.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.corewing.app.dto.ResourceCategoryTreeRequest;
import com.corewing.app.entity.AppModelCategory;
import com.corewing.app.entity.BizResourceCategory;
import com.corewing.app.mapper.BizResourceCategoryMapper;
import com.corewing.app.service.BizResourceCategoryService;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Service
public class BizResourceCategoryServiceImpl extends ServiceImpl<BizResourceCategoryMapper, BizResourceCategory> implements BizResourceCategoryService {


    @Override
    public List<Tree<String>> tree(ResourceCategoryTreeRequest resourceCategoryTreeRequest) {
        LambdaQueryWrapper<BizResourceCategory> queryWrapper = new LambdaQueryWrapper<>();
        List<BizResourceCategory> resourceList = list(queryWrapper);

        // 填充上层的父级菜单
        this.fillParentCategoryInfo(resourceList);

        List<TreeNode<String>> treeNodeList = resourceList.stream().map(category ->
                        new TreeNode<>(category.getId(), category.getParentId(),
                                category.getCategoryName(), category.getSortCode()).setExtra(JSONUtil.parseObj(category)))
                .collect(Collectors.toList());
        return TreeUtil.build(treeNodeList, "0");
    }

    private void fillParentCategoryInfo(List<BizResourceCategory> categoryList) {
        if(CollUtil.isNotEmpty(categoryList)){
            List<BizResourceCategory> parentResourceCategoryList = categoryList.stream().filter(distinctByKey(BizResourceCategory::getParentId)).collect(Collectors.toList());

            List<String> parentIds = null;
            if(CollUtil.isNotEmpty(parentResourceCategoryList)){
                parentIds = CollUtil.newArrayList();
                for(BizResourceCategory parentCategory : categoryList){
                    if(!StrUtil.equals(parentCategory.getParentId(),"0")){
                        parentIds.add(parentCategory.getParentId());
                    }
                }
            }
            if(CollUtil.isNotEmpty(parentIds)){
                LambdaQueryWrapper<BizResourceCategory> parentCategoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
                parentCategoryLambdaQueryWrapper.in(BizResourceCategory::getId,parentIds);
                List<BizResourceCategory> parentCategoryList = this.list(parentCategoryLambdaQueryWrapper);
                if(CollUtil.isNotEmpty(parentCategoryList)){
                    this.fillParentCategoryInfo(parentCategoryList);
                    categoryList.addAll(parentCategoryList);
                }
            }
        }
    }

    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }
}
