import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useHistory, useLocation, Prompt } from 'react-router-dom';
import { useAxiosGet } from '../utilities/useAxiosGet';
import { UtilitySideBar } from '../UI/utilityDisplay/UtilitySideBar';
import { makeStyles } from '@material-ui/core';
import { PageContainer } from '../page/PageContainer';
import { transformMenuPageTree } from '../utilities/tree/TreeUtilities';
import { BaseTreeMenu } from '../treeMenu/BaseTreeMenu';
import { TreeViewModeEnums } from '../enums/unitySystemEnums';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { useUser } from '../utilities/auth/useUser';
import { useShellStore } from '../stores/shellStore';
import { NodeLoader } from '../UI/feedback/NodeLoader';
import { APP_RIBBON_SPACE, useBuildEnvironment } from '../shell/ui/useBuildEnvironment';
import { useSetLocationState } from '../hooks/useSetLocationState';
import { useTranslation } from 'react-i18next';
import { ConfigService } from '../configService';
const useStyles = makeStyles((theme) => ({
    root: {
        flex: 1,
        height: '100%',
        minHeight: 0,
        display: 'grid',
        gridTemplateAreas: ['sidebar content'].map((line) => `"${line}"`).join(' '),
        gridTemplateColumns: 'auto 1fr',
        gridTemplateRows: 'auto 1fr'
    },
    sidebar: {
        gridArea: 'sidebar',
        marginRight: theme.spacing(1),
        display: 'flex',
        flexDirection: 'column',
        minHeight: 0
    },
    content: {
        gridArea: 'content',
        display: 'flex',
        flexDirection: 'column',
        position: 'relative',
        zIndex: 1,
        height: `100%`,
        minHeight: 0,
        overflowY: 'auto'
    },
    menuContent: {
        marginTop: theme.spacing(1),
        flex: 1,
        minHeight: 0,
        overflowX: 'hidden',
        overflowY: 'auto'
    },
    loader: {
        marginRight: theme.spacing(1),
        marginLeft: theme.spacing(1)
    },
    loadingContent: {
        flex: 1,
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'center'
    }
}));
// Define a stable constant for empty headers to prevent useEffect loops
const EMPTY_HEADERS = {};
// Helper to find a node deep in the tree (Moved outside to ensure stability)
const findNodeById = (nodes, id) => {
    if (!nodes || !id)
        return null;
    for (const node of nodes) {
        if (String(node.id) === String(id))
            return node;
        if (node.children) {
            const found = findNodeById(node.children, id);
            if (found)
                return found;
        }
    }
    return null;
};
const MenuPage = (props) => {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
    const buildEnv = useBuildEnvironment();
    const classes = useStyles(Object.assign(Object.assign({}, props), { appRibbonSpace: buildEnv ? APP_RIBBON_SPACE : 0 }));
    const history = useHistory();
    const location = useLocation();
    const user = useUser();
    const { t } = useTranslation();
    const setLocationState = useSetLocationState();
    const { innerMenuOverride, mainContent, menuTitle, allowMissingPageParam = false, searchParamsTransformer } = props;
    // --- STATE ---
    const [sidebarExpanded, setSidebarExpanded] = useState(true);
    const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
    const { setSubHeaderActionHasChildren, setNavigationExpanded } = useShellStore();
    // --- DATA FETCHING ---
    const innerMenuId = location.pathname.replace('/menupage/', '');
    const [{ data: fetchedInnerMenu, loading: menuLoading }] = useAxiosGet(ConfigService.tenantV1ApiUrl, `menus/${innerMenuId}`, EMPTY_HEADERS, !innerMenuId || innerMenuOverride, //If no innerMenuId or an override dont make api call
    false);
    const innerMenu = innerMenuOverride !== null && innerMenuOverride !== void 0 ? innerMenuOverride : fetchedInnerMenu;
    // --- MEMOIZED DATA ---
    const menuItemsList = useMemo(() => {
        var _a;
        var _b;
        if (!innerMenu)
            return [];
        return ((_b = (_a = innerMenu.menuItemInstanceStructureViews) === null || _a === void 0 ? void 0 : _a.reduce((acc, menuInstance) => {
            const updatedMenu = transformMenuPageTree(menuInstance);
            if (updatedMenu)
                acc.push(updatedMenu);
            return acc;
        }, [])) !== null && _b !== void 0 ? _b : []);
    }, [innerMenu]);
    // --- CORE REFACTOR: DERIVE SELECTED NODE ---
    const pageId = new URLSearchParams(location.search).get('page');
    const selectedNode = useMemo(() => {
        if (!menuItemsList.length)
            return null;
        // 1. Try to find the node requested in URL
        const found = findNodeById(menuItemsList, pageId);
        if (found)
            return found;
        // 2. Default to first item
        // Even if allowMissingPageParam is true, we still want to RETURN the node for rendering,
        // we just don't want the Redirector useEffect to force it into the URL.
        return menuItemsList[0];
    }, [menuItemsList, pageId]);
    // Fetch Page Data based on the derived node
    const [{ data: pageData, loading: pageLoading }] = useAxiosGet(ConfigService.tenantV1ApiUrl, `page/${(_b = (_a = selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.properties) === null || _a === void 0 ? void 0 : _a.page) === null || _b === void 0 ? void 0 : _b.id}`, EMPTY_HEADERS, !((_d = (_c = selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.properties) === null || _c === void 0 ? void 0 : _c.page) === null || _d === void 0 ? void 0 : _d.id), false);
    // --- ACTIONS ---
    const buildSearchString = useCallback((params, node, menuIndex) => {
        if (typeof searchParamsTransformer === 'function') {
            const result = searchParamsTransformer({
                searchParams: params,
                node,
                menuIndex,
                location
            });
            if (result === null)
                return '';
            if (result instanceof URLSearchParams)
                return result.toString();
            if (typeof result === 'string')
                return result;
            if (result !== undefined)
                return String(result);
        }
        return params.toString();
    }, [location, searchParamsTransformer]);
    const handleSelectedNode = useCallback((node, menuIndex) => {
        // 1. Check if we are "selecting" the current node to clear query params if needed
        if (allowMissingPageParam) {
            const firstNode = menuItemsList === null || menuItemsList === void 0 ? void 0 : menuItemsList[0];
            if (firstNode && String(node === null || node === void 0 ? void 0 : node.id) === String(firstNode.id)) {
                if (location.search) {
                    history.replace({ pathname: location.pathname, search: '' });
                }
                setHasUnsavedChanges(false);
                return;
            }
        }
        // 2. Build URL
        const searchParams = new URLSearchParams(location.search);
        searchParams.set('page', node.id);
        const searchString = buildSearchString(searchParams, node, menuIndex);
        // 3. Navigate (The URL change will trigger the re-render & selectedNode update)
        history.push({
            pathname: location.pathname,
            search: searchString
        });
        // Note: We don't set 'selectedNode' manually anymore. It is derived.
    }, [history, location, allowMissingPageParam, menuItemsList, buildSearchString]);
    const handleSidebarExpandClick = useCallback(() => {
        setSidebarExpanded((expanded) => !expanded);
    }, []);
    const handleDropNode = useCallback(() => {
        // TODO: Implement if we need to for next Phase
    }, []);
    // --- EFFECTS ---
    // 1. URL SYNCHRONIZATION (The "Redirector")
    // Ensures URL matches the selected node (e.g. on initial load or default selection)
    useEffect(() => {
        if (selectedNode && !allowMissingPageParam) {
            const currentUrlId = new URLSearchParams(location.search).get('page');
            if (String(selectedNode.id) !== String(currentUrlId)) {
                const newParams = new URLSearchParams(location.search);
                newParams.set('page', selectedNode.id);
                history.replace({
                    pathname: location.pathname,
                    search: newParams.toString()
                });
            }
        }
    }, [selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.id, location.search, history, allowMissingPageParam]);
    // 2. UI CLEANUP (The "Reactor")
    // Runs only when the ACTUAL selected ID changes to reset UI state
    useEffect(() => {
        if (selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.id) {
            setNavigationExpanded(false);
            setHasUnsavedChanges(false);
            setSubHeaderActionHasChildren(false);
        }
    }, [selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.id, setNavigationExpanded, setSubHeaderActionHasChildren]);
    // 3. BREADCRUMB / LABEL SYNC
    useEffect(() => {
        var _a;
        if (innerMenu && ((_a = location.state) === null || _a === void 0 ? void 0 : _a.label) !== t(innerMenu === null || innerMenu === void 0 ? void 0 : innerMenu.name)) {
            setLocationState({ label: t(innerMenu === null || innerMenu === void 0 ? void 0 : innerMenu.name) });
        }
    }, [setLocationState, t, innerMenu, (_e = location.state) === null || _e === void 0 ? void 0 : _e.label]);
    // --- RENDER ---
    return (React.createElement(DndProvider, { backend: HTML5Backend }, React.createElement(Prompt, { when: hasUnsavedChanges, message: "You have unsaved changes. Are you sure you want to leave this page?" }), React.createElement("div", { className: classes.root }, React.createElement("div", { className: classes.sidebar }, React.createElement(UtilitySideBar, { title: (innerMenu === null || innerMenu === void 0 ? void 0 : innerMenu.name) || menuTitle, isUsingChildren: true, resizable: true, removePadding: true, removeTopLayoutUnit: true, onUtilitySidebarToggleExpandClick: handleSidebarExpandClick, collapsedWidth: 64 }, React.createElement("div", { className: classes.menuContent, key: innerMenuId }, (menuItemsList === null || menuItemsList === void 0 ? void 0 : menuItemsList.length) > 0 &&
        !menuLoading &&
        menuItemsList.map((menuItems, index) => (React.createElement("div", { key: menuItems.id, className: classes.nodeContainer }, React.createElement(BaseTreeMenu, { menuItems: menuItems, onSelectNode: handleSelectedNode, onDropNode: handleDropNode, menuIndex: index, selectedNodeId: selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.id, selectedNodeParentId: selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.parentId, sidebarExpanded: sidebarExpanded, treeViewMode: TreeViewModeEnums.Classic })))), menuLoading && (React.createElement("div", { className: classes.loader }, React.createElement(NodeLoader, { loading: menuLoading })))))), React.createElement("div", { className: classes.content }, mainContent
        ? typeof mainContent === 'function'
            ? mainContent({ selectedNode, menuItemsList })
            : mainContent
        : ((_g = (_f = selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.properties) === null || _f === void 0 ? void 0 : _f.page) === null || _g === void 0 ? void 0 : _g.id) && (React.createElement(PageContainer, { user: user, key: selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.id, pageData: pageData, pageLoading: pageLoading, widgetParams: {
                pageId: pageData === null || pageData === void 0 ? void 0 : pageData.pageId,
                entityName: (_k = (_j = (_h = selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.properties) === null || _h === void 0 ? void 0 : _h.page) === null || _j === void 0 ? void 0 : _j.entity) === null || _k === void 0 ? void 0 : _k.entityName,
                pbiReportCode: (_m = (_l = selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.properties) === null || _l === void 0 ? void 0 : _l.page) === null || _m === void 0 ? void 0 : _m.pbiReportCode,
                requiredFieldsMap: (_p = (_o = selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.properties) === null || _o === void 0 ? void 0 : _o.page) === null || _p === void 0 ? void 0 : _p.requiredFieldMapping,
                udpTagId: (_r = (_q = selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.properties) === null || _q === void 0 ? void 0 : _q.page) === null || _r === void 0 ? void 0 : _r.udpTagId,
                queryId: (_t = (_s = selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.properties) === null || _s === void 0 ? void 0 : _s.page) === null || _t === void 0 ? void 0 : _t.queryId,
                inquiryTreeId: (_v = (_u = selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.properties) === null || _u === void 0 ? void 0 : _u.page) === null || _v === void 0 ? void 0 : _v.inquiryTreeId,
                setHasUnsavedChanges: setHasUnsavedChanges
            }, disableMargins: true, fromMenu: true }))))));
};
export default MenuPage;
//# sourceMappingURL=MenuPage.js.map