package com.yeejoin.amos.boot.biz.common.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

public class TreeRecursive<T> {
    private List<T> list;
    private String childName;
    private Function<T, List<T>> childrenGetter;
    private BiConsumer<T, List<T>> childrenSetter;

    private TreeRecursive(List<T> list, String childName,
                          Function<T, List<T>> childrenGetter,
                          BiConsumer<T, List<T>> childrenSetter) {
        this.list = deepCopy(list);
        this.childName = childName;
        this.childrenGetter = childrenGetter;
        this.childrenSetter = childrenSetter;
    }

    // 在TreeRecursive类中添加以下方法
    public <R> List<R> mapTree(Function<T, R> mapper) {
        return mapTreeRecursive(list, mapper);
    }

    private <R> List<R> mapTreeRecursive(List<T> nodes, Function<T, R> mapper) {
        List<R> result = new ArrayList<>();

        for (T node : nodes) {
            // 创建新节点
            R mappedNode = mapper.apply(node);
            result.add(mappedNode);

            // 递归处理子节点
            List<T> children = getChildren(node);
            if (children != null && !children.isEmpty()) {
                List<R> mappedChildren = mapTreeRecursive(children, mapper);

                // 将映射后的子节点设置到当前节点
                if (mappedNode instanceof Map) {
                    @SuppressWarnings("unchecked")
                    Map<String, Object> mappedMap = (Map<String, Object>) mappedNode;
                    mappedMap.put(childName, mappedChildren);
                }
                // 如果是Bean对象，可以使用childrenSetter
                else if (childrenSetter != null) {
                    // 这里需要类型转换，实际使用时可能需要调整
                    @SuppressWarnings("unchecked")
                    T castedNode = (T) mappedNode;
                    @SuppressWarnings("unchecked")
                    List<T> castedChildren = (List<T>) mappedChildren;
                    setChildren(castedNode, castedChildren);
                }
            }
        }

        return result;
    }

    /**
     * 使用反射方式（适用于Map或Bean）
     */
    public static <T> TreeRecursive<T> recursive(List<T> list, String childName) {
        return new TreeRecursive<>(list, childName, null, null);
    }

    /**
     * 使用自定义getter/setter（推荐用于Bean对象）
     */
    public static <T> TreeRecursive<T> recursive(List<T> list,
                                                 Function<T, List<T>> childrenGetter,
                                                 BiConsumer<T, List<T>> childrenSetter) {
        return new TreeRecursive<>(list, "children", childrenGetter, childrenSetter);
    }

    public static <T> TreeRecursive<T> recursive(List<T> list) {
        return new TreeRecursive<>(list, "children", null, null);
    }

    // 深度拷贝方法
    private List<T> deepCopy(List<T> original) {
        if (original == null) return new ArrayList<>();
        return new ArrayList<>(original);
    }

    // 获取子节点列表
    @SuppressWarnings("unchecked")
    private List<T> getChildren(T node) {
        if (childrenGetter != null) {
            return childrenGetter.apply(node);
        }

        if (node instanceof Map) {
            Map<String, Object> map = (Map<String, Object>) node;
            Object children = map.get(childName);
            if (children instanceof List) {
                return (List<T>) children;
            }
        }

        // 如果是Bean对象，可以通过反射获取，这里简化处理
        return Collections.emptyList();
    }

    // 设置子节点列表
    @SuppressWarnings("unchecked")
    private void setChildren(T node, List<T> children) {
        if (childrenSetter != null) {
            childrenSetter.accept(node, children);
            return;
        }

        if (node instanceof Map) {
            Map<String, Object> map = (Map<String, Object>) node;
            map.put(childName, children);
        }
    }

    /**
     * 按顺序获取树的所有叶子节点
     */
    public List<T> getLeafNodes() {
        List<T> leaves = new ArrayList<>();
        for (T node : list) {
            traverseLeafNodes(node, leaves);
        }
        return leaves;
    }

    private void traverseLeafNodes(T node, List<T> leaves) {
        List<T> children = getChildren(node);
        if (children != null && !children.isEmpty()) {
            for (T child : children) {
                traverseLeafNodes(child, leaves);
            }
        } else {
            leaves.add(node);
        }
    }

    public boolean some(Predicate<T> predicate) {
        for (T node : list) {
            if (someRecursive(node, predicate)) {
                return true;
            }
        }
        return false;
    }

    private boolean someRecursive(T node, Predicate<T> predicate) {
        if (predicate.test(node)) {
            return true;
        }

        List<T> children = getChildren(node);
        if (children != null && !children.isEmpty()) {
            for (T child : children) {
                if (someRecursive(child, predicate)) {
                    return true;
                }
            }
        }
        return false;
    }

    public T find(Predicate<T> predicate) {
        for (T node : list) {
            T result = findRecursive(node, predicate);
            if (result != null) {
                return result;
            }
        }
        return null;
    }

    private T findRecursive(T node, Predicate<T> predicate) {
        if (predicate.test(node)) {
            return node;
        }

        List<T> children = getChildren(node);
        if (children != null && !children.isEmpty()) {
            for (T child : children) {
                T result = findRecursive(child, predicate);
                if (result != null) {
                    return result;
                }
            }
        }
        return null;
    }

    public List<T> filter(Predicate<T> predicate) {
        return filterRecursive(list, predicate);
    }

    private List<T> filterRecursive(List<T> nodes, Predicate<T> predicate) {
        List<T> result = new ArrayList<>();

        for (T node : nodes) {
            T newNode = node; // 这里假设T是不可变的，如果需要修改可以clone

            List<T> children = getChildren(newNode);
            if (children != null && !children.isEmpty()) {
                List<T> filteredChildren = filterRecursive(children, predicate);
                setChildren(newNode, filteredChildren);
            }

            if (predicate.test(newNode)) {
                result.add(newNode);
            }
        }

        return result;
    }

    public List<T> flatFilter(Predicate<T> predicate) {
        List<T> result = new ArrayList<>();
        flatFilterRecursive(list, predicate, result);
        return result;
    }

    private void flatFilterRecursive(List<T> nodes, Predicate<T> predicate, List<T> result) {
        for (T node : nodes) {
            if (predicate.test(node)) {
                result.add(node);
            }

            List<T> children = getChildren(node);
            if (children != null && !children.isEmpty()) {
                flatFilterRecursive(children, predicate, result);
            }
        }
    }

    public <R> List<R> map(Function<T, R> mapper) {
        return mapRecursive(list, mapper);
    }

    private <R> List<R> mapRecursive(List<T> nodes, Function<T, R> mapper) {
        List<R> result = new ArrayList<>();

        for (T node : nodes) {
            R mappedNode = mapper.apply(node);
            result.add(mappedNode);

            List<T> children = getChildren(node);
            if (children != null && !children.isEmpty()) {
                // 如果需要处理子节点，可以递归调用
            }
        }

        return result;
    }

    public void forEach(Consumer<T> consumer) {
        forEachRecursive(list, consumer);
    }

    private void forEachRecursive(List<T> nodes, Consumer<T> consumer) {
        for (T node : nodes) {
            consumer.accept(node);

            List<T> children = getChildren(node);
            if (children != null && !children.isEmpty()) {
                forEachRecursive(children, consumer);
            }
        }
    }
}