package cn.axzo.msg.center.utils;

import cn.axzo.msg.center.domain.entity.MessageGroupNode;
import cn.axzo.msg.center.service.dto.GroupTreeNodeDTO;
import cn.axzo.msg.center.service.enums.MessageGroupNodeCategoryEnum;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author cold_blade
 * @date 2023/10/16
 * @version 1.0
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class TreeHelperUtil {

    public static List<GroupTreeNodeDTO> buildTrees(List<MessageGroupNode> nodes) {
        if (CollectionUtils.isEmpty(nodes)) {
            return Collections.emptyList();
        }
        List<GroupTreeNodeDTO> rootNodes = nodes.stream()
                .filter(e -> StringUtils.isBlank(e.getParentCode()))
                .map(TreeHelperUtil::convert)
                .collect(Collectors.toList());
        rootNodes.forEach(e -> buildTree(e, nodes));
        return rootNodes;
    }

    public static boolean isLeafNodeCategory(MessageGroupNodeCategoryEnum category) {
        return MessageGroupNodeCategoryEnum.GENERAL_MESSAGE_CATEGORY.equals(category)
                || MessageGroupNodeCategoryEnum.PENDING_MESSAGE_CATEGORY.equals(category);
    }

    public static boolean containsMountTemplateChild(GroupTreeNodeDTO treeNode) {
        if (Objects.isNull(treeNode)) {
            return false;
        }
        if (CollectionUtils.isEmpty(treeNode.getNodeChildren())) {
            return treeNode.canMountTemplate();
        }
        LinkedList<GroupTreeNodeDTO> stack = new LinkedList<>(treeNode.getNodeChildren());
        while (!stack.isEmpty()) {
            GroupTreeNodeDTO node = stack.pop();
            if (node.canMountTemplate()) {
                return true;
            }
            stack.addAll(node.getNodeChildren());
        }
        return false;
    }

    public static boolean containsMountTemplateChild(GroupTreeNodeDTO treeNode, String mountTemplateNodeName) {
        if (Objects.isNull(treeNode) || StringUtils.isBlank(mountTemplateNodeName)) {
            return false;
        }
        if (CollectionUtils.isEmpty(treeNode.getNodeChildren())) {
            return treeNode.canMountTemplate() && treeNode.getNodeName().contains(mountTemplateNodeName);
        }
        LinkedList<GroupTreeNodeDTO> stack = new LinkedList<>(treeNode.getNodeChildren());
        while (!stack.isEmpty()) {
            GroupTreeNodeDTO node = stack.pop();
            if (node.canMountTemplate() && node.getNodeName().contains(mountTemplateNodeName)) {
                return true;
            }
            stack.addAll(node.getNodeChildren());
        }
        return false;
    }

    private static void buildTree(GroupTreeNodeDTO parentNode, List<MessageGroupNode> nodes) {
        List<MessageGroupNode> children = nodes.stream()
                .filter(e -> Objects.equals(e.getParentCode(), parentNode.getNodeCode()))
                .collect(Collectors.toList());
        if (children.isEmpty()) {
            return;
        }
        children.forEach(e -> {
            GroupTreeNodeDTO child = convert(e);
            parentNode.addChild(child);
            buildTree(child, nodes);
        });
    }

    private static GroupTreeNodeDTO convert(MessageGroupNode groupNode) {
        return GroupTreeNodeDTO.builder()
                .nodeId(groupNode.getId())
                .nodeName(groupNode.getName())
                .nodeCode(groupNode.getCode())
                .nodeIcon(groupNode.getIcon())
                .category(groupNode.getCategory())
                .isLeaf(groupNode.getIsLeaf())
                .status(groupNode.getStatus())
                .build();
    }
}
