import React, { useState, useEffect, createRef } from 'react';
import PropTypes from 'prop-types';
import { createNamespace } from '../../../../../tools/namingTools';
import { generateUniqueID } from '../../../../../tools/helpers';
import { categoryShape, headerSettingsShape } from '../../../../../constants/components/prop-types/header';
import { generateUserLinks, getMenu } from '../../../../../tools/components/header';
import { USER_BRANCH_OPEN } from '../../../../../constants/components/header';
import ButtonIcon from '../../../../../atoms/button-icon/ButtonIcon';
import Avatar from '../../../../../atoms/avatar/Avatar';
import Link from '../../../../../atoms/link/Link';
import HeaderMobileList from '../header-mobile-list/HeaderMobileList';
import { MENUS } from '../../../../../constants/menus';
import { getPropValue } from '../../../../../tools/objectTools';
import { getOnlyProductLines,
    isSameProductLineEntry,
    getNavigationBarPrevData,
    getFormattedProductLinesData } from '../header-navigation-utils/headerNavigationUtils';
import { getListingUrlForProductLines } from '../../../../../tools/urlTools';
// IMPORTANT: (s)css should be imported after other atoms/components
import './styles/HeaderMobile.scss';
import { getMemberships,
    getCompanyListItems } from '../../../utils/companySwitcherUtils';

const n = createNamespace('HeaderMobile');

const MENU_LEVEL_1 = 1;
const MENU_LEVEL_2 = 2;

export const mergeNavigationBarData = (productLines, navigationBarData) => {
    const onlyInProductLines = productLines && navigationBarData
        ? getOnlyProductLines(productLines, navigationBarData, isSameProductLineEntry)
        : [];
    const result = [
        ...getNavigationBarPrevData(productLines, navigationBarData),
        ...getFormattedProductLinesData(onlyInProductLines)
    ];
    return result;
};

const generateNavBarData = (nav, navBarItems) => {
    const secondaryItems = nav?.secondary?.items || [];
    const secondaryItemsFiltered = secondaryItems.reduce((filtered, item) => {
        if (!item.key) {
            const { href } = item;
            const id = parseInt((href.split('=')[1]), 10);
            filtered.push({ ...item, id });
        }
        return filtered;
    }, []);

    return mergeNavigationBarData(secondaryItemsFiltered, navBarItems);
};

