import React from 'react';
import PropTypes from 'prop-types';
import Grid from '../../atoms/grid/Grid';
import Button from '../../atoms/button/Button';
import Image from '../../atoms/image/Image';
import { createNamespace } from '../../tools/namingTools';
import { generateUniqueID, parseToBool } from '../../tools/helpers';
import { stripSlash, lowerFirst } from '../../tools/stringTools';
import { useContainerWidth } from '../../tools/widths/useContainerWidth';
import { TOGGLE, DROPDOWN } from '../../constants/schemaComponentTypes';
import { MEDIUM, LARGE } from '../../constants/sizes';
import { NAMESPACES } from '../../constants/namespaces';
import { bSmall } from '../../constants/breakpoints';
import withListener from '../withListener';
import './styles/ProductDescription.scss';

const n = createNamespace('ProductDescription');

export const ProductDescriptionComponent = ({
    settings,
    data: {
        addonProducts = [],
        hidePricings,
        overview: { title, description, pricingUrl, i18n },
        startingPrice: { formattedPrice, frequency },
        bundle = {}
    },
    onSeePricingPlans
}) => {
    const [containerRef, containerWidth] = useContainerWidth();
    const isMobile = containerWidth && containerWidth < bSmall;
    const gridColumns = isMobile ? 2 : 3;

    const i18nWithDefaults = { ...ProductDescriptionComponent.defaultProps.data.overview.i18n, ...i18n };

    const settingsWithDefaults = { ...ProductDescriptionComponent.defaultProps.settings, ...settings };
    const [isPricesVisible, isAddonsVisible] = parseToBool(
        settingsWithDefaults.isPricesVisible,
        settingsWithDefaults.isAddonsVisible
    );

    const { textSize } = settingsWithDefaults;

    const renderPriceElements = price => {
        const { formattedFullPriceElements } = price;
        const [addonPrice, , unitFrequency] = formattedFullPriceElements;

        return (
            <div {...n('addonPriceWrapper').props} key={`price-${formattedFullPriceElements.join('-')}`}>
                {addonPrice && <span {...n('addonPrice').withTestId().props}>{addonPrice}</span>}
                <div {...n('addonPriceDetails').props}>
                    {unitFrequency && (
                        <span {...n('frequency').withTestId().props}>{`${stripSlash(unitFrequency)}`}</span>
                    )}
                </div>
            </div>
        );
    };

    const renderUsageRange = (usage, key) => {
        const { usageRange } = usage;
        if (!usageRange.length) {
            return null;
        }
        return <React.Fragment key={`usage-usageRange-${key}`}>{usageRange.map(renderPriceElements)}</React.Fragment>;
    };

    const renderPlan = (plans, key) => {
        const { costs } = plans;
        const { unitPrice, flatPrice = {} } = costs;

        return (
            <div {...n('addonPriceSection').props} key={`plans-unitPrice-${key}`}>
                {unitPrice.map(renderUsageRange)}
                {flatPrice.price ? renderPriceElements(flatPrice) : null}
            </div>
        );
    };

    const renderEdition = (edition, key) => {
        const [{ plans }] = edition;
        const [firstPlan] = plans;
        if (!plans) {
            return null;
        }
        return <React.Fragment key={`edition-${plans}-${key}`}>{renderPlan(firstPlan)}</React.Fragment>;
    };

    const renderAddon = addon => (
        <div {...n('addonItem').withTestId().props} key={`addon-${addon.name}`}>
            <div {...n('addonName').props}>{addon.name}</div>
            <span {...n('addonPriceItem').props}>
                <span {...n('addonFormattedPrice').props}>{renderEdition(addon.edition)}</span>
            </span>
        </div>
    );

    const renderBundle = item => {
        if (!item.card) {
            return null;
        }

        const { logoSrc: bundleLogo, logoSrcSet: bundleLogoSrcSet, title: bundleTitle } = item.card;

        return (
            <div {...n('bundleCard').withTestId().props} key={generateUniqueID([item.id, bundleTitle])}>
                <Image {...n('bundleLogo').props} src={bundleLogo} imageSrcSet={bundleLogoSrcSet} alt={bundleTitle} />
                <span {...n('bundleTitle').props}>{bundleTitle}</span>
            </div>
        );
    };

    return (
        <div {...n('wrapper').props} ref={containerRef}>
            {title && <h3 {...n('title').withTestId().withE2EId().props}>{title}</h3>}
            {description && (
                <p {...n('description', lowerFirst(textSize)).withTestId().withE2EId().props} dangerouslySetInnerHTML={{ __html: description }} />
            )}
            {isPricesVisible && formattedPrice && !hidePricings && (
                <div {...n('pricingWrapper').withTestId().props}>
                    <div {...n('pricing').props}>
                        <div {...n('startingFrom').withTestId().withE2EId().props}>{i18nWithDefaults.startingFrom}</div>
                        <span {...n('priceItem').props}>
                            <span {...n('priceValue').withTestId().withE2EId().props}>{formattedPrice}</span>
                            <span {...n('priceFrequency').withTestId().props}>{frequency.label}</span>
                        </span>
                    </div>
                    {pricingUrl && (
                        <div {...n('priceButton').withE2EId().props}>
                            <Button
                                type="primary"
                                onClick={() => onSeePricingPlans(pricingUrl)}
                                wide
                                {...n('').withTestId('seePricingPlans').props}
                            >
                                {i18nWithDefaults.seePricingPlans}
                            </Button>
                        </div>
                    )}
                </div>
            )}

            {bundle.items && bundle.items.length ? (
                <div {...n('bundleWrapper').props}>
                    <div {...n('subtitle').withTestId().props}>{i18nWithDefaults.availableBundles}</div>
                    <div {...n('bundleList').props}>
                        {bundle.items.map(item => renderBundle(item))}
                    </div>
                </div>
            ) : ''}

            {isAddonsVisible && addonProducts.length ? (
                <div {...n('availableAddons').props}>
                    <div {...n('subtitle').withTestId().props}>{i18nWithDefaults.availableAddons}</div>
                    <div {...n('addonWrapper').props}>
                        <Grid maxCol={gridColumns}>{addonProducts.slice(0, 3).map(renderAddon)}</Grid>
                    </div>
                </div>
            ) : null}
        </div>
    );
};

