package com.corewing.app.service.impl;

import cn.dev33.satoken.stp.StpUtil;
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.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.corewing.app.common.page.PageContext;
import com.corewing.app.dto.AppModel.ModelCategoryListRequest;
import com.corewing.app.dto.AppModel.ModelCategoryPageRequest;
import com.corewing.app.dto.AppModel.ModelDownloadRequest;
import com.corewing.app.dto.AppModel.ModelFavoriteRequest;
import com.corewing.app.entity.AppModel;
import com.corewing.app.entity.AppModelCategory;
import com.corewing.app.entity.AppModelDownloadLog;
import com.corewing.app.entity.AppModelFavorite;
import com.corewing.app.handler.GlobalExceptionHandler;
import com.corewing.app.mapper.AppModelCategoryMapper;
import com.corewing.app.service.AppModelCategoryService;
import com.corewing.app.service.AppModelDownloadLogService;
import com.corewing.app.service.AppModelFavoriteService;
import com.corewing.app.service.AppModelService;
import com.corewing.app.util.CommonServletUtil;
import com.corewing.app.util.IpUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
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 AppModelCategoryServiceImpl extends ServiceImpl<AppModelCategoryMapper, AppModelCategory> implements AppModelCategoryService {

    @Resource
    private AppModelCategoryMapper appModelCategoryMapper;

    @Override
    public Page<AppModelCategory> page(ModelCategoryPageRequest modelCategoryPageRequest) {
        Page<AppModelCategory> page = PageContext.getDefaultPage(AppModelCategory.class);
        return appModelCategoryMapper.page(page, modelCategoryPageRequest);
    }

    @Override
    public List<AppModelCategory> list(ModelCategoryListRequest modelCategoryListRequest) {
        return appModelCategoryMapper.list(modelCategoryListRequest);
    }

    @Override
    public List<Tree<String>> tree(ModelCategoryListRequest modelCategoryListRequest) {
        List<AppModelCategory> resourceList = appModelCategoryMapper.list(modelCategoryListRequest);

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

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


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

            List<String> parentIds = null;
            if(CollUtil.isNotEmpty(parentModelCategoryList)){
                parentIds = CollUtil.newArrayList();
                for(AppModelCategory parentCategory : categoryList){
                    if(!StrUtil.equals(parentCategory.getParentId(),"0")){
                        parentIds.add(parentCategory.getParentId());
                    }
                }
            }
            if(CollUtil.isNotEmpty(parentIds)){
                LambdaQueryWrapper<AppModelCategory> parentCategoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
                parentCategoryLambdaQueryWrapper.in(AppModelCategory::getId,parentIds);
                List<AppModelCategory> 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));
    }
}
