import React, { useRef } from 'react';
import PropTypes from 'prop-types';
import { generateUniqueID } from '../../../../tools/helpers';
import { addonShape } from '../../../../constants/components/prop-types/addon';
import { RenderInclusions, RenderPrice, RenderAudience, RenderDiscount } from '../../../product-edition/card/ProductEditionCard';
import Button from '../../../button/Button';
import Badge from '../../../badge/Badge';
import Icon from '../../../icon/Icon';
import { createNamespace } from '../../../../tools/namingTools';
import { useCarouselA11yVisible } from '../../../../tools/a11y/useCarouselA11yVisible';

const n = createNamespace('ProductAddonList');

const pickPriceElements = ({ unit, price, formattedFullPriceElements }) => ({
    unit,
    discount: {
        discountOff: price.formatted.discountOff
    },
    price: {
        original: price.formatted.originalFullPriceElements,
        formatted: formattedFullPriceElements
    }
});

const reducePrices = (flatPrice, unitPrice) => {
    const prices = [];

    // if there is a flat price, that needs to be shown first
    if (flatPrice.price) {
        prices.push(pickPriceElements(flatPrice));
    }

    // if there are unit prices, they need to be added
    if (unitPrice) {
        unitPrice.forEach(price => {
            price.usageRange.forEach(usageRange => {
                prices.push(pickPriceElements(usageRange));
            });
        });
    }

    return prices;
};

const renderPlan = (plans, key) => {
    const { costs, setupFees, contractFees, formattedContract, uuid } = plans;
    const { unitPrice, flatPrice = {} } = costs;

    // unify the prices into one array
    const prices = reducePrices(flatPrice, unitPrice);

    // split off the first element
    const [mainPrice, ...otherPrices] = prices;
    const shouldRenderPrices = !!otherPrices.length || !!setupFees.length || !!contractFees.length;

    return (
        <div {...n('addonPriceSection').props} key={`plans-${unitPrice}-${key}`}>
            {mainPrice && (
                <div {...n('mainPrice').withTestId().props}>
                    <RenderPrice unit={mainPrice.unit} formattedPrice={mainPrice.price.formatted} />
                    {formattedContract && <Badge label={formattedContract} {...n('contract').props} />}
                </div>
            )}
            {shouldRenderPrices && (
                <div {...n('additionalPrice').props}>
                    {otherPrices && !!otherPrices.length && otherPrices.map(otherPrice => (
                        <div {...n('otherPrice').withTestId().props}>
                            <RenderPrice
                                unit={otherPrice.unit}
                                formattedPrice={otherPrice.price.formatted}
                                key={generateUniqueID([...otherPrice.price.formatted, uuid])}
                                isSecondary
                                discount={(
                                    <RenderDiscount
                                        discountOff={otherPrice.discount.discountOff}
                                        original={otherPrice.price.original}
                                        isUnitPrice
                                    />
                                )}
                            />
                        </div>
                    ))}
                    {setupFees && !!setupFees.length && setupFees.map(setupFee => (
                        <div {...n('setupFees').withTestId().props}>
                            <RenderPrice
                                formattedPrice={setupFee.formattedFullPriceElements}
                                key={generateUniqueID([...setupFee.formattedFullPriceElements, uuid])}
                                isSecondary
                                textSeparator={' '}
                                discount={(
                                    <RenderDiscount
                                        discountOff={setupFee.price.formatted.discountOff}
                                        original={setupFee.price.formatted.originalFullPriceElements}
                                        isUnitPrice
                                    />
                                )}
                            />
                        </div>
                    ))}
                    {contractFees && !!contractFees.length && contractFees.map(contractFee => (
                        <div {...n('contractFees').withTestId().props}>
                            <RenderPrice
                                formattedPrice={contractFee.formattedFullPriceElements}
                                key={generateUniqueID([...contractFee.formattedFullPriceElements, uuid])}
                                isSecondary
                                textSeparator={' '}
                                discount={(
                                    <RenderDiscount
                                        discountOff={contractFee.price.formatted.discountOff}
                                        original={contractFee.price.formatted.originalFullPriceElements}
                                        isUnitPrice
                                    />
                                )}
                            />
                        </div>
                    ))}
                </div>
            )}
        </div>
    );
};


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


const Addon = React.forwardRef((
    {
        addon,
        height,
        selectable,
        onAddonSelect,
        onAddonRemove,
        i18n,
        isSelected,
        carouselEnabled
    },
    titleRef
) => {
    const containerRef = useRef();
    const [isCarouselA11yVisible] = useCarouselA11yVisible(containerRef);
    const isA11yVisible = isCarouselA11yVisible || !carouselEnabled;
    const renderButton = (currentAddon = {}) => {
        const buttonProps = Object.assign({
            'data-testid': `button:select:addon-${currentAddon.id}`,
            type: isSelected ? 'emphasis-outline' : 'primary',
            wide: true,
            tabIndex: isA11yVisible ? 0 : -1
        },
        isSelected && {
            selected: true
        },
        !isSelected && {
            onClick: () => onAddonSelect(currentAddon)
        });
        return (
            <div {...n('actionsWrapper').props}>
                <div {...n('buttonWrapper').withTestId('actions-container').props}>
                    <Button {...buttonProps}>
                        {isSelected ? i18n.added : i18n.addToOrder}
                        {isSelected && <Icon type="check" {...n('selectedCheck').props} />}
                    </Button>
                </div>
                {isSelected && (
                    <div {...n('actionLink').withTestId().props}>
                        <Button
                            buttonType="link"
                            type="primary"
                            {...n('actionLinkLabel').props}
                            data-testid={`button:remove:addon-${currentAddon.id}`}
                            onClick={() => onAddonRemove(currentAddon)}
                            onKeyDown={() => onAddonRemove(currentAddon)}
                            tabIndex={isA11yVisible ? 0 : -1}
                        >
                            {i18n.remove}
                        </Button>
                    </div>
                )}
            </div>
        );
    };

    const { edition, name } = addon;
    const {
        bullets, audience
    } = edition[0];
    const inclusions = addon.edition[0].items; // Can't deconstruct object, "items" is already declared
    // height of title comes from hook, as all title within the same row must be as high as the highest one
    const addonVariables = { 'addon-name-height': height ? `${height}px` : null };

    return (
        <div {...n('container').withVariables(addonVariables).withTestId().props} ref={containerRef}>
            <div {...n('main', selectable && 'with-buttons').props}>
                <div {...n('text').props}>
                    {name && <h2 {...n('name').withTestId().props} ref={titleRef}>{name}</h2>}
                    <div {...n('edition').withTestId().props}>{edition.map(renderEdition)}</div>
                    <RenderAudience audience={audience} i18n={i18n} />
                    {inclusions && <RenderInclusions items={inclusions} i18n={i18n} />}
                    <p {...n('description').withTestId().props}>
                        {bullets[0] && bullets[0].content}
                    </p>
                </div>
                {selectable ? renderButton(addon) : null}
            </div>
        </div>
    );
});

Addon.propTypes = {
    addon: addonShape,
    height: PropTypes.number,
    i18n: PropTypes.object,
    selectable: PropTypes.bool,
    isSelected: PropTypes.bool,
    carouselEnabled: PropTypes.bool,
    onAddonSelect: PropTypes.func,
    onAddonRemove: PropTypes.func
};
Addon.defaultProps = {
    addon: {},
    i18n: {},
    height: 0,
    selectable: false,
    isSelected: false,
    carouselEnabled: false,
    onAddonSelect: null,
    onAddonRemove: null
};

export default Addon;