const HeaderMobile = ({
    className,
    categories,
    listingEndpoint,
    user,
    baseUrl,
    i18n: i18nProp,
    settings,
    nav,
    locale,
    picture,
    channelSettings,
    config
}) => {
    const [activeBranches, setActiveBranches] = useState([]);
    const mainNavRef = createRef();
    const activeBranchRef = createRef();
    const [memberships, setMemberships] = useState([]);

    const setMainNavHeight = () => {
        const mainNav = mainNavRef.current;
        const activeBranch = activeBranchRef.current;
        if (activeBranch) {
            const { height } = activeBranch.getBoundingClientRect();
            mainNav.style.setProperty('--main-nav-height', `${height}px`);
        } else {
            mainNav.style.removeProperty('--main-nav-height');
        }
    };
    useEffect(setMainNavHeight);

    const branchIsActive = branch => (activeBranches[activeBranches.length - 1] === branch);

    const i18n = {
        ...HeaderMobile.defaultProps.i18n,
        ...i18nProp
    };
    const {
        catMenuTextSize,
        catMenuBackgroundColor,
        catMenuBgColorHover,
        catMenuBgColorActive,
        catMenuTextHoverColor,
        catMenuTextActiveColor,
        catMenuTextColor,
        catMenuRowSpacing,
        auxBarBackgroundColor,
        auxBarTextColor,
        auxBarMenuItems,
        navBarMenuItems,
        homeBarMenuItems
    } = settings;

    const auxBarItems = getMenu(auxBarMenuItems, MENUS.AUXILIARY_BAR_MENU);
    const navBarItems = getMenu(navBarMenuItems, MENUS.NAVIGATION_BAR_MENU);
    const homeBarItems = getMenu(homeBarMenuItems, MENUS.HOME_BAR_MENU);

    const [navBarData] = useState(() => generateNavBarData(nav, navBarItems));

    const wrapperStyles = {
        'main-nav-bg-color': catMenuBackgroundColor,
        'main-nav-bg-color-hover': catMenuBgColorHover,
        'main-nav-bg-color-active': catMenuBgColorActive,
        'main-nav-text-color': catMenuTextColor,
        'main-nav-text-color-hover': catMenuTextHoverColor,
        'main-nav-text-color-active': catMenuTextActiveColor,
        'items-height': catMenuRowSpacing && `${catMenuRowSpacing}px`,
        'aux-nav-bg-color': auxBarBackgroundColor,
        'aux-nav-text-color': auxBarTextColor
    };

    const mainNavVariables = {
        'left-level-1': `-${activeBranches.length * 100}%`
    };

    const goToNextBranch = branch => {
        const ab = activeBranches.slice();
        ab.push(branch);
        setActiveBranches(ab);
    };
    const goToPreviousBranch = () => {
        const ab = activeBranches.slice();
        ab.pop();
        setActiveBranches(ab);
    };

    const hideMenuItems = (
        isVisible,
        titleText,
        isMenuItemHidden
    ) => !!(!isVisible || !titleText || isMenuItemHidden);

    const renderLink = (
        { label, url, hasChildren, onClick, target, headerItem, isSubMenu, openInNewTab }
    ) => (hasChildren && !headerItem ? (
        <ButtonIcon
            {...n('menuLink').props}
            type="link"
            icon="caretRight"
            iconPosition="right"
            url={url}
            openUrlInNewTab={openInNewTab}
            onClick={onClick}
        >
            <span {...n('menuLabel').props}>{label}</span>
        </ButtonIcon>
    ) : (
        <Link
            {...n('menuLink', isSubMenu && 'subMenuLink').withTestId().props}
            href={url}
            target={target}
        >
            <span {...n('menuLabel').props}>{label}</span>
        </Link>
    ));

    const renderCategories = (categoriesList, level = 1, parentCategory = null) => {
        const isSubmenu = level > 1;
        const backButtonLabel = parentCategory ? parentCategory.name : i18n.backToMainMenu;
        const viewAllLink = parentCategory ? parentCategory.hrefListing : listingEndpoint;
        return (
            <>
                {isSubmenu && (
                    <li {...n('menuItem', 'branches-navigation').props}>
                        <ButtonIcon
                            {...n('menuPreviousButton').props}
                            icon="caretLeft"
                            onClick={goToPreviousBranch}
                        >
                            <span {...n('menuLabel').props}>{backButtonLabel}</span>
                        </ButtonIcon>
                    </li>
                )}
                <li {...n('menuItem').withTestId('viewAll').props}>
                    <Link
                        {...n('menuLink').props}
                        href={viewAllLink}
                    >
                        {i18n.viewall}
                    </Link>
                </li>
                {categoriesList.map(category => {
                    const hasSubCategories = Boolean(category.subCategories && category.subCategories.length);
                    const isActive = branchIsActive(category.subCategories);
                    return (
                        <li
                            {...n('menuItem').withTestId('category').props}
                            key={generateUniqueID([category.name, category.url])}
                        >
                            {renderLink({
                                label: category.name,
                                hasChildren: hasSubCategories,
                                onClick: () => goToNextBranch(category.subCategories),
                                headerItem: false,
                                url: !hasSubCategories && category.hrefListing
                            })}
                            {hasSubCategories && (
                                <HeaderMobileList
                                    {...n('menuList').props}
                                    level={level}
                                    isActive={isActive}
                                    ref={(isActive && activeBranchRef) || null}
                                    isVisible={activeBranches.includes(category.subCategories)}
                                >
                                    {renderCategories(category.subCategories, level + 1, category)}
                                </HeaderMobileList>
                            )}
                        </li>
                    );
                })}
            </>
        );
    };

    useEffect(() => {
        const fetchMemberships = async () => {
            const membership = await getMemberships(config);
            setMemberships(membership);
        };
        fetchMemberships();
    }, []);

    const renderMenuItems = (items, level = MENU_LEVEL_1, parentItem = null) => {
        const isSubmenu = level > MENU_LEVEL_1;
        const backButtonLabel = parentItem ? parentItem.label : i18n.backToMainMenu;
        return (
            <>
                {isSubmenu && (
                    <li {...n('menuItem', 'branches-navigation').props}>
                        <ButtonIcon
                            {...n('menuPreviousButton').props}
                            icon="caretLeft"
                            onClick={goToPreviousBranch}
                        >
                            <span {...n('menuLabel').props}>{backButtonLabel}</span>
                        </ButtonIcon>
                    </li>
                )}
                {items.map(item => {
                    if (!item) {
                        return null;
                    }

                    const { label, url } = item;
                    const subBranches = items.items;
                    const hasSubBranches = Boolean(subBranches && subBranches.length);
                    const isActive = branchIsActive(item.items);
                    const isCompanyItem = label === i18n.company;
                    return (
                        <React.Fragment
                            key={generateUniqueID([label, url])}
                        >
                            <li
                                {...n('menuItem').withTestId('menuItem').props}
                                key={generateUniqueID([label, url])}
                            >
                                {renderLink({
                                    label,
                                    url,
                                    hasChildren: hasSubBranches,
                                    onClick: () => goToNextBranch(item.items)
                                })}
                                {isCompanyItem && memberships.length > 1 && (
                                    <>
                                        <li {...n('userDropdownItem', 'userDropdownCompanySwitcher').props}>
                                            {i18n.companySwitcher}
                                        </li>
                                        {getCompanyListItems(memberships, config, n, i18n, 'menuLink')}
                                        <hr {...n('menuDivider').props} />
                                    </>
                                )}
                                {hasSubBranches && (
                                    <HeaderMobileList
                                        {...n('menuList').props}
                                        level={level}
                                        isVisible={activeBranches.includes(item.items)}
                                        ref={(isActive && activeBranchRef) || null}
                                        isActive={isActive}
                                    >
                                        {renderMenuItems(items.items, level + 1, items)}
                                    </HeaderMobileList>
                                )}
                            </li>
                        </React.Fragment>
                    );
                })}
            </>
        );
    };

    const renderHeaderMenuItems = (menuType, items, level = MENU_LEVEL_1) => {
        const isSubMenu = level > MENU_LEVEL_1;
        const backButtonLabel = i18n.backToMainMenu;
        const getTestId = () => {
            switch (menuType) {
                case MENUS.NAVIGATION_BAR_MENU:
                    return 'navmenuItem';
                case MENUS.HOME_BAR_MENU:
                    return 'homemenuItem';
                case MENUS.AUXILIARY_BAR_MENU:
                    return 'auxmenuItem';
                default:
                    return '';
            }
        };
        return (
            <>
                {isSubMenu && (
                    <li {...n('menuItem', 'branches-navigation').props}>
                        <ButtonIcon
                            {...n('menuPreviousButton').props}
                            icon="caretLeft"
                            onClick={goToPreviousBranch}
                        >
                            <span {...n('menuLabel').props}>{backButtonLabel}</span>
                        </ButtonIcon>
                    </li>
                )}
                {items && items.map(item => {
                    const { isVisible, openInNewTab, children, uuid, editorType, customData } = item;
                    const titleText = getPropValue(item, 'title.value');
                    let linkUrl = getPropValue(item, 'link.value');
                    const isMenuItemHidden = !isSubMenu
                        && !((children && activeBranches.includes(children))
                            || activeBranches.length === 0);

                    if (hideMenuItems(isVisible, titleText, isMenuItemHidden)) {
                        return null;
                    }

                    if (editorType === 'PRODUCT_LINES') {
                        linkUrl = getListingUrlForProductLines(locale.code, customData && customData.externalUUID);
                    }
                    const subBranches = children;
                    const hasChildren = Boolean(subBranches && subBranches.length);
                    const target = openInNewTab ? '_blank' : null;
                    const isActive = branchIsActive(children);
                    return (
                        <li
                            {...n('menuItem').withTestId(getTestId()).props}
                            key={uuid}
                        >
                            {renderLink({
                                label: titleText,
                                url: linkUrl,
                                hasChildren,
                                onClick: () => goToNextBranch(children),
                                openInNewTab,
                                target,
                                isSubMenu
                            })}
                            {hasChildren && (
                                <HeaderMobileList
                                    {...n('menuList').withTestId('userDropdownList').props}
                                    level={MENU_LEVEL_2}
                                    isVisible={activeBranches.includes(children)}
                                    ref={(isActive && activeBranchRef) || null}
                                    isActive={isActive}
                                >
                                    {renderHeaderMenuItems(menuType, children, MENU_LEVEL_2, item)}
                                </HeaderMobileList>
                            )}
                        </li>
                    );
                })}
            </>
        );
    };

    const isCategoryBranchActive = branchIsActive(categories);
    const isUserBranchActive = branchIsActive(USER_BRANCH_OPEN);

    return (
        <div {...n('wrapper', `${catMenuTextSize}-text`).withClass(className).withVariables(wrapperStyles).props}>
            <nav
                {...n('mainNavWrapper').withTestId().withVariables(mainNavVariables).props}
                aria-label={i18n.mainNavigation}
                ref={mainNavRef}
            >
                <HeaderMobileList
                    {...n('menuList').props}
                    level={1}
                    isVisible
                    isActive={activeBranches.length === 0}
                >
                    {user.isLoggedIn && (
                        <li {...n('menuItem', 'user-profile').props}>
                            <ButtonIcon
                                {...n('menuLink').props}
                                type="link"
                                icon="caretRight"
                                iconPosition="right"
                                onClick={() => goToNextBranch(USER_BRANCH_OPEN)}
                            >
                                <span {...n('userProfile').withTestId('userProfile').props}>
                                    <Avatar
                                        {...n('userAvatar').props}
                                        name={user.name}
                                        size={30}
                                        borderRadius={3}
                                        picture={picture}
                                    />
                                    <span {...n('menuLabel').props}>{user.name}</span>
                                </span>
                            </ButtonIcon>
                            <HeaderMobileList
                                {...n('menuList', ['level-2', 'submenu', 'hidden']).withTestId('userDropdownList').props}
                                level={2}
                                isVisible={activeBranches.includes(USER_BRANCH_OPEN)}
                                isActive={isUserBranchActive}
                                ref={(isUserBranchActive && activeBranchRef) || null}
                            >
                                {renderMenuItems(generateUserLinks(baseUrl, user, i18n, channelSettings), 2)}
                            </HeaderMobileList>
                        </li>
                    )}
                    {Boolean(categories && categories.length)
                        && (
                            <li {...n('menuItem').withTestId('allProducts').props}>
                                {renderLink({
                                    label: i18n.allProducts,
                                    hasChildren: true,
                                    onClick: () => goToNextBranch(categories)
                                })}
                                <HeaderMobileList
                                    {...n('menuList').props}
                                    isVisible={activeBranches.includes(categories)}
                                    ref={(isCategoryBranchActive && activeBranchRef) || null}
                                    isActive={isCategoryBranchActive}
                                    level={2}
                                >
                                    {renderCategories(categories, 2)}
                                </HeaderMobileList>
                            </li>
                        )}
                    {renderHeaderMenuItems(
                        MENUS.NAVIGATION_BAR_MENU,
                        navBarData
                    )}
                    {renderHeaderMenuItems(MENUS.HOME_BAR_MENU, homeBarItems)}
                    {Boolean(auxBarItems && auxBarItems.length)
                        && (
                            <nav
                                {...n('auxNavWrapper').withTestId().props}
                                aria-label={i18n.auxNavigation}
                            >
                                {renderHeaderMenuItems(MENUS.AUXILIARY_BAR_MENU, auxBarItems)}
                            </nav>
                        )}
                </HeaderMobileList>
            </nav>
        </div>
    );
};

HeaderMobile.propTypes = {
    className: PropTypes.string,
    categories: PropTypes.arrayOf(PropTypes.shape(categoryShape)),
    navBarMenuItems: PropTypes.array,
    settings: PropTypes.shape(headerSettingsShape),
    i18n: PropTypes.shape({
        allProducts: PropTypes.string,
        viewall: PropTypes.string,
        backToMainMenu: PropTypes.string,
        profile: PropTypes.string,
        account: PropTypes.string,
        company: PropTypes.string,
        settings: PropTypes.string,
        logout: PropTypes.string,
        mainNavigation: PropTypes.string,
        auxNavigation: PropTypes.string
    }),
    listingEndpoint: PropTypes.string,
    baseUrl: PropTypes.string,
    user: PropTypes.shape({
        isLoggedIn: PropTypes.bool,
        name: PropTypes.string,
        userUuid: PropTypes.string,
        companyUuid: PropTypes.string
    }),
    nav: PropTypes.object,
    locale: PropTypes.object,
    picture: PropTypes.string,
    channelSettings: PropTypes.object,
    config: PropTypes.object
};

HeaderMobile.defaultProps = {
    className: undefined,
    categories: [],
    navBarMenuItems: [],
    settings: {},
    baseUrl: '/',
    listingEndpoint: '/',
    i18n: {
        allProducts: 'All Products',
        viewall: 'View All',
        backToMainMenu: 'Back to Main Menu',
        profile: 'Profile',
        account: 'Account',
        company: 'Company',
        settings: 'Settings',
        logout: 'Logout',
        mainNavigation: 'Main Navigation',
        auxNavigation: 'Auxiliary Navigation',
        companySwitcher: 'SWITCH COMPANIES',
        currentCompany: 'CURRENT COMPANY'
    },
    user: {},
    nav: {},
    locale: {
        code: 'en-US'
    },
    picture: null,
    channelSettings: {
        showProfiles: true
    },
    config: {}
};

export default HeaderMobile;
