import _ from "lodash";

/**
 * @description 在树结构中查找路径
 * @param {Object[]} tree - 树的根节点数组
 * @param {Function} predicate - 要查找的目标条件
 * @param {string} children - 属性名，默认`children`
 * @param {string[]} path - 当前路径（递归用）
 * @returns {Object[] | null} - 返回路径数组，如果没找到返回 null
 */
export function findTreePath(tree, predicate, children = 'children', path = []) {
    if (!Array.isArray(tree)) throw new TypeError('tree must be an array')
    if (typeof predicate !== 'function') throw new TypeError('predicate must be a function')
    for (const node of tree) {
        if (!node) continue
        // 添加当前节点到路径
        const currentPath = [...path, node];
        // 检查当前节点的值是否匹配
        if (predicate(node)) return currentPath;
        // 如果有子节点，递归查找
        if (node[children]?.length) {
            const result = findTreePath(node[children], predicate, children, currentPath);
            if (result) {
                return result; // 找到路径则返回
            }
        }
    }
    // 如果未找到目标值，返回 null
    return null;
}

export function findTreeNode(tree, predicate, children = 'children') {
    const path = findTreePath(tree, predicate, children)
    return _.last(path)
}

export function convertStandardTree(
    root,
    labelKey = 'label',
    valueKey = 'value',
    childrenKey = 'children',
    toLabel = 'label',
    toValue = 'value',
    toChildren = 'children') {
    const convertor = (node) => ({
        [toLabel]: node[labelKey],
        [toValue]: node[valueKey],
        [toChildren]: node[childrenKey]?.map(convertor)
    })
    const arrRoot = Array.isArray(root) ? root : [root]
    return arrRoot.map(convertor)
}

export function fillTreeChildCount(tree) {
    const fillChildCount = (node) => {
        node.childCount = node.children?.length || 0
        node.children?.forEach(child => fillChildCount(child))
    }
    [].concat(tree).forEach(node => fillChildCount(node))
}

export function fillTreeParentBridge(tree) {
    const fillParent = (node, parent = null, root = null) => {
        node.parent = parent
        node.root = root
        if (!node.children?.length) return
        node.children.forEach(child => fillParent(child, node, root || node))
    }
    [].concat(tree).forEach(node => fillParent(node))
}