import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { createNamespace } from '../../../../../tools/namingTools';

import { headerCategoriesMenuDefaultSettings, headerCategoriesMenuSchemaForm } from '../../../../../constants/components/schemas/header';
import { categoryShape, headerCategoriesMenuSettingsShape } from '../../../../../constants/components/prop-types/header';

import Link from '../../../../../atoms/link/Link';
import ButtonIcon from '../../../../../atoms/button-icon/ButtonIcon';

import './styles/HeaderCategoriesMenu.scss';

const n = createNamespace('HeaderCategoriesMenu');

const HeaderCategoriesMenu = ({
    className: extraClass,
    listingEndpoint,
    categories,
    i18n: i18nProp,
    toggleHeaderScrimFunction,
    settings: settingsProp
}) => {
    const [subMenusLevelsOpen, setSubMenusLevelsOpen] = useState(0);

    const settings = {
        ...HeaderCategoriesMenu.defaultProps.settings,
        ...settingsProp
    };

    const {
        catMenuTextSize,
        catMenuRowSpacing,
        catMenuTitleColor,
        catMenuTextColor,
        catMenuTextHoverColor,
        catMenuTextActiveColor,
        catMenuBackgroundColor,
        catMenuBgColorHover,
        catMenuBgColorActive
    } = settings;

    const i18n = {
        ...HeaderCategoriesMenu.defaultProps.i18n,
        i18nProp
    };

    const renderCategories = (currentBranch, level = 1, parentHref = null) => {
        const isSubMenu = level > 1;
        const branchModifiers = [
            `level-${level}`,
            isSubMenu && 'submenu',
            subMenusLevelsOpen === level && 'open'
        ];
        const bgModifiers = [
            ...branchModifiers,
            isSubMenu && 'with-transition'
        ];
        const openSubmenu = () => {
            setSubMenusLevelsOpen(level + 1);
            toggleHeaderScrimFunction(true);
        };
        const closeSubmenu = () => {
            setSubMenusLevelsOpen(level);
            toggleHeaderScrimFunction(false);
        };
        return (
            <div {...n('categoriesListWrapper', branchModifiers).props}>
                <div {...n('categoriesListBg', bgModifiers).props} aria-hidden="true" />
                <ul
                    {...n('categoriesList', branchModifiers)
                        .withTestId(`catListLevel${level}`)
                        .props}
                    onMouseLeave={closeSubmenu}
                >
                    <li
                        {...n('categoryItem').withTestId(`catListItem${level}`).props}
                        onFocus={openSubmenu}
                        onMouseOver={openSubmenu}
                    >
                        <Link
                            {...n('categoryLink').withTestId(`catLinkLevel${level}`).props}
                            href={parentHref ?? listingEndpoint}
                        >
                            {i18n.viewall}
                        </Link>
                    </li>
                    {currentBranch.map(category => {
                        const hasSubCategories = (category.subCategories && category.subCategories.length > 0);
                        return (
                            // eslint-disable-next-line jsx-a11y/mouse-events-have-key-events
                            <li
                                {...n('categoryItem').withTestId(`catListItem${level}`).props}
                                key={category.id}
                                onMouseOver={openSubmenu}
                            >
                                {hasSubCategories ? (
                                <>
                                    <ButtonIcon
                                        {...n('categoryLink').withTestId(`catLinkLevel${level}`).props}
                                        type="link"
                                        icon="caretRight"
                                        iconPosition="right"
                                        onFocus={openSubmenu}
                                        onBlur={closeSubmenu}
                                    >
                                        {category.name}
                                    </ButtonIcon>
                                    {renderCategories(category.subCategories, level + 1, category.hrefListing)}
                                </>
                                ) : (
                                    <Link
                                        {...n('categoryLink').withTestId(`catLinkLevel${level}`).props}
                                        href={category.hrefListing}
                                    >
                                        {category.name}
                                    </Link>
                                )}
                            </li>
                        );
                    })}
                </ul>
            </div>
        );
    };

    const styleVariables = {
        'row-height': `${catMenuRowSpacing}px`,
        'title-color': catMenuTitleColor,
        'categories-text-color': catMenuTextColor,
        'categories-text-hover-color': catMenuTextHoverColor,
        'categories-text-active-color': catMenuTextActiveColor,
        'bg-color': catMenuBackgroundColor,
        'bg-color-hover': catMenuBgColorHover,
        'bg-color-active': catMenuBgColorActive
    };

    return (
        <div
            {...n('wrapper', [`text-${catMenuTextSize}`])
                .withClass(extraClass)
                .withVariables(styleVariables)
                .withTestId('wrapper')
                .props}
        >
            <nav {...n('navWrapper').props} aria-label={i18n.categories}>
                {renderCategories(categories)}
            </nav>
        </div>
    );
};

HeaderCategoriesMenu.schema = () => ({
    name: 'Header Categories Menu',
    title: 'uieditor.sfbComponent.header.categoriesMenu.title',
    iconName: 'categories',
    form: headerCategoriesMenuSchemaForm
});

HeaderCategoriesMenu.propTypes = {
    className: PropTypes.string,
    categories: PropTypes.arrayOf(PropTypes.shape(categoryShape)),
    listingEndpoint: PropTypes.string,
    i18n: PropTypes.shape({
        categories: PropTypes.string,
        viewall: PropTypes.string
    }),
    settings: PropTypes.shape(headerCategoriesMenuSettingsShape),
    toggleHeaderScrimFunction: PropTypes.func
};

HeaderCategoriesMenu.defaultProps = {
    className: null,
    categories: [],
    listingEndpoint: '/',
    i18n: {
        categories: 'Categories',
        viewall: 'View All'
    },
    settings: headerCategoriesMenuDefaultSettings,
    toggleHeaderScrimFunction: () => {}
};

export default HeaderCategoriesMenu;
