package com.openhis.web.document.util;

import com.openhis.common.enums.DocTypeEnum;
import com.openhis.web.document.dto.DirectoryNode;
import com.openhis.web.document.dto.DocDefinitionDto;

import java.util.*;

public class DocumentDirectoryProcessor {

    private static Long id;

    /**
     * 构建文档目录树
     *
     * @param documents 文档定义列表
     * @return 目录节点列表（树形结构）
     */
    public static List<DirectoryNode> buildDocumentDirectory(List<DocDefinitionDto> documents) {
        // 第一步：按一级菜单分组，使用LinkedHashMap保持插入顺序
        id = 1L;
        Map<Object, List<DocDefinitionDto>> level1Groups = new LinkedHashMap<>();
        for (DocDefinitionDto doc : documents) {
            Object key = doc.getPrimaryMenuEnum() != null ? doc.getPrimaryMenuEnum() : doc.getName();
            level1Groups.computeIfAbsent(key, k -> new ArrayList<>()).add(doc);
        }

        // 对一级节点进行排序，确保输出顺序符合预期
        List<Object> sortedKeys = new ArrayList<>(level1Groups.keySet());
        sortedKeys.sort((k1, k2) -> {
            // 处理数字类型的键（primaryMenuEnum）
            if (k1 instanceof Integer && k2 instanceof Integer) {
                return Integer.compare((Integer) k1, (Integer) k2);
            }
            // 数字键排在前面，非数字键（如体温单）排在后面
            if (k1 instanceof Integer) {
                return -1;
            }
            if (k2 instanceof Integer) {
                return 1;
            }
            // 都是非数字键，按名称排序
            return k1.toString().compareTo(k2.toString());
        });

        // 按排序后的键重新组织分组
        Map<Object, List<DocDefinitionDto>> sortedLevel1Groups = new LinkedHashMap<>();
        for (Object key : sortedKeys) {
            sortedLevel1Groups.put(key, level1Groups.get(key));
        }

        List<DirectoryNode> result = new ArrayList<>();

        for (Map.Entry<Object, List<DocDefinitionDto>> entry : sortedLevel1Groups.entrySet()) {
            Object level1Key = entry.getKey();
            List<DocDefinitionDto> level1Docs = entry.getValue();

            DirectoryNode level1Node = new DirectoryNode();
            if (level1Key instanceof Integer) {
                level1Node.setName(getMenuName((Integer) level1Key));
            } else {
                level1Node.setName(level1Key.toString());
            }
            level1Node.setId(id++);
            level1Node.setLevel(1);

            buildSubNodes(level1Node, level1Docs);

            result.add(level1Node);
        }

        return result;
    }

    private static void buildSubNodes(DirectoryNode parentNode, List<DocDefinitionDto> documents) {
        if (documents == null || documents.isEmpty()) {
            return;
        }

        // 按下一级分组键分组（处理null键）
        Map<String, List<DocDefinitionDto>> groups = new HashMap<>();
        for (DocDefinitionDto doc : documents) {
            String key = getNextLevelKey(parentNode, doc);
            // 统一使用空字符串处理null键，避免分组异常
            key = (key == null) ? "" : key;
            groups.computeIfAbsent(key, k -> new ArrayList<>()).add(doc);
        }

        // 对分组键进行排序，确保子节点顺序一致
        List<String> sortedGroupKeys = new ArrayList<>(groups.keySet());
        sortedGroupKeys.sort(String::compareTo);

        for (String groupKey : sortedGroupKeys) {
            List<DocDefinitionDto> groupDocs = groups.get(groupKey);

            if (groupKey.isEmpty()) {
                // 分组键为空，直接添加文档节点
                for (DocDefinitionDto doc : groupDocs) {
                    parentNode.getChildren().add(createDocumentNode(doc));
                }
            } else {
                // 创建目录节点
                DirectoryNode childNode = new DirectoryNode();
                childNode.setName(groupKey);
                childNode.setLevel(parentNode.getLevel() + 1);
                childNode.setId(id++);

                // 递归构建子节点
                buildSubNodes(childNode, groupDocs);

                // 添加子节点到父节点
                parentNode.getChildren().add(childNode);
            }
        }
    }

    /**
     * 获取下一级节点的分组键
     * 关键优化：二级节点(level=2)不再进行分组，直接返回null
     */
    private static String getNextLevelKey(DirectoryNode parentNode, DocDefinitionDto doc) {
        int parentLevel = parentNode.getLevel();
        if (parentLevel == 1) {
            return doc.getSubMenu(); // 一级节点的下一级是subMenu(二级菜单)
        } else if (parentLevel == 2) {
            return null; // 二级节点的下一级直接是文档，不进行分组
        }
        return null;
    }

    private static DirectoryNode createDocumentNode(DocDefinitionDto doc) {
        DirectoryNode node = new DirectoryNode();
        node.setName(doc.getName() + " (" + doc.getVersion() + ")");
        node.setLevel(3);
        node.setId(id++);
        node.setDocument(doc);
        return node;
    }

    private static String getMenuName(Integer menuEnum) {
        DocTypeEnum docType = DocTypeEnum.getByValue(menuEnum);
        if (docType != null) {
            return docType.getInfo();
        }
        return "其他文书";
    }

    /**
     * 打印目录结构（优化缩进格式）
     *
     * @param nodes  节点列表
     * @param indent 缩进级别（0表示无缩进）
     */
    public static void printDirectory(List<DirectoryNode> nodes, int indent) {
        for (DirectoryNode node : nodes) {
            // 打印缩进和节点信息
            System.out.println("  ".repeat(indent) + node.getName() + " (" + node.getLevel() + ")");
            // 递归打印子节点，缩进+1
            printDirectory(node.getChildren(), indent + 1);
        }
    }
}
