import React, { useEffect, useState } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import { COLORPICKER, GROUP_HEADER, SLIDER, TABS_LIST } from '../../constants/schemaComponentTypes';
import { MAIN_HEADER_ID, UNIVERSAL_HEADER_ELEMENT_ID } from '../../constants/environment';
import { buildCustomizedPageTabs, isFeaturesTabVisible } from '../../tools/parsers/pageTabsParser';
import { createNamespace } from '../../tools/namingTools';
import Button from '../../atoms/button/Button';
import ButtonIcon from '../../atoms/button-icon/ButtonIcon';
import Icon from '../../atoms/icon/Icon';
import './styles/TabsMenu.scss'; // eslint-disable-line import/no-duplicates
// import { topNavMinHeight } from './styles/TabsMenu.scss'; // eslint-disable-line import/no-duplicates
import { ALLOWED_CTA_TYPES, CTA_BUY, CTA_BUY_MORE, CTA_DOMAIN_ADD_TO_CART, CTA_ADD_TO_CART } from '../../constants/actions';
import { NAMESPACES } from '../../constants/namespaces';
import { ORDERABLE_COMPONENTS } from '../page-orderable-container/PageOrderableContainer';
import { useResponsive } from '../../tools/widths/useResponsive';
import { domainAppDataStore } from '../../store/domainApp';
import { PROFILE_TABS } from '../../constants/profileTabs';
import { profilePageDataStore } from '../../store/profilePageData';
import { cartPreviewStore } from '../../store/cartPreview';
import { handleAddToCartAction } from '../../tools/callToActions';
import { isProductEditionAddedToCart } from '../../tools/cart';
import { editionPropTypes } from '../../constants/prop-types/application/editions';
import { addonShape } from '../../constants/components/prop-types/addon';

import withListener from '../withListener';

const n = createNamespace('TabsMenu');

/*
    Mapping between IDs and anchors. This mapping is required for the
    scroll to section functionality in Overview to work.
*/
export const anchorToIdMapping = (() => {
    const anchorToIdMap = {};
    Object.values(ORDERABLE_COMPONENTS).forEach(value => {
        const schema = value.schema();
        if (schema.anchor && schema.name) {
            anchorToIdMap[schema.anchor] = schema.name;
        }
    });
    return anchorToIdMap;
})();

