import React, { useRef, useState } from 'react';
import PropTypes from 'prop-types';
import { createNamespace } from '../../../tools/namingTools';
import { useRowHeights } from '../../../tools/heights/useRowHeights';
import { useResponsive } from '../../../tools/widths/useResponsive';
import { useItemsGrid } from '../../../tools/widths/useItemsGrid';
import { ANCHOR_PRODUCT_EDITIONS, ANCHOR_PRODUCT_ADDONS } from '../../../constants/anchors';
import { CTA_UPGRADE, CTA_ADD_TO_CART } from '../../../constants/actions';
import { parsePricingAction, handleAddToCartAction } from '../../../tools/callToActions';
import Grid from '../../grid/Grid';
import SlickSlider from '../../slick-slider/SlickSlider';
import ProductEditionCardV2 from '../card/ProductEditionCardV2';
import UpgradeModal from '../../../components/upgrade-modal/UpgradeModal';
import DotsNav from '../../dots-nav/DotsNav';
import './styles/ProductEditionListV2.scss';

const n = createNamespace('ProductEditionListV2');

const childrenRefNames = ['title'];

export const ProductEditionListComponent = ({
    data: {
        editions,
        configurator,
        i18n: i18nProp
    },
    hasAddons,
    selectedEditionId,
    configuratorMode,
    carouselEnabled,
    carouselSlidesToShow,
    hiddenTitle,
    onEditionSelect,
    isIncludedHidden
}) => {
    const [isEditionsCollapsed, setEditionsCollapsedState] = useState(configuratorMode);
    const sliderRef = useRef(null);
    const [containerRef, gridColumns] = useItemsGrid();
    const [itemRefs, childrenRefs, editionHeights] = useRowHeights(editions.length, childrenRefNames);
    const [upgradeDetails, setUpgradeDetails] = useState(null);
    const i18n = { ...ProductEditionListComponent.defaultProps.data.i18n, ...i18nProp };
    const { mediumDown } = useResponsive();
    const isMobile = mediumDown;

    const renderModal = () => {
        const handleClose = () => {
            setUpgradeDetails(null);
        };

        return (
            upgradeDetails && <UpgradeModal upgrades={upgradeDetails} handleClose={handleClose} />
        );
    };

    const renderEdition = (item, index) => {
        const titleRef = childrenRefs.title && childrenRefs.title[index];
        const infoRef = childrenRefs.info && childrenRefs.info[index];
        const mainRef = itemRefs[index];
        const { main, children } = editionHeights;
        const height = main && main[index];
        const titleHeight = children && children.title && children.title[index];
        const infoHeight = children && children.info && children.info[index];
        return (
            <ProductEditionCardV2
                key={item.id}
                data={item}
                i18n={i18n}
                isSelected={!!selectedEditionId && selectedEditionId === item.id}
                configuratorMode={configuratorMode}
                isDetailCollapsed={isEditionsCollapsed}
                ref={{ mainRef, infoRef, titleRef }}
                height={height}
                titleHeight={titleHeight}
                carouselEnabled={carouselEnabled}
                infoHeight={infoHeight}
                onSelect={() => onEditionSelect(item, configurator, setUpgradeDetails)}
                onExpand={() => setEditionsCollapsedState(!isEditionsCollapsed)}
                isIncludedHidden={isIncludedHidden}
            />
        );
    };

    const [currentSlide, setCurrentSlide] = useState(0);
    const afterChange = index => {
        // change of state is necessary on each change,
        // to trigger the layout effect that will check for slide's a11y tabindex
        setCurrentSlide(index);
    };

    const headerModifiers = [hiddenTitle && 'no-title', i18n.viewAddons && 'with-link'];
    const titleModifers = [hiddenTitle && 'hidden', i18n.viewAddons && 'with-link'];

    return (
        <section {...n('wrapper').props} id={ANCHOR_PRODUCT_EDITIONS} ref={containerRef}>
            {(i18n.selectEditionTitle || i18n.viewAddons) && (
                <header {...n('header', headerModifiers).props}>
                    {i18n.selectEditionTitle && <h2 {...n('title', titleModifers).props}>{i18n.selectEditionTitle}</h2>}
                    {!isMobile && hasAddons && <a href={`#${ANCHOR_PRODUCT_ADDONS}`} {...n('headerLink').props}>{i18n.viewAddons}</a>}
                </header>
            )}
            <div {...n('content').props}>
                {carouselEnabled ? (
                    <>
                        <SlickSlider
                            settings={{
                                ref: sliderRef,
                                draggable: false,
                                infinite: false,
                                dots: false,
                                slidesToShow: carouselSlidesToShow,
                                afterChange
                            }}
                        >
                            {editions.map(renderEdition)}
                        </SlickSlider>
                        <div {...n('dots').props}>
                            <DotsNav
                                nItems={editions.length}
                                currentIndex={currentSlide}
                                goTo={sliderRef.current && sliderRef.current.slickGoTo}
                            />
                        </div>
                    </>
                ) : (
                    <Grid maxCol={gridColumns}>
                        {editions.map(renderEdition)}
                    </Grid>
                )}
            </div>

            {renderModal()}
        </section>
    );
};

const priceType = PropTypes.shape({
    formattedFullPriceElements: PropTypes.arrayOf(PropTypes.string),
    originalFullPriceElements: PropTypes.arrayOf(PropTypes.string),
    unit: PropTypes.shape({
        limitLabel: PropTypes.string
    })
});

export const defaultEditionsProps = PropTypes.shape({
    editions: PropTypes.arrayOf(
        PropTypes.shape({
            name: PropTypes.string,
            description: PropTypes.string,
            id: PropTypes.number,
            primary: PropTypes.bool,
            plans: PropTypes.arrayOf(
                PropTypes.shape({
                    costs: PropTypes.shape({
                        flatPrice: priceType,
                        unitPrice: PropTypes.arrayOf(priceType)
                    }),
                    uuid: PropTypes.string
                })
            ),
            audience: PropTypes.arrayOf(
                PropTypes.shape({
                    content: PropTypes.string
                })
            ),
            items: PropTypes.arrayOf(
                PropTypes.shape({
                    content: PropTypes.string
                })
            ),
            bullets: PropTypes.arrayOf(
                PropTypes.shape({
                    content: PropTypes.string,
                    tooltip: PropTypes.string
                })
            )
        })
    ),
    configurator: PropTypes.shape({
        enabled: PropTypes.bool,
        url: PropTypes.string
    }),
    i18n: PropTypes.shape({
        audience: PropTypes.string,
        inclusions: PropTypes.string,
        mostPopular: PropTypes.string,
        selectEditionTitle: PropTypes.string,
        select: PropTypes.string,
        selected: PropTypes.string,
        hideDetails: PropTypes.string,
        viewDetails: PropTypes.string,
        viewAddons: PropTypes.string
    })
});

ProductEditionListComponent.propTypes = {
    data: defaultEditionsProps,
    hasAddons: PropTypes.bool,
    selectedEditionId: PropTypes.number,
    configuratorMode: PropTypes.bool,
    carouselEnabled: PropTypes.bool,
    carouselSlidesToShow: PropTypes.number,
    hiddenTitle: PropTypes.bool,
    onEditionSelect: PropTypes.func,
    isIncludedHidden: PropTypes.bool
};

ProductEditionListComponent.defaultProps = {
    data: {
        editions: [],
        configurator: {
            enabled: true,
            url: ''
        },
        i18n: {
            audience: 'Ideal For',
            inclusions: 'Included',
            mostPopular: 'Most Popular',
            selectEditionTitle: 'Select an edition for this product',
            hideDetails: 'Hide Details',
            viewDetails: 'View Details',
            viewAddons: 'View Add-ons'
        }
    },
    hasAddons: false,
    carouselEnabled: false,
    carouselSlidesToShow: 1,
    selectedEditionId: 0,
    configuratorMode: false,
    hiddenTitle: false,
    isIncludedHidden: false,
    onEditionSelect: (edition, configurator = {}, setUpgradeDetails) => {
        const { id, callToAction = {} } = edition;

        const pricingAction = parsePricingAction(callToAction);
        const paramEdition = `editionId=${id}`;
        const url = configurator.enabled ? `${configurator.url}?${paramEdition}` : pricingAction.url;

        switch (callToAction.actionType) {
            case CTA_UPGRADE:
                setUpgradeDetails(callToAction.popup);
                break;
            case CTA_ADD_TO_CART:
                handleAddToCartAction(edition);
                // FIXME: remove manual reload when the storefront header
                // reloads on cart updates MP-35173
                window.location.reload();
                break;
            default:
                window.location.assign(url);
        }
    }
};

export default ProductEditionListComponent;
