import React, { useMemo } from 'react';
import PropTypes from 'prop-types';
import withListener from '../withListener';
import { useResponsive } from '../../tools/widths/useResponsive';
import { createNamespace } from '../../tools/namingTools';
import { parseToBool } from '../../tools/helpers';
import { unescapeHtml } from '../../tools/stringTools';
import { summaryPropTypes } from '../../constants/prop-types/application/summary';
import { relatedContentPropTypes } from '../../constants/prop-types/application/related-content';
import { editionPropTypes } from '../../constants/prop-types/application/editions';
import { COLORPICKER, DROPDOWN, IMAGE_UPLOADER, RADIO, GROUP_HEADER, TOGGLE } from '../../constants/schemaComponentTypes';
import { BACKGROUND_COLOR, BACKGROUND_IMAGE } from '../../constants/backgroundSettings';
import { SMALL, MEDIUM, LARGE } from '../../constants/sizes';
import { parsePricingActions } from '../../tools/callToActions';
import { LIGHT, DARK } from '../../constants/themeColor';
import { CTA_NO_ACTION } from '../../constants/actions';

import ProductCard from '../../atoms/product-card/ProductCard';
import ButtonsList, { callToActionsShape } from '../../atoms/buttons-list/ButtonsList';
import BreadCrumbs from '../../atoms/bread-crumbs/BreadCrumbs';

import { marketplaceProductDataStore } from '../../store/marketplaceProductData';

import './styles/ProductBanner.scss';

const n = createNamespace('ProductBanner');

const AVAILABLE_TYPES = [BACKGROUND_IMAGE.value];

export const ProductBannerComponent = ({
    settings,
    data: {
        applicationType,
        callToActions = { items: [] },
        categories,
        config,
        i18n: i18nProp,
        listingPageUrl,
        relatedContent,
        summary,
        defaultSelectedEdition
    }
}) => {
    const { marketplaceProductData } = marketplaceProductDataStore();

    const hasRequiredProduct = Boolean(
        Array.isArray(marketplaceProductData?.product?.editions)
        && marketplaceProductData.product.editions.some(element => (element.upstreamAssociations?.length))
    );

    // build the crumb's back button link. If we come from a listing page, clicking back will go history -1.
    // Otherwise (for example if we come from an external site) the crumb's root will be a link to the listings page
    const breadcrumbRoot = useMemo(() => {
        const i18n = { ...ProductBannerComponent.defaultProps.data.i18n, ...i18nProp };
        if (!listingPageUrl) {
            return {};
        }

        const { referrer } = document;
        const i18nWithDefaults = { ...ProductBannerComponent.defaultProps.data.i18n, ...i18n };

        // we come from a listings page
        if (referrer.indexOf(listingPageUrl) !== -1) {
            return {
                baseLinkText: i18nWithDefaults.backToResults,
                baseLinkAction: () => window.history.go(-1)
            };
        }

        return {
            baseLinkText: i18nWithDefaults.allProducts,
            baseLinkUrl: listingPageUrl
        };
    }, [listingPageUrl, i18nProp]);

    const { largeDown: isMobile } = useResponsive();

    if (!summary) {
        return null;
    }

    const cardSummary = {
        ...summary,
        hasRequiredProduct
    };

    const settingsWithDefaults = { ...ProductBannerComponent.defaultProps.settings, ...settings };
    const {
        backgroundType,
        bannerBackgroundColor,
        backgroundImg,
        settingsHeight,
        productNameSize,
        descTextSize,
        textColor
    } = settingsWithDefaults;
    const [showRatings] = parseToBool(settings.showRatings);
    const pricingActions = parsePricingActions(callToActions);

    const textSettings = {
        showRatings,
        settingsHeight,
        productNameSize,
        descTextSize,
        textColor
    };

    const hasButtons = Boolean(
        pricingActions?.items?.[0]?.actionType !== CTA_NO_ACTION
    );

    const containerModifiers = [
        textColor && textColor.toLowerCase()
    ];

    const wrapperModifiers = [
        settingsHeight && settingsHeight.toLowerCase()
    ];

    const buildBackgroundStyle = () => {
        const imageOrColor = AVAILABLE_TYPES.includes(backgroundType)
            ? { backgroundImage: `url(${unescapeHtml(backgroundImg.url)})` }
            : { backgroundColor: bannerBackgroundColor };

        return Object.assign(
            {},
            imageOrColor
        );
    };

    const breadcrumb = [];

    if (categories && categories.items && categories.items.length) {
        breadcrumb.push({
            ...categories,
            label: categories.label || ProductBannerComponent.defaultProps.data.categories.label
        });
    }

    const breadCrumbsProps = {
        ...breadcrumbRoot,
        crumbs: breadcrumb
    };

    const i18nSummaryWithDefaults = { ...ProductBannerComponent.defaultProps.data.summary.i18n, ...summary.i18n };

    return (
        <div {...n('container', containerModifiers).withTestId().withE2EId().props}>
            <div
                {...n('backgroundWrapper').withTestId().props}
                style={buildBackgroundStyle()}
            />
            <div {...n('breadCrumbs').props}>
                <BreadCrumbs {...breadCrumbsProps} />
            </div>
            <section {...n('wrapper', wrapperModifiers).withTestId().props}>
                <h1 {...n('title', 'hidden').props}>{i18nSummaryWithDefaults.title}</h1>
                <div {...n('row').props}>
                    <div {...n('card').props}>
                        <ProductCard
                            cardData={cardSummary}
                            reviewData={relatedContent}
                            settings={textSettings}
                        />
                    </div>
                    {hasButtons && !isMobile && (
                        <div {...n('buttons').props}>
                            <ButtonsList data={{
                                applicationType,
                                callToActions: pricingActions,
                                primaryButtonType: 'emphasis',
                                referUrl: config && config.referUrl,
                                defaultSelectedEdition
                            }}
                            />
                        </div>
                    )}
                </div>
            </section>
        </div>
    );
};