const TEXT_SIZE_OPTIONS = [MEDIUM, LARGE];

ProductDescriptionComponent.schema = () => ({
    name: 'ProductDescription',
    title: 'uieditor.sfbComponent.productDescription.title',
    iconName: 'text',
    orderableSection: [NAMESPACES.profile],
    form: {
        textSize: {
            title: 'uieditor.sfbComponent.productBundleViewer.textSize.title',
            type: DROPDOWN,
            defaultValue: TEXT_SIZE_OPTIONS[0].value,
            options: TEXT_SIZE_OPTIONS
        },
        isPricesVisible: {
            labelOn: 'uieditor.sfbComponent.productDescription.isPricesVisible.labelOn',
            labelOff: 'uieditor.sfbComponent.productDescription.isPricesVisible.labelOff',
            defaultValue: true,
            type: TOGGLE
        },
        isAddonsVisible: {
            labelOn: 'uieditor.sfbComponent.productDescription.isAddonsVisible.labelOn',
            labelOff: 'uieditor.sfbComponent.productDescription.isAddonsVisible.labelOff',
            defaultValue: true,
            type: TOGGLE
        }
    },
    marketplaceData: {
        overview: 'application.overview',
        startingPrice: 'application.startingPrice',
        hidePricings: 'application.config.hidePricings',
        addonProducts: 'application.addonProducts.items',
        i18n: 'application.reviews.i18n'
    }
});

export const bundleLogoShape = PropTypes.shape({
    id: PropTypes.number,
    card: PropTypes.shape({
        title: PropTypes.string,
        logoSrc: PropTypes.string,
        logoSrcset: PropTypes.shape({
            default: PropTypes.string
        })
    })
});

ProductDescriptionComponent.propTypes = {
    settings: PropTypes.shape({
        isPricesVisible: PropTypes.bool,
        isAddonsVisible: PropTypes.bool,
        textSize: PropTypes.oneOf(TEXT_SIZE_OPTIONS)
    }),
    data: PropTypes.shape({
        addonProducts: PropTypes.arrayOf(
            PropTypes.shape({
                name: PropTypes.string,
                edition: PropTypes.arrayOf(
                    PropTypes.shape({
                        plans: PropTypes.arrayOf(
                            PropTypes.shape({
                                costs: PropTypes.shape({
                                    unitPrice: PropTypes.arrayOf(
                                        PropTypes.shape({
                                            usageRange: PropTypes.arrayOf(
                                                PropTypes.shape({
                                                    formattedFullPriceElements: PropTypes.arrayOf(PropTypes.string)
                                                })
                                            )
                                        })
                                    )
                                })
                            })
                        )
                    })
                )
            })
        ),
        hidePricings: PropTypes.bool,
        overview: PropTypes.shape({
            title: PropTypes.string,
            description: PropTypes.string,
            pricingUrl: PropTypes.string,
            i18n: PropTypes.shape({
                startingFrom: PropTypes.string,
                seePricingPlans: PropTypes.string,
                availableAddons: PropTypes.string,
                availableBundles: PropTypes.string
            })
        }),
        startingPrice: PropTypes.shape({
            formattedPrice: PropTypes.string,
            frequency: PropTypes.shape({
                label: PropTypes.string
            })
        }),
        bundle: PropTypes.shape({
            items: PropTypes.arrayOf(bundleLogoShape)
        })
    }),
    onSeePricingPlans: PropTypes.func
};

const SETTINGS = ProductDescriptionComponent.schema().form;

ProductDescriptionComponent.defaultProps = {
    settings: {
        isPricesVisible: SETTINGS.isPricesVisible.defaultValue,
        isAddonsVisible: SETTINGS.isAddonsVisible.defaultValue,
        textSize: TEXT_SIZE_OPTIONS[0].value
    },
    data: {
        addonProducts: [],
        hidePricings: false,
        overview: {
            i18n: {
                startingFrom: 'Starting From',
                seePricingPlans: 'See Pricing Plans',
                availableAddons: 'Available Add-ons',
                availableBundles: 'Bundle Package Includes'
            }
        },
        startingPrice: {},
        bundle: {}
    },
    onSeePricingPlans: url => {
        window.location.assign(url);
    }
};

export default withListener(ProductDescriptionComponent);