export const TabsMenuComponent = ({
    data: {
        navigation: {
            items,
            i18n: i18nNavigation
        },
        callToActions,
        summary,
        config,
        locale,
        editions,
        addonProducts,
        defaultSelectedEdition,
        i18n
    },
    settings
}) => {
    const settingsWithDefaults = { ...TabsMenuComponent.defaultProps.settings, ...settings };
    const {
        pageTabs: settingsPageTabs,
        textColor,
        textActiveColor,
        backgroundColor,
        borderColor,
        height,
        linkSpacing
    } = settingsWithDefaults;

    const cssVars = {
        textColor,
        textActiveColor,
        backgroundColor,
        borderColor,
        height: height ? `${height}px` : '',
        linkSpacing: linkSpacing ? `${linkSpacing}px` : ''
    };
    const { largeDown } = useResponsive();
    const [isMobileMenu, setMobileMenuState] = useState(false);
    const [isMenuCollapsed, setCollapseMenuState] = useState(true);
    const [portal, setPortal] = useState(null);
    const [contentTabs, setContentTabs] = useState(items);
    const { setIsFeaturesLinkEnabled } = profilePageDataStore();

    const hasNav = Boolean(contentTabs && contentTabs.length);

    const i18nNavigationWithDefaults = { ...TabsMenuComponent.defaultProps.data.navigation.i18n, ...i18nNavigation };

    useEffect(() => {
        if (settingsPageTabs && settingsPageTabs.length) {
            setContentTabs(buildCustomizedPageTabs(items, settingsPageTabs));
            setIsFeaturesLinkEnabled(isFeaturesTabVisible(settingsPageTabs));
        }
    }, [settingsPageTabs, items]);

    const { cart, fetchCart } = cartPreviewStore();

    // fetch once, cart is updated by zustand store
    useEffect(() => {
        fetchCart(locale);
    }, [fetchCart, locale]);

    const isAddedToCart = isProductEditionAddedToCart(editions?.items, cart, config?.uuid, config?.type, addonProducts);

    useEffect(() => {
        setMobileMenuState(largeDown);
    }, [largeDown]);

    // on mobile, create a sticky portal to move element in the DOM, under universal header
    // Since sfb toolkit 3.0.0 we need to also support a new main header id and apply the same logic
    useEffect(() => {
        if (!portal) {
            const header = document.querySelector(`#${UNIVERSAL_HEADER_ELEMENT_ID}`) || document.querySelector(`#${MAIN_HEADER_ID}`);
            if (!header) {
                return;
            }
            const domNode = document.createElement('div');
            domNode.classList.add(n('stickyContainer').props.className);
            header.after(domNode);
            setPortal(domNode);
        }
    }, [largeDown, portal]);

    const { callToActions: domainsCallToActions, handleBuyNowDomains, handleAddToCartDomains } = domainAppDataStore();

    const renderTopNavButton = item => {
        const { actionType, disabled, icon, label, leadPageUrl, type, url } = item;
        const ctaIcon = icon || ((actionType === CTA_BUY || actionType === CTA_BUY_MORE) && 'cart');

        const modifiers = ctaIcon ? 'with-icon' : '';
        let action;
        let buttonType = type || 'emphasis';
        switch (actionType) {
            case CTA_BUY_MORE:
                action = () => handleBuyNowDomains(actionType);
                break;
            case CTA_DOMAIN_ADD_TO_CART:
                action = handleAddToCartDomains;
                break;
            case CTA_ADD_TO_CART:
                buttonType = 'emphasisAlt';
                action = () => handleAddToCartAction(defaultSelectedEdition);
                break;

            default:
        }

        const buttonProps = {
            type: buttonType,
            size: 'small',
            onClick: action,
            url: !action ? url || leadPageUrl : null,
            disabled,
            ctaType: actionType,
            referUrl: config && config.referUrl
        };

        if (actionType === CTA_ADD_TO_CART && isAddedToCart) {
            return (
                <div {...n('topNavButton').props} key="addedToCart">
                    <ButtonIcon
                        {...buttonProps}
                        theme="emphasisAlt-outline"
                        type="button"
                        icon="check"
                        notClickable
                        iconClass="addedToCart"
                        size="small"
                        className="buttonIcon"
                    >
                        {i18n.cart.addedToCart}
                    </ButtonIcon>
                </div>
            );
        }

        return (
            <div {...n('topNavButton', modifiers).props} key={url || label}>
                <Button {...buttonProps}>
                    {label}
                    {ctaIcon && <Icon type={ctaIcon} />}
                </Button>
            </div>
        );
    };

    const renderLogo = () => {
        if (!summary || !summary.title || !summary.logoSrc) {
            return null;
        }
        const { title, logoSrc } = summary;

        return (<img src={logoSrc} alt={title} {...n('topNavThumbnail').props} />);
    };

    const renderCtas = () => {
        const finalCtas = domainsCallToActions || (callToActions && callToActions.items);

        if (!finalCtas) {
            return null;
        }

        return (
            <div {...n('btnContainer').props}>
                {finalCtas.map(renderTopNavButton)}
            </div>
        );
    };

    const content = (
        <div>
            {(isMobileMenu || hasNav) && (
                <div {...n('container').withVariables(cssVars).withTestId().withE2EId().props}>
                    <nav {...n('nav', [hasNav && 'with-nav', isMobileMenu && 'mobile']).props} aria-label={i18nNavigationWithDefaults.label}>
                        {isMobileMenu && (
                            <div {...n('topNav', hasNav && 'with-nav').props}>
                                {hasNav ? (
                                    <div {...n('btnMenu', !isMenuCollapsed ? 'is-opened' : '').props}>
                                        <Button type="white" onClick={() => setCollapseMenuState(!isMenuCollapsed)}>
                                            {i18nNavigationWithDefaults.mobileMenuLabel}
                                            <Icon type="caretUp" />
                                        </Button>
                                    </div>
                                ) : null}
                                {renderLogo()}
                                {renderCtas()}
                            </div>
                        )}
                        {hasNav ? (
                            <div {...n('menu').props}>
                                <ul {...n('list', !isMenuCollapsed ? 'is-opened' : '').props}>
                                    {contentTabs.filter(item => item.isVisible)
                                        .map(({ href, label, selected, value }) => (
                                            <li {...n('item').props} key={value}>
                                                <a
                                                    {...n('link', selected ? 'selected' : null).withClass(`tab-${value}`).withTestId().withE2EId().props}
                                                    href={href}
                                                >
                                                    {label && label.value ? label.value : label}
                                                </a>
                                            </li>
                                        ))}
                                </ul>
                            </div>
                        ) : null}
                    </nav>
                </div>
            )}
        </div>
    );

    // on desktop, element is placed normally in the flow
    if (!largeDown || !portal) {
        return content;
    }

    // on mobile, element needs to be right after universal header in the DOM
    return ReactDOM.createPortal(
        content,
        portal
    );
};