const BACKGROUND_TYPE_OPTIONS = [BACKGROUND_IMAGE, BACKGROUND_COLOR];
const SIZE_OPTIONS = [SMALL, MEDIUM, LARGE];
const TEXT_COLOR_OPTIONS = [LIGHT, DARK];

ProductBannerComponent.schema = () => ({
    name: 'ProductBanner',
    title: 'uieditor.sfbComponent.productBanner.title',
    iconName: 'banner',
    form: {
        spacer: {
            type: GROUP_HEADER,
            title: 'uieditor.sfbComponent.productBanner.spacer.title',
            symbol: 'style'
        },
        backgroundType: {
            title: 'uieditor.sfbComponent.productBanner.backgroundType.title',
            type: RADIO,
            required: false,
            defaultValue: BACKGROUND_TYPE_OPTIONS[1].value,
            options: BACKGROUND_TYPE_OPTIONS
        },
        backgroundImg: {
            title: 'uieditor.sfbComponent.productBanner.backgroundImg.title',
            caption: 'uieditor.sfbComponent.productBanner.backgroundImg.caption',
            placeholder: 'uieditor.sfbComponent.productBanner.backgroundImg.placeholder',
            defaultValue: {
                filename: '',
                type: 'IMAGE_UPLOADER',
                url: ''
            },
            type: IMAGE_UPLOADER,
            required: false,
            conditionalAttributes: {
                isDisabled: {
                    when: 'backgroundType',
                    connector: 'equals',
                    value: BACKGROUND_COLOR.value
                }
            }
        },
        bannerBackgroundColor: {
            title: 'uieditor.sfbComponent.productBanner.bannerBackgroundColor.title',
            defaultValue: '#ffffff',
            type: COLORPICKER,
            conditionalAttributes: {
                isDisabled: {
                    when: 'backgroundType',
                    connector: 'equals',
                    value: BACKGROUND_IMAGE.value
                }
            }
        },
        textColor: {
            title: 'uieditor.sfbComponent.productBanner.textColor.title',
            type: DROPDOWN,
            required: true,
            defaultValue: TEXT_COLOR_OPTIONS[1].value,
            options: TEXT_COLOR_OPTIONS
        },
        spacer3: {
            type: GROUP_HEADER,
            title: 'uieditor.sfbComponent.productBanner.spacer3.title',
            symbol: 'settings'
        },
        settingsHeight: {
            title: 'uieditor.sfbComponent.productBanner.settingsHeight.title',
            type: DROPDOWN,
            required: true,
            defaultValue: SIZE_OPTIONS[1].value,
            options: SIZE_OPTIONS
        },
        showRatings: {
            labelOn: 'uieditor.sfbComponent.productBanner.showRatings.labelOn',
            labelOff: 'uieditor.sfbComponent.productBanner.showRatings.labelOff',
            defaultValue: true,
            type: TOGGLE
        },
        productNameSize: {
            title: 'uieditor.sfbComponent.productBanner.productNameSize.title',
            type: DROPDOWN,
            required: true,
            defaultValue: SIZE_OPTIONS[1].value,
            options: SIZE_OPTIONS
        },
        descTextSize: {
            title: 'uieditor.sfbComponent.productBanner.descTextSize.title',
            type: DROPDOWN,
            required: true,
            defaultValue: SIZE_OPTIONS[1].value,
            options: SIZE_OPTIONS
        }
    },
    marketplaceData: {
        applicationType: 'application.config.type',
        callToActions: 'application.callToActions',
        categories: 'application.categories',
        config: 'application.config',
        configurator: 'application.configurator',
        i18n: 'i18n',
        listingPageUrl: 'config.listingEndpoint',
        relatedContent: 'application.relatedContent',
        summary: 'application.summary',
        defaultSelectedEdition: 'application.defaultSelectedEdition'
    }
});

ProductBannerComponent.propTypes = {
    settings: PropTypes.shape({
        backgroundType: PropTypes.oneOfType([
            PropTypes.string,
            PropTypes.object
        ]),
        bannerBackgroundColor: PropTypes.string,
        textColor: PropTypes.oneOf(TEXT_COLOR_OPTIONS.map(({ value }) => value)),
        backgroundImg: PropTypes.shape({
            filename: PropTypes.string,
            type: PropTypes.oneOf([IMAGE_UPLOADER]),
            url: PropTypes.string
        }),
        showRatings: PropTypes.bool,
        settingsHeight: PropTypes.string,
        productNameSize: PropTypes.oneOf(SIZE_OPTIONS.map(({ value }) => value)),
        descTextSize: PropTypes.oneOf(SIZE_OPTIONS.map(({ value }) => value))
    }),
    data: PropTypes.shape({
        summary: PropTypes.shape(summaryPropTypes),
        categories: PropTypes.shape({
            label: PropTypes.string,
            items: PropTypes.arrayOf(
                PropTypes.shape({
                    label: PropTypes.string,
                    href: PropTypes.string
                })
            )
        }),
        applicationType: PropTypes.string,
        listingPageUrl: PropTypes.string,
        callToActions: PropTypes.shape(callToActionsShape),
        config: PropTypes.object,
        configurator: PropTypes.shape({
            url: PropTypes.string
        }),
        relatedContent: PropTypes.shape(relatedContentPropTypes),
        i18n: PropTypes.shape({
            backToResults: PropTypes.string,
            allProducts: PropTypes.string
        }),
        defaultSelectedEdition: PropTypes.shape(editionPropTypes)
    })
};

const SETTINGS = ProductBannerComponent.schema().form;

ProductBannerComponent.defaultProps = {
    settings: {
        backgroundType: SETTINGS.backgroundType.defaultValue,
        bannerBackgroundColor: SETTINGS.bannerBackgroundColor.defaultValue,
        textColor: SETTINGS.textColor.defaultValue,
        backgroundImg: SETTINGS.backgroundImg.defaultValue,
        showRatings: SETTINGS.showRatings.defaultValue,
        settingsHeight: SETTINGS.settingsHeight.defaultValue,
        productNameSize: SETTINGS.productNameSize.defaultValue,
        descTextSize: SETTINGS.descTextSize.defaultValue
    },
    data: {
        summary: {
            i18n: {
                title: 'Summary'
            }
        },
        categories: {
            label: 'Categories',
            items: null
        },
        config: {},
        configurator: {
            url: ''
        },
        callToActions: null,
        relatedContent: {
            details: {
                reviews: {
                    rating: 0,
                    numRatings: 0,
                    caption: '',
                    title: ''
                },
                vendor: {
                    title: '',
                    items: [
                        {
                            label: ''
                        }
                    ]
                }
            }
        },
        applicationType: '',
        i18n: {
            backToResults: 'Back to Results',
            allProducts: 'All Products'
        },
        defaultSelectedEdition: null
    }
};

export default withListener(ProductBannerComponent);
