package com.ssyf.plugs.pedigree;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.Accessors;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 级联树构建工具
 * 级联树：数据之间使用类似id和parentId相互关联的存在上下级关系的数据
 *
 * @author huwei
 * @date 2024/5/25 13:51
 */
public class TreeCascadeBuilder {

    public static final String ID_KEY = "id";

    public static final String PARENT_ID_KEY = "parentId";

    public static final String CHILDREN_KEY = "children";

    public static <T> TreeResult buildTreeResult(List<T> dataList){
        return buildTreeResult(dataList, ID_KEY, PARENT_ID_KEY, CHILDREN_KEY);
    }

    public static <T> TreeResult buildTreeResult(List<T> dataList, String idKey, String parentIdKey, String childrenKey){
        if(dataList == null || dataList.isEmpty()){
            return buildTreeResultFormMapData(null, idKey, parentIdKey, childrenKey);
        }
        List<Map<String, Object>> temp = dataList.stream().map(data -> BeanUtil.beanToMap(data)).collect(Collectors.toList());
        return buildTreeResultFormMapData(temp, idKey, parentIdKey, childrenKey);
    }

    public static TreeResult buildTreeResultFormMapData(List<Map<String, Object>> dataList){
        return buildTreeResultFormMapData(dataList, ID_KEY, PARENT_ID_KEY, CHILDREN_KEY);
    }

    public static TreeResult buildTreeResultFormMapData(List<Map<String, Object>> dataList, String idKey, String parentIdKey, String childrenKey) {
        Map<String, Map<String, Object>> nodeMap = new LinkedHashMap<>(); // 改为LinkedHashMap以保持顺序
        if (dataList == null || dataList.isEmpty()) {
            return new TreeResult(new ArrayList<>(), new ArrayList<>(), nodeMap);
        }

        for (Map<String, Object> data : dataList) {
            String id = getId(data, idKey);
            String parentId = getParentId(data, parentIdKey);
            data.put(childrenKey, getChildren(data, childrenKey, new ArrayList<>()));
            nodeMap.put(id, data);
        }

        for (Map<String, Object> data : dataList) {
            String parentId = getParentId(data, parentIdKey);
            if (parentId == null || StrUtil.isBlank(parentId)) {
                continue;
            }
            Map<String, Object> parentNode = nodeMap.get(parentId);
            List<Map<String, Object>> childrenList = (List<Map<String, Object>>) parentNode.get(childrenKey);
            childrenList.add(data);
        }

        List<Map<String, Object>> result = new ArrayList<>();
        for (Map<String, Object> data : dataList) {
            String id = getId(data, idKey);
            if (!nodeMap.containsKey(id)) {
                continue;
            }
            Map<String, Object> node = nodeMap.get(id);
            String parentId = getParentId(node, parentIdKey);
            if (parentId == null || StrUtil.isBlank(parentId) || !nodeMap.containsKey(parentId)) {
                result.add(node);
            }
        }

        return new TreeResult(result, dataList, nodeMap);
    }

    public static List<Map<String, Object>> buildTreeFormMapData(List<Map<String, Object>> dataList) {
        return buildTreeFormMapData(dataList, ID_KEY, PARENT_ID_KEY, CHILDREN_KEY);
    }

    /**
     * 构建级联树
     *
     * @param dataList    数据列表
     * @param idKey       id字段
     * @param parentIdKey parentId字段
     * @return
     */
    public static List<Map<String, Object>> buildTreeFormMapData(List<Map<String, Object>> dataList, String idKey, String parentIdKey, String childrenKey) {
        return buildTreeResultFormMapData(dataList, idKey, parentIdKey, childrenKey).getTopList();
    }

    public static <T> List<Map<String, Object>> buildTree(List<T> dataList) {
        return buildTree(dataList, ID_KEY, PARENT_ID_KEY, CHILDREN_KEY);
    }

    public static <T> List<Map<String, Object>> buildTree(List<T> dataList, String idKey, String parentIdKey , String childrenKey) {
        if (dataList == null || dataList.isEmpty()) {
            return new ArrayList<>();
        }
        List<Map<String, Object>> temp = dataList.stream().map(data -> BeanUtil.beanToMap(data)).collect(Collectors.toList());
        return buildTreeFormMapData(temp, idKey, parentIdKey, childrenKey);
    }

    private static String getId(Map<String, Object> data, String idKey) {
        Object idObj = data.get(idKey);
        if (idObj == null) {
            throw new IllegalArgumentException("Data does not contain " + idKey + ".");
        }
        return idObj.toString();
    }

    private static String getParentId(Map<String, Object> data, String parentIdKey) {
        Object parentIdObj = data.get(parentIdKey);
        return parentIdObj != null ? parentIdObj.toString() : null;
    }

    private static List<Map<String, Object>> getChildren(Map<String, Object> data, String childrenKey, List<Map<String, Object>> defaultChildren) {
        Object childrenObj = data.get(childrenKey);
        return childrenObj instanceof List ? (List<Map<String, Object>>) childrenObj : defaultChildren;
    }

    @Data
    @Accessors(chain = true)
    @AllArgsConstructor
    public static class TreeResult{
        /**
         * 树头部列表
         */
        private List<Map<String, Object>> topList;

        /**
         * 整棵树
         */
        private List<Map<String, Object>> allList;
        /**
         * id与值得映射
         */
        private Map<String ,Map<String ,Object>> idToMap;
    }
}