TabsMenuComponent.schema = () => ({
    name: 'ProductTabMenu',
    title: 'uieditor.sfbComponent.tabsMenu.title',
    orderableSection: [NAMESPACES.profile],
    iconName: 'pageTabs',
    form: {
        pageTabs: {
            type: TABS_LIST,
            defaultValue: [
                PROFILE_TABS.overview, PROFILE_TABS.features, PROFILE_TABS.reviews,
                PROFILE_TABS.questions, PROFILE_TABS.policies, PROFILE_TABS.resources,
                PROFILE_TABS.editions
            ]
        },
        headingSpacer: {
            type: GROUP_HEADER,
            title: 'uieditor.sfbComponent.tabsMenu.settings.title',
            symbol: 'style'
        },
        linkSpacing: {
            title: 'uieditor.sfbComponent.tabsMenu.linkSpacing.title',
            type: SLIDER,
            required: true,
            defaultValue: 30,
            options: {
                step: 1,
                min: 4,
                max: 150
            }
        },
        height: {
            title: 'uieditor.sfbComponent.tabsMenu.height.title',
            type: SLIDER,
            required: true,
            defaultValue: 50,
            options: {
                step: 1,
                min: 16,
                max: 100
            }
        },
        headingSpacerText: {
            type: GROUP_HEADER,
            title: 'uieditor.sfbComponent.tabsMenu.color.title',
            symbol: 'style'
        },
        textColor: {
            title: 'uieditor.sfbComponent.tabsMenu.textColor.title',
            defaultValue: '#9C9C9C',
            type: COLORPICKER
        },
        textActiveColor: {
            title: 'uieditor.sfbComponent.tabsMenu.textActiveColor.title',
            type: COLORPICKER
        },
        headingSpacerBg: {
            type: GROUP_HEADER,
            title: 'uieditor.sfbComponent.tabsMenu.background.title',
            symbol: 'style'
        },
        borderColor: {
            title: 'uieditor.sfbComponent.tabsMenu.borderColor.title',
            defaultValue: '#CBCBCB',
            type: COLORPICKER
        },
        backgroundColor: {
            title: 'uieditor.sfbComponent.tabsMenu.backgroundColor.title',
            defaultValue: '#fff',
            type: COLORPICKER
        }
    },
    marketplaceData: {
        summary: 'application.summary',
        callToActions: 'application.callToActions',
        navigation: 'application.navigation',
        config: 'application.config',
        locale: 'config.locale.code',
        editions: 'application.editions',
        addonProducts: 'application.addonProducts',
        defaultSelectedEdition: 'application.defaultSelectedEdition',
        i18n: 'i18n'
    }
});

TabsMenuComponent.propTypes = {
    data: PropTypes.shape({
        navigation: PropTypes.shape({
            items: PropTypes.arrayOf(
                PropTypes.shape({
                    label: PropTypes.string,
                    href: PropTypes.string,
                    value: PropTypes.string,
                    selected: PropTypes.bool
                })
            ),
            i18n: PropTypes.shape({
                label: PropTypes.string,
                mobileMenuLabel: PropTypes.string
            })
        }),
        summary: PropTypes.shape({
            logoSrc: PropTypes.string,
            title: PropTypes.string
        }),
        config: PropTypes.object,
        callToActions: PropTypes.shape({
            items: PropTypes.arrayOf(
                PropTypes.shape({
                    label: PropTypes.string,
                    tooltip: PropTypes.string,
                    isPrimary: PropTypes.bool,
                    disabled: PropTypes.bool,
                    url: PropTypes.string,
                    actionType: PropTypes.oneOf(ALLOWED_CTA_TYPES)
                })
            )
        }),
        defaultSelectedEdition: PropTypes.shape(editionPropTypes),
        editions: PropTypes.shape({
            items: PropTypes.arrayOf(PropTypes.shape(editionPropTypes))
        }),
        addonProducts: addonShape,
        i18n: PropTypes.shape({
            cart: PropTypes.shape({
                addedToCart: PropTypes.string
            })
        }),
        locale: PropTypes.string
    }),
    settings: PropTypes.shape({
        height: PropTypes.number,
        linkSpacing: PropTypes.number,
        textColor: PropTypes.string,
        textActiveColor: PropTypes.string,
        backgroundColor: PropTypes.string,
        borderColor: PropTypes.string
    })
};

const SETTINGS = TabsMenuComponent.schema().form;

TabsMenuComponent.defaultProps = {
    data: {
        navigation: {
            items: [],
            i18n: {
                label: 'Product',
                mobileMenuLabel: 'More'
            }
        },
        callToActions: {},
        summary: {},
        config: {},
        defaultSelectedEdition: null,
        editions: {},
        i18n: {
            cart: {
                addedToCart: 'Added to Cart'
            }
        },
        locale: 'en-US'

    },
    settings: Object.keys(SETTINGS).reduce((defaults, settingKey) => (
        {
            ...defaults,
            [settingKey]: SETTINGS[settingKey].defaultValue
        }
    ), {})
};

export default withListener(TabsMenuComponent);
