import get from 'lodash/get';
import isArray from 'lodash/isArray';
import isPlainObject from 'lodash/isPlainObject';
import upperFirst from 'lodash/upperFirst';
import uniqBy from 'lodash/uniqBy';
import { containerConnect } from 'Framework/ComponentContainer';
import { t } from 'Framework/i18n';
import { Services } from 'App/ServiceLocator';
import createSelector from 'Utils/Function/createSelector';
import {
    findMaxChildrenCount,
    getSelectedAmounts,
    getItem,
    getCalculation,
    getUserSelectedCalculation,
    getClient,
    getBulkNames,
    getClientTexts,
    showCallToAction,
    showReceiveOfferForm,
    getConfiguration,
} from '../../../Reducers/Configurator/Selectors';
import { getVisibilityMapProperty } from '../../../Reducers/UI/Selectors';
import { getConf } from '../../../configuration';
import { isBulkNamesSelected } from '../../../Reducers/DesignArea/Selectors';
import AmountPrice from '../../Components/AmountPrice';
import { AmountPriceAdminareaWrapper } from './AmountPriceAdminareaWrapper';
import {
    getAvailableConfigurationModes,
    isCreatorModeSelected,
} from '../../../Reducers/ConfigurationMode/Selectors';

export const showProductVariantsForItem = createSelector(getItem, item => findMaxChildrenCount(item) > 1);

export const createAmountPropsFromState = createSelector(
    getItem,
    getSelectedAmounts,
    getClient,
    getBulkNames,
    (item, selectedAmounts, client) => {
        const query = new URLSearchParams(location.search);
        const props = {
            title: item && item.title,
            amount: 0,
            hidePrices: query.has('_hide_prices')
                ? query.get('_hide_prices') === '1'
                : client && !!client.hidePrices,
        };
        if (isPlainObject(selectedAmounts)) {
            props.amount = Object.values(selectedAmounts).reduce((sum, amount) => sum + amount, 0);
        }
        return props;
    }
);

export const createBulkNameErrors = createSelector(
    getItem,
    getSelectedAmounts,
    getBulkNames,
    (item, selectedAmounts, bulkNames) => {
        let bulkNameErrors = [];
        const children = get(item, 'itemGroup.children', []);
        for (const childItem of children) {
            if (childItem.itemGroup && childItem.itemGroup.identifier === 'size') {
                for (const sizeChildItem of childItem.itemGroup.children) {
                    const selectedAmount = get(selectedAmounts, sizeChildItem.identifier, 0);
                    const childBulkNames = get(bulkNames, sizeChildItem.identifier, []);
                    if (selectedAmount > 0 && childBulkNames.length !== selectedAmount) {
                        bulkNameErrors.push(
                            t('receiveOfferForm.checkBulkNamesInputs', {
                                item:
                                    item.title +
                                    ' / ' +
                                    upperFirst(childItem.itemgroupentryTitle) +
                                    ' / ' +
                                    sizeChildItem.itemgroupentryTitle,
                            })
                        );
                    }
                }
            } else {
                const selectedAmount = get(selectedAmounts, childItem.identifier, 0);
                const childBulkNames = get(bulkNames, childItem.identifier, []);
                if (selectedAmount > 0 && childBulkNames.length !== selectedAmount) {
                    bulkNameErrors.push(
                        t('receiveOfferForm.checkBulkNamesInputs', {
                            item: item.title + ' / ' + upperFirst(childItem.itemgroupentryTitle),
                        })
                    );
                }
            }
        }
        return bulkNameErrors;
    }
);

export const createPricePropsFromState = createSelector(
    getCalculation,
    getUserSelectedCalculation,
    (calculation, userSelectedCalculation) => {
        const displayNetPrices = getConf('displayNetPrices', false);
        const props = {
            priceList: [],
            priceFormatted: displayNetPrices
                ? get(calculation, 'netTotalFormatted', '')
                : get(calculation, 'totalFormatted', ''),
            error: null,
            bulkSavings: [],
            notifications: [],
        };
        const positions = get(calculation, 'positions');
        if (isArray(positions)) {
            props.priceList = positions.map(p => ({
                key: p.calculationTypeIdentifier,
                selectable: p.selectableByUser,
                selected: get(userSelectedCalculation, p.calculationTypeIdentifier, false),
                label: p.title || t(`calculationTypes.${p.calculationTypeIdentifier}`),
                price: displayNetPrices ? p.priceNetFormatted : p.priceFormatted,
            }));
        }
        const bulkSavings = get(calculation, 'bulkSavings');
        if (isArray(bulkSavings)) {
            props.bulkSavings = bulkSavings.map(b => ({
                key: b.itemIdentifier,
                itemTitle: b.itemTitle,
                savingsBulkAmount: b.savingsBulkAmount,
                savingAmount: b.savingAmount,
            }));
        }
        if (calculation && calculation.success === false) {
            props.error = {
                code: calculation.code,
                errors: calculation.errors,
            };
        }
        if (props.error && props.error.errors.length) {
            const uniqErrors = uniqBy(props.error.errors, 'itemIdentifier');
            for (const fieldError of uniqErrors) {
                props.notifications.push({
                    message: t('amountPrice.minimumAmountError', {
                        minimumAmount: fieldError.minimumAmount,
                        itemTitle: fieldError.itemTitle,
                        selectedAmount: fieldError.selectedAmount,
                    }),
                    level: 'error',
                    color: 'error',
                });
            }
        }

        props.bulkSavings.length > 0 &&
            props.bulkSavings.map(bulkSaving => {
                props.notifications.push({
                    message: t('amountPrice.bulkSavings', {
                        itemTitle: bulkSaving.itemTitle,
                        savingsBulkAmount: bulkSaving.savingsBulkAmount,
                        savingAmount: bulkSaving.savingAmount,
                    }),
                    level: 'info',
                    color: 'default',
                });
            });

        return props;
    }
);

const mapStateToProps = ({ configurator, configurationMode, ui }) => {
    let priceProps = createPricePropsFromState(configurator);
    const { designer: designerAvailable } = getAvailableConfigurationModes({ configurationMode });
    if (!designerAvailable) {
        // remove user selectable designer global calculation post from priceList for only creator Product
        priceProps = {
            ...priceProps,
            priceList: priceProps.priceList.filter(
                listItem => !listItem.key.startsWith('global') && listItem.selectableByUser === true
            ),
        };
    }
    const query = new URLSearchParams(location.search);
    return {
        Component: AmountPriceAdminareaWrapper,
        AmountPriceComponent: AmountPrice,
        vatNotice: !getConf('displayNetPrices', false)
            ? t('amountPrice.vatNotice')
            : t('amountPrice.vatNoticeNet'),
        boxed: true,
        showProductVariants: true,
        showReceiveOfferForm: query.has('_cta_element')
            ? query.get('_cta_element') === 'requestOffer'
            : showReceiveOfferForm(configurator),
        showCallToAction: query.has('_cta_element')
            ? query.get('_cta_element') !== 'none'
            : showCallToAction(configurator),
        skipPriceOverview: query.has('_skipcartoverlay'),
        displayAcceptDesign: !designerAvailable ? false : getConf('displayAcceptDesign', true),
        isBulkNamesSelected: isBulkNamesSelected(configurator),
        bulkNameErrors: isBulkNamesSelected(configurator) ? createBulkNameErrors(configurator) : null,
        ...createAmountPropsFromState(configurator),
        ...priceProps,
        clientTexts: getClientTexts(configurator),
        addToCartPopUpLoader: getVisibilityMapProperty(ui, 'addToCartPopUpLoader'),
        userComment: get(configurator, 'configuration.customdata.comment', ''),
        userConfiguration: getConfiguration(configurator),
        isCreator: isCreatorModeSelected({ configurationMode }),
    };
};

const mapDispatchToProps = () => ({
    onSelectableChanged: (identifier, value) =>
        Services.configurator.setSelectedCalculation(identifier, value),
    onClose: () => {
        Services.visualization.abortScreenshotting();
    },
    onChangeAmount: amount => Services.configurator.setSelectedAmount(false, amount),
    sendReceiveOfferRequest: data => Services.interaction.sendReceiveOfferRequest(data),
    setConfigurationComment: notice => Services.configurator.setConfigurationComment(notice),
    onAddToBasket: () => Services.interaction.addToCart(),
    onShowChange: on => Services.configurator.setCalculationAutoResolveEnabled(!on),
    validateConfiguration: () =>
        getConf('validateBeforeCTA') && Services.configurator.validateConfiguration(),
    toggleGlobalLoader: on => Services.ui.toggle('globalLoader', on),
});

export default containerConnect(mapStateToProps, mapDispatchToProps);
