import React, { useCallback, useState, useEffect } from 'react';
import { makeStyles, useTheme, lighten, CircularProgress, Typography } from '@material-ui/core';
import TreeView from '@material-ui/lab/TreeView';
import { InquiryTreeMenuItem } from './InquiryTreeMenuItem';
import { searchTree, findAllParentIds, getNodeIdForRightBorder, findNodeById, formatTreeMenuItem, mapNodeObjValuesToSearchParameters } from '../utilities/tree/TreeUtilities';
import { FluentIcon } from '../utilities/iconLibrary/FluentIcon';
import { CaretUpSolid8Icon, CaretDownSolid8Icon } from '@fluentui/react-icons';
import { cloneDeep, difference } from 'lodash-es';
import { TreeViewModeEnums } from '../enums/unitySystemEnums.ts';
import { getSearchObject } from '../utilities/search/SearchUtilities';
import { toUpperFirstChar } from '../utilities/input/StringUtilities';
import { useSnackbar } from 'notistack';
import { UdpButton } from '../UI/fluent-web-components/UdpButton';
const useStyles = makeStyles((theme) => ({
    root: {
        marginBottom: theme.spacing(1.75),
        borderTop: (props) => props.treeViewMode === TreeViewModeEnums.Compact
            ? `1px solid ${theme.palette.grey[200]}`
            : ''
    },
    noChildrenContainer: {
        borderBottom: (props) => props.treeViewMode === TreeViewModeEnums.Compact
            ? `1px solid ${theme.palette.grey[200]}`
            : ''
    }
}));
const getDefaultExpandedRecursively = (tree) => {
    if (!tree)
        return [];
    return tree.reduce((defaultExpandedIds, item) => {
        var _a;
        if (item === null || item === void 0 ? void 0 : item.isExpanded) {
            defaultExpandedIds.push(item.id);
        }
        if ((_a = item === null || item === void 0 ? void 0 : item.children) === null || _a === void 0 ? void 0 : _a.length) {
            defaultExpandedIds = defaultExpandedIds.concat(getDefaultExpandedRecursively(item.children));
        }
        return defaultExpandedIds;
    }, []);
};
export const InquiryTreeMenu = (props) => {
    const { menuItems, onSelectNode, onDropNode, menuIndex, selectedNodeId, selectedNodeParentId, expandAllClicked, sidebarExpanded, executeQueryAdHoc, catalogObjects, promotedEntities, treeStructureArr, setMenuList, treeViewMode, onExpandedChange } = props;
    const [defaultExpanded, setDefaultExpanded] = useState(null);
    const [isCurrentActiveTree, setIsCurrentActiveTree] = useState(false);
    const [selectedNodeIsHidden, setSelectedNodeIsHidden] = useState(false);
    const [loadingChildren, setLoadingChildren] = useState(false);
    const [loadingMoreChildrenId, setLoadingMoreChildrenId] = useState(null);
    const [tree, setTree] = useState(menuItems);
    const theme = useTheme();
    const classes = useStyles(props);
    const { enqueueSnackbar } = useSnackbar();
    const handleSelectedNode = useCallback((e, value) => {
        const selectedNode = searchTree(tree, value);
        const parentNode = findNodeById(menuItems, selectedNode.entityNodeParentId
            ? selectedNode.entityNodeParentId
            : selectedNode.parentId);
        selectedNode.parentNode = parentNode;
        if (onSelectNode) {
            onSelectNode(selectedNode, menuIndex, tree);
            setSelectedNodeIsHidden(false);
        }
    }, [tree, menuIndex, onSelectNode, menuItems]);
    // Shared helper for many-to-many lazy loading. Handles the two-step fetch:
    // 1. Fetch joining/bridge table rows for the given page
    // 2. Extract entity IDs and fetch the actual child entities
    // Returns { nodes, hasMore } so callers handle dedup and appending.
    const fetchManyToManyChildren = useCallback(async ({ searchMethod, treeStructure, pageNumber, wasLazyLoaded }) => {
        var _a, _b, _c, _d, _e;
        const joiningResponse = await executeQueryAdHoc({ data: Object.assign(Object.assign({}, searchMethod.data), { pageNumber }) }, searchMethod.apiMethodId).catch(() => null);
        if (!joiningResponse ||
            joiningResponse.status !== 200 ||
            !((_b = (_a = joiningResponse.data) === null || _a === void 0 ? void 0 : _a.pageList) === null || _b === void 0 ? void 0 : _b.length)) {
            return { nodes: [], hasMore: false };
        }
        const items = joiningResponse.data.pageList;
        const pageSize = searchMethod.pageSize || 50;
        const hasMore = pageNumber * pageSize < joiningResponse.data.total;
        const childFilterElements = [];
        const manyToManyJoiningObject = {
            manyToManyKeys: searchMethod.manyToManyKeys,
            apiMethodId: searchMethod.manyToManyJointEntityApiMethodId
        };
        manyToManyJoiningObject.manyToManyKeys.forEach((mtmKey) => {
            const searchValue = [];
            const formattedPropertyName = toUpperFirstChar(mtmKey.searchNameKey);
            items.forEach((item) => {
                if (item[mtmKey.searchValueKey]) {
                    searchValue.push(item[mtmKey.searchValueKey]);
                }
            });
            childFilterElements.push({
                searchField: formattedPropertyName,
                searchValue: searchValue.toString(),
                searchOperator: 'IN'
            });
        });
        const entityResponse = await executeQueryAdHoc({ data: getSearchObject(childFilterElements, 1, 50) }, manyToManyJoiningObject.apiMethodId).catch(() => null);
        if (!entityResponse ||
            entityResponse.status !== 200 ||
            !((_d = (_c = entityResponse.data) === null || _c === void 0 ? void 0 : _c.pageList) === null || _d === void 0 ? void 0 : _d.length)) {
            return { nodes: [], hasMore };
        }
        const joiningEntityCatalogObjectKey = (_e = treeStructure === null || treeStructure === void 0 ? void 0 : treeStructure.properties) === null || _e === void 0 ? void 0 : _e.joiningEntityCatalogObjectKey;
        const entityItems = entityResponse.data.pageList;
        items.forEach((entityRow) => {
            if (manyToManyJoiningObject &&
                Object.prototype.hasOwnProperty.call(entityRow, joiningEntityCatalogObjectKey)) {
                manyToManyJoiningObject.manyToManyKeys.forEach((mtmKey) => {
                    if (entityRow[mtmKey.searchValueKey]) {
                        entityRow[joiningEntityCatalogObjectKey] = entityItems.find((item) => item[mtmKey.searchItemIdentifier] ===
                            entityRow[mtmKey.searchValueKey]);
                    }
                });
            }
        });
        const nodes = items.map((item) => formatTreeMenuItem(item, treeStructure, catalogObjects, promotedEntities, null, wasLazyLoaded));
        return { nodes, hasMore };
    }, [executeQueryAdHoc, catalogObjects, promotedEntities]);
    // Fetches the next page of children for a lazy-loaded node ("Show More" button).
    // Handles both one-to-many (direct page increment) and many-to-many (via fetchManyToManyChildren).
    // Appends results to existing children rather than replacing them.
    const handleLoadMoreChildren = useCallback(async (node) => {
        setLoadingMoreChildrenId(node.id);
        const treeCopy = cloneDeep(tree);
        const matchingNode = findNodeById(treeCopy, node.id);
        if (!matchingNode) {
            setLoadingMoreChildrenId(null);
            return;
        }
        const nextPage = (node.currentChildPage || 1) + 1;
        let hasMoreChildren = false;
        let errorExists = false;
        const oneToManyEntries = [];
        const manyToManyPending = [];
        node.lazyLoadChildrenArr.forEach((searchMethod) => {
            const treeStructure = treeStructureArr.find((ts) => ts.properties.catalogReturnObject ===
                searchMethod.catalogReturnObject);
            if (searchMethod.manyToManyJointEntityApiMethodId) {
                manyToManyPending.push({ searchMethod, treeStructure });
            }
            else {
                oneToManyEntries.push({ searchMethod, treeStructure });
            }
        });
        const oneToManyResults = await Promise.all(oneToManyEntries.map(({ searchMethod }) => executeQueryAdHoc({ data: Object.assign(Object.assign({}, searchMethod.data), { pageNumber: nextPage }) }, searchMethod.apiMethodId).catch(() => null)));
        oneToManyResults.forEach((response, i) => {
            var _a, _b;
            const { searchMethod, treeStructure } = oneToManyEntries[i];
            if ((response === null || response === void 0 ? void 0 : response.status) === 200 && ((_b = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.pageList) === null || _b === void 0 ? void 0 : _b.length)) {
                const pageSize = searchMethod.pageSize || 50;
                if (nextPage * pageSize < response.data.total)
                    hasMoreChildren = true;
                response.data.pageList.forEach((item) => {
                    var _a;
                    const displayTree = formatTreeMenuItem(item, treeStructure, catalogObjects, promotedEntities, null, true);
                    displayTree.parentId = node.id;
                    if (displayTree.wasLazyLoaded &&
                        !((_a = displayTree.properties) === null || _a === void 0 ? void 0 : _a.isUsingJointEntityAdditionalProperties) &&
                        matchingNode.children.some((child) => {
                            var _a, _b, _c;
                            return ((_a = child === null || child === void 0 ? void 0 : child.nodeObj) === null || _a === void 0 ? void 0 : _a.businessObjectKey) &&
                                ((_b = child === null || child === void 0 ? void 0 : child.nodeObj) === null || _b === void 0 ? void 0 : _b.businessObjectKey) ===
                                    ((_c = displayTree === null || displayTree === void 0 ? void 0 : displayTree.nodeObj) === null || _c === void 0 ? void 0 : _c.businessObjectKey);
                        })) {
                        return;
                    }
                    matchingNode.children.push(displayTree);
                });
            }
            else if (response === null) {
                errorExists = true;
            }
        });
        const manyToManyResults = await Promise.all(manyToManyPending.map((entry) => fetchManyToManyChildren({
            searchMethod: entry.searchMethod,
            treeStructure: entry.treeStructure,
            pageNumber: nextPage,
            wasLazyLoaded: true
        }).catch(() => ({ nodes: [], hasMore: false }))));
        manyToManyResults.forEach(({ nodes, hasMore }, index) => {
            var _a, _b;
            const entry = manyToManyPending[index];
            const joiningEntityCatalogObjectKey = (_b = (_a = entry.treeStructure) === null || _a === void 0 ? void 0 : _a.properties) === null || _b === void 0 ? void 0 : _b.joiningEntityCatalogObjectKey;
            if (hasMore)
                hasMoreChildren = true;
            nodes.forEach((displayTree) => {
                var _a;
                displayTree.parentId = node.id;
                if (displayTree.wasLazyLoaded &&
                    !((_a = displayTree.properties) === null || _a === void 0 ? void 0 : _a.isUsingJointEntityAdditionalProperties) &&
                    matchingNode.children.some((child) => {
                        var _a, _b, _c, _d;
                        if (displayTree === null || displayTree === void 0 ? void 0 : displayTree.nodeObj)
                            return false;
                        return (((_b = (_a = child === null || child === void 0 ? void 0 : child.nodeObj) === null || _a === void 0 ? void 0 : _a[joiningEntityCatalogObjectKey]) === null || _b === void 0 ? void 0 : _b.businessObjectKey) ===
                            ((_d = (_c = displayTree === null || displayTree === void 0 ? void 0 : displayTree.nodeObj) === null || _c === void 0 ? void 0 : _c[joiningEntityCatalogObjectKey]) === null || _d === void 0 ? void 0 : _d.businessObjectKey));
                    })) {
                    return;
                }
                matchingNode.children.push(displayTree);
            });
        });
        matchingNode.currentChildPage = nextPage;
        matchingNode.hasMoreChildren = hasMoreChildren;
        if (errorExists)
            matchingNode.errorRetrievingChildren = true;
        setMenuList((prevState) => {
            const menuItemsListCopy = cloneDeep(prevState);
            menuItemsListCopy[menuIndex] = treeCopy;
            return menuItemsListCopy;
        });
        setLoadingMoreChildrenId(null);
    }, [
        tree,
        executeQueryAdHoc,
        treeStructureArr,
        catalogObjects,
        promotedEntities,
        menuIndex,
        setMenuList,
        fetchManyToManyChildren
    ]);
    const renderTree = (node, depth = 1) => {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23;
        var _24, _25;
        let nodeId = node.id;
        let iconName = (_b = (_a = node.properties) === null || _a === void 0 ? void 0 : _a.defaultIcon) === null || _b === void 0 ? void 0 : _b.name;
        let iconType = (_d = (_c = node.properties) === null || _c === void 0 ? void 0 : _c.defaultIcon) === null || _d === void 0 ? void 0 : _d.type;
        let iconColor = (_g = (_f = (_e = node.properties) === null || _e === void 0 ? void 0 : _e.defaultIcon) === null || _f === void 0 ? void 0 : _f.color) === null || _g === void 0 ? void 0 : _g.hex;
        if ((_h = node.properties) === null || _h === void 0 ? void 0 : _h.conditionalNodeIconName) {
            iconName = (_j = node.properties) === null || _j === void 0 ? void 0 : _j.conditionalNodeIconName;
            iconType = (_k = node.properties) === null || _k === void 0 ? void 0 : _k.conditionalNodeIconType;
            iconColor = ((_l = node.properties) === null || _l === void 0 ? void 0 : _l.conditionalNodeIconName)
                ? (_24 = (_m = node.properties) === null || _m === void 0 ? void 0 : _m.conditionalNodeIconColor) !== null && _24 !== void 0 ? _24 : (_q = (_p = (_o = node.properties) === null || _o === void 0 ? void 0 : _o.defaultIcon) === null || _p === void 0 ? void 0 : _p.color) === null || _q === void 0 ? void 0 : _q.hex : (_t = (_s = (_r = node.properties) === null || _r === void 0 ? void 0 : _r.defaultIcon) === null || _s === void 0 ? void 0 : _s.color) === null || _t === void 0 ? void 0 : _t.hex;
        }
        let adornmentName = ((_u = node.properties) === null || _u === void 0 ? void 0 : _u.conditionalNodeAdornmentName) || '';
        let adornmentType = ((_v = node.properties) === null || _v === void 0 ? void 0 : _v.conditionalNodeAdornmentName)
            ? node.properties.conditionalNodeAdornmentType
            : '';
        let adornmentColor = ((_w = node.properties) === null || _w === void 0 ? void 0 : _w.conditionalNodeAdornmentName)
            ? (_25 = (_x = node.properties) === null || _x === void 0 ? void 0 : _x.conditionalNodeAdornmentColor) !== null && _25 !== void 0 ? _25 : (_0 = (_z = (_y = node.properties) === null || _y === void 0 ? void 0 : _y.defaultIcon) === null || _z === void 0 ? void 0 : _z.color) === null || _0 === void 0 ? void 0 : _0.hex : '';
        let aggregateThresholdId = ((_1 = node.properties) === null || _1 === void 0 ? void 0 : _1.aggregateThresholdId) || '';
        let aggregateThresholdNodeMapping = mapNodeObjValuesToSearchParameters(node === null || node === void 0 ? void 0 : node.nodeObj, (_2 = node.properties) === null || _2 === void 0 ? void 0 : _2.aggregateThresholdParamMappings);
        let label = ((_3 = node.properties) === null || _3 === void 0 ? void 0 : _3.nodeLabel) || ((_4 = node.properties) === null || _4 === void 0 ? void 0 : _4.name);
        let subLabel = (_5 = node.properties) === null || _5 === void 0 ? void 0 : _5.nodeSubLabel;
        if (node.isGroupNode) {
            label = (_6 = node.properties) === null || _6 === void 0 ? void 0 : _6.label;
            subLabel = (_7 = node.properties) === null || _7 === void 0 ? void 0 : _7.subLabel;
            iconName = (_9 = (_8 = node.properties) === null || _8 === void 0 ? void 0 : _8.icon) === null || _9 === void 0 ? void 0 : _9.name;
            iconType = (_11 = (_10 = node.properties) === null || _10 === void 0 ? void 0 : _10.icon) === null || _11 === void 0 ? void 0 : _11.type;
            iconColor = (_14 = (_13 = (_12 = node.properties) === null || _12 === void 0 ? void 0 : _12.icon) === null || _13 === void 0 ? void 0 : _13.color) === null || _14 === void 0 ? void 0 : _14.hex;
        }
        return (React.createElement(InquiryTreeMenuItem, { key: nodeId, nodeId: nodeId, label: label, subLabel: subLabel, iconName: iconName, iconType: iconType, iconColor: iconColor, adornmentName: adornmentName, adornmentType: adornmentType, adornmentColor: adornmentColor, parentId: node.parentId, onNodeSelect: handleSelectedNode, selectedNodeId: selectedNodeId, isSelectedNode: selectedNodeId === node.id, showRightBorderColor: selectedNodeIsHidden &&
                isCurrentActiveTree &&
                getNodeIdForRightBorder(defaultExpanded, tree, selectedNodeParentId) === node.id, isCurrentActiveTree: isCurrentActiveTree, sidebarExpanded: sidebarExpanded, depth: depth, hideExpansion: !((_15 = node.properties) === null || _15 === void 0 ? void 0 : _15.lazyLoad) && !!!((_16 = node.children) === null || _16 === void 0 ? void 0 : _16.length), node: node, onDropNode: onDropNode, treeViewMode: treeViewMode, menuIndex: menuIndex, aggregateThresholdId: aggregateThresholdId, aggregateThresholdNodeMapping: aggregateThresholdNodeMapping }, ((_17 = node.properties) === null || _17 === void 0 ? void 0 : _17.lazyLoad) &&
            !!!((_18 = node.children) === null || _18 === void 0 ? void 0 : _18.length) &&
            !node.completedLoadingChildren &&
            !node.errorRetrievingChildren && (React.createElement(CircularProgress, { size: 12, style: { marginLeft: (depth || 1) * theme.spacing(1) } })), ((_19 = node.properties) === null || _19 === void 0 ? void 0 : _19.lazyLoad) &&
            !!!((_20 = node.children) === null || _20 === void 0 ? void 0 : _20.length) &&
            node.completedLoadingChildren &&
            sidebarExpanded &&
            !node.errorRetrievingChildren && (React.createElement("div", { className: classes.noChildrenContainer }, React.createElement(Typography, { variant: "caption", style: {
                marginLeft: (depth || 1) * theme.spacing(3),
                fontWeight: 400
            } }, "No Childre"))), ((_21 = node.properties) === null || _21 === void 0 ? void 0 : _21.lazyLoad) &&
            sidebarExpanded &&
            node.errorRetrievingChildren && (React.createElement("div", { className: classes.noChildrenContainer }, React.createElement(Typography, { variant: "caption", style: {
                marginLeft: (depth || 1) * theme.spacing(3),
                fontWeight: 400
            } }, node.completedLoadingChildren
            ? `Error Retrieving ${!!((_22 = node.children) === null || _22 === void 0 ? void 0 : _22.length) ? `Additional ` : ''}Children`
            : node.errorRetrievingChildren))), Array.isArray(node.children)
            ? node.children.map((n, i) => renderTree(n, depth + 1))
            : null, ((_23 = node.properties) === null || _23 === void 0 ? void 0 : _23.lazyLoad) &&
            node.completedLoadingChildren &&
            node.hasMoreChildren &&
            sidebarExpanded && (React.createElement(UdpButton, { appearance: "transparent", size: "small", loading: loadingMoreChildrenId === node.id, onClick: () => handleLoadMoreChildren(node), style: { marginLeft: (depth || 1) * theme.spacing(3) } }, "Show Mor"))));
    };
    const handleNodeExpansion = useCallback(async (evt, nodeIds) => {
        var _a, _b;
        const expandingNodes = nodeIds.filter((x) => !defaultExpanded.includes(x));
        let currentExpandedNodeId = null;
        let currentExpandedNode = null;
        // Check to see if we're expanding
        if (nodeIds.length > defaultExpanded.length) {
            currentExpandedNodeId = expandingNodes[0];
        }
        const treeCopy = cloneDeep(tree);
        // Handle collapsing of a node.
        if (!currentExpandedNodeId) {
            const collapsingNodeList = difference(defaultExpanded, nodeIds);
            if (collapsingNodeList.length) {
                const collapsingNodeId = collapsingNodeList[0];
                const nodeMatch = findNodeById(treeCopy, collapsingNodeId);
                if (nodeMatch) {
                    nodeMatch.isExpanded = false;
                    setMenuList((prevState) => {
                        const menuItemsListCopy = cloneDeep(prevState);
                        menuItemsListCopy[menuIndex] = treeCopy;
                        return menuItemsListCopy;
                    });
                }
            }
        }
        setDefaultExpanded(nodeIds);
        if (currentExpandedNodeId) {
            currentExpandedNode = searchTree(treeCopy, currentExpandedNodeId);
            if ((_a = currentExpandedNode === null || currentExpandedNode === void 0 ? void 0 : currentExpandedNode.properties) === null || _a === void 0 ? void 0 : _a.lazyLoad) {
                const matchingNode = findNodeById(treeCopy, currentExpandedNodeId);
                // If children were already fetched, skip re-fetching and just re-expand
                if (matchingNode === null || matchingNode === void 0 ? void 0 : matchingNode.completedLoadingChildren) {
                    matchingNode.isExpanded = true;
                    setMenuList((prevState) => {
                        const menuItemsListCopy = cloneDeep(prevState);
                        menuItemsListCopy[menuIndex] = treeCopy;
                        return menuItemsListCopy;
                    });
                }
                else {
                    // No lazy load entries — nothing to fetch, show "No Children"
                    if (!((_b = currentExpandedNode.lazyLoadChildrenArr) === null || _b === void 0 ? void 0 : _b.length)) {
                        matchingNode.children = [];
                        matchingNode.isExpanded = true;
                        matchingNode.completedLoadingChildren = true;
                        setMenuList((prevState) => {
                            const menuItemsListCopy = cloneDeep(prevState);
                            menuItemsListCopy[menuIndex] = treeCopy;
                            return menuItemsListCopy;
                        });
                        return;
                    }
                    setLoadingChildren(true);
                    const promises = [];
                    const parentNodeRefKeys = [];
                    const treeStructuresList = [];
                    const searchObjList = [];
                    const manyToManyPending = [];
                    const manyToManyObjectList = [];
                    currentExpandedNode.lazyLoadChildrenArr.forEach((searchMethod) => {
                        var _a;
                        parentNodeRefKeys.push(searchMethod.parentNodeRefKey);
                        const childTree = treeStructureArr.find((ts) => ts.properties.catalogReturnObject ===
                            searchMethod.catalogReturnObject);
                        if (childTree) {
                            treeStructuresList.push(childTree);
                        }
                        promises.push(executeQueryAdHoc({ data: searchMethod.data }, searchMethod.apiMethodId));
                        searchObjList.push({
                            wasLazyLoaded: (_a = currentExpandedNode === null || currentExpandedNode === void 0 ? void 0 : currentExpandedNode.properties) === null || _a === void 0 ? void 0 : _a.lazyLoad
                        });
                        if (searchMethod.manyToManyJointEntityApiMethodId) {
                            manyToManyObjectList.push({
                                manyToManyKeys: searchMethod['manyToManyKeys'],
                                apiMethodId: searchMethod.manyToManyJointEntityApiMethodId
                            });
                        }
                        else {
                            manyToManyObjectList.push(null);
                        }
                    });
                    const updatedNodeObj = cloneDeep(currentExpandedNode.nodeObj);
                    let errorExists = false;
                    let hasMoreChildren = false;
                    await Promise.all(promises.map((p) => p.catch((e) => {
                        errorExists = true;
                        setLoadingChildren(false);
                    }))).then((responses) => {
                        responses.forEach((response, index) => {
                            var _a, _b, _c;
                            if ((response === null || response === void 0 ? void 0 : response.status) === 200) {
                                if ((_b = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.pageList) === null || _b === void 0 ? void 0 : _b.length) {
                                    const manyToManyJoiningObject = manyToManyObjectList[index];
                                    if (manyToManyJoiningObject) {
                                        manyToManyPending.push({
                                            searchMethod: currentExpandedNode.lazyLoadChildrenArr[index],
                                            treeStructure: treeStructuresList[index],
                                            wasLazyLoaded: searchObjList[index].wasLazyLoaded
                                        });
                                    }
                                    else {
                                        if (treeStructuresList[index]) {
                                            const items = response.data.pageList;
                                            if (items === null || items === void 0 ? void 0 : items.length) {
                                                items.forEach((item) => {
                                                    var _a, _b, _c;
                                                    const displayTree = formatTreeMenuItem(item, treeStructuresList[index], catalogObjects, promotedEntities, null, searchObjList[index].wasLazyLoaded);
                                                    displayTree.parentId = currentExpandedNode.id;
                                                    if (displayTree.wasLazyLoaded &&
                                                        ((_a = displayTree.properties) === null || _a === void 0 ? void 0 : _a.isUsingJointEntityAdditionalProperties)) {
                                                        enqueueSnackbar(`Promote ${(_b = displayTree.properties) === null || _b === void 0 ? void 0 : _b.joiningEntityName} search method to view additional joining properties`, {
                                                            variant: 'warning',
                                                            anchorOrigin: {
                                                                vertical: 'top',
                                                                horizontal: 'center'
                                                            },
                                                            preventDuplicate: true,
                                                            autoHideDuration: 5000
                                                        });
                                                    }
                                                    if (matchingNode) {
                                                        if (displayTree.wasLazyLoaded &&
                                                            !((_c = displayTree.properties) === null || _c === void 0 ? void 0 : _c.isUsingJointEntityAdditionalProperties) &&
                                                            matchingNode.children.some((child) => {
                                                                var _a, _b, _c;
                                                                return ((_a = child === null || child === void 0 ? void 0 : child.nodeObj) === null || _a === void 0 ? void 0 : _a.businessObjectKey) &&
                                                                    ((_b = child === null || child === void 0 ? void 0 : child.nodeObj) === null || _b === void 0 ? void 0 : _b.businessObjectKey) ===
                                                                        ((_c = displayTree === null || displayTree === void 0 ? void 0 : displayTree.nodeObj) === null || _c === void 0 ? void 0 : _c.businessObjectKey);
                                                            })) {
                                                            return;
                                                        }
                                                        matchingNode.children.push(displayTree);
                                                    }
                                                });
                                            }
                                        }
                                    }
                                    if (!manyToManyObjectList[index] && treeStructuresList[index]) {
                                        const pageSize = ((_c = currentExpandedNode.lazyLoadChildrenArr[index]) === null || _c === void 0 ? void 0 : _c.pageSize) || 50;
                                        if (pageSize < response.data.total) {
                                            hasMoreChildren = true;
                                        }
                                    }
                                    const parentNodeCatalogObjKey = parentNodeRefKeys[index];
                                    if (parentNodeCatalogObjKey) {
                                        updatedNodeObj[parentNodeCatalogObjKey] =
                                            response.data.pageList;
                                    }
                                }
                            }
                        });
                    });
                    // Process many-to-many entries using the shared helper
                    const manyToManyResults = await Promise.all(manyToManyPending.map((entry) => fetchManyToManyChildren({
                        searchMethod: entry.searchMethod,
                        treeStructure: entry.treeStructure,
                        pageNumber: 1,
                        wasLazyLoaded: entry.wasLazyLoaded
                    }).catch(() => ({ nodes: [], hasMore: false }))));
                    manyToManyResults.forEach(({ nodes, hasMore }, index) => {
                        var _a, _b;
                        const entry = manyToManyPending[index];
                        const joiningEntityCatalogObjectKey = (_b = (_a = entry.treeStructure) === null || _a === void 0 ? void 0 : _a.properties) === null || _b === void 0 ? void 0 : _b.joiningEntityCatalogObjectKey;
                        if (hasMore)
                            hasMoreChildren = true;
                        nodes.forEach((displayTree) => {
                            var _a;
                            displayTree.parentId = currentExpandedNode.id;
                            if (matchingNode) {
                                if (displayTree.wasLazyLoaded &&
                                    !((_a = displayTree.properties) === null || _a === void 0 ? void 0 : _a.isUsingJointEntityAdditionalProperties) &&
                                    matchingNode.children.some((child) => {
                                        var _a, _b, _c, _d;
                                        if (displayTree === null || displayTree === void 0 ? void 0 : displayTree.nodeObj) {
                                            return false;
                                        }
                                        return (((_b = (_a = child === null || child === void 0 ? void 0 : child.nodeObj) === null || _a === void 0 ? void 0 : _a[joiningEntityCatalogObjectKey]) === null || _b === void 0 ? void 0 : _b.businessObjectKey) ===
                                            ((_d = (_c = displayTree === null || displayTree === void 0 ? void 0 : displayTree.nodeObj) === null || _c === void 0 ? void 0 : _c[joiningEntityCatalogObjectKey]) === null || _d === void 0 ? void 0 : _d.businessObjectKey));
                                    })) {
                                    return;
                                }
                                matchingNode.children.push(displayTree);
                            }
                        });
                    });
                    if (matchingNode) {
                        // Property to be used to signal that lazy load for children request is completed
                        matchingNode.completedLoadingChildren = true;
                        matchingNode.currentChildPage = 1;
                        matchingNode.hasMoreChildren = hasMoreChildren;
                    }
                    if (currentExpandedNode.lazyLoadChildrenArr.length) {
                        if (matchingNode) {
                            matchingNode.nodeObj = updatedNodeObj;
                            matchingNode.isExpanded = true;
                            if (errorExists) {
                                matchingNode.errorRetrievingChildren = true;
                            }
                        }
                        setMenuList((prevState) => {
                            const menuItemsListCopy = cloneDeep(prevState);
                            menuItemsListCopy[menuIndex] = treeCopy;
                            return menuItemsListCopy;
                        });
                        setLoadingChildren(false);
                    }
                }
            }
            else {
                const foundNode = findNodeById(treeCopy, currentExpandedNodeId);
                if (foundNode) {
                    foundNode.isExpanded = true;
                }
                else {
                    foundNode.isExpanded = false;
                }
                setMenuList((prevState) => {
                    const menuItemsListCopy = cloneDeep(prevState);
                    menuItemsListCopy[menuIndex] = treeCopy;
                    return menuItemsListCopy;
                });
            }
        }
        const parentNode = searchTree(treeCopy, selectedNodeParentId);
        const initialAllParentNodeIds = selectedNodeParentId
            ? [selectedNodeParentId]
            : [];
        const allParentNodeIds = findAllParentIds(treeCopy, parentNode, initialAllParentNodeIds);
        const selectedNodeShown = allParentNodeIds.every((id) => nodeIds.includes(id));
        if (isCurrentActiveTree &&
            allParentNodeIds.length &&
            !selectedNodeShown) {
            setSelectedNodeIsHidden(true);
        }
        else {
            setSelectedNodeIsHidden(false);
        }
    }, [
        defaultExpanded,
        tree,
        selectedNodeParentId,
        isCurrentActiveTree,
        menuIndex,
        setMenuList,
        treeStructureArr,
        executeQueryAdHoc,
        catalogObjects,
        promotedEntities,
        enqueueSnackbar,
        fetchManyToManyChildren
    ]);
    useEffect(() => {
        if (!defaultExpanded || !onExpandedChange || !tree)
            return;
        const getStableKey = (n) => {
            var _a, _b;
            return n.isGroupNode ? (_a = n.properties) === null || _a === void 0 ? void 0 : _a.label : (_b = n.nodeObj) === null || _b === void 0 ? void 0 : _b.businessObjectKey;
        };
        const expandedIds = new Set(defaultExpanded);
        const stateMap = new Map();
        const walk = (n) => {
            var _a;
            const key = getStableKey(n);
            if (key)
                stateMap.set(key, expandedIds.has(n.id));
            (_a = n.children) === null || _a === void 0 ? void 0 : _a.forEach(walk);
        };
        if (Array.isArray(tree)) {
            tree.forEach(walk);
        }
        else {
            walk(tree);
        }
        onExpandedChange(menuIndex, stateMap);
    }, [defaultExpanded, onExpandedChange, menuIndex, tree]);
    useEffect(() => {
        setTree(menuItems);
    }, [menuItems]);
    useEffect(() => {
        if (!tree) {
            return;
        }
        let expanded = [];
        if (tree === null || tree === void 0 ? void 0 : tree.isExpanded) {
            expanded.push(tree.id);
        }
        expanded = expanded.concat(getDefaultExpandedRecursively(tree.children));
        setDefaultExpanded(expanded);
    }, [tree]);
    useEffect(() => {
        if (!!searchTree(tree, selectedNodeId)) {
            setIsCurrentActiveTree(true);
        }
        else {
            setIsCurrentActiveTree(false);
        }
    }, [tree, selectedNodeId]);
    useEffect(() => {
        setSelectedNodeIsHidden(false);
    }, [expandAllClicked]);
    if (!defaultExpanded) {
        return null;
    }
    return (React.createElement(TreeView, { key: tree, className: classes.root, defaultCollapseIcon: React.createElement(FluentIcon, { size: "small", component: CaretUpSolid8Icon, style: {
                color: lighten(theme.palette.primary.main, 0.5),
                width: theme.spacing(1.5),
                height: theme.spacing(1.5)
            } }), expanded: defaultExpanded || [], onNodeToggle: handleNodeExpansion, defaultExpandIcon: React.createElement(FluentIcon, { size: "small", component: CaretDownSolid8Icon, style: {
                color: lighten(theme.palette.primary.main, 0.5),
                width: theme.spacing(1.5),
                height: theme.spacing(1.5)
            } }), 
        // onNodeSelect={handleSelectedNode}
        selected: selectedNodeId }, tree && renderTree(tree)));
};
//# sourceMappingURL=InquiryTreeMenu.js.map