import ServiceLocator from '../../../ServiceLocator';
import { setConf } from '../../../configuration';
import {
    SET_SELECTED_AMOUNT,
    SET_SELECTED_CALCULATION,
    SAVE_BULKNAMES,
    SET_SELECTED_AMOUNTS,
    DELETE_SELECTED_AMOUNTS,
    setSelectedAmount,
    setSelectedCalculation,
    applyVariantAmountPreSelection,
    saveBulkNames,
    receiveConfiguration,
    CLEAR_BULKNAMES,
    clearBulkNames,
    setSelectedAmounts,
    deleteSelectedAmounts,
    setCalculationErrorsResolved,
    SET_CALCULATION_ERRORS_RESOLVED,
    setCalculationAutoResolveEnabled,
    SET_CALCULATION_AUTO_RESOLVE_ENABLED,
} from '../Actions';
import { addImagesFromDesignArea } from '../../ImageGallery/Actions';

describe('Reducers/Configurator/Actions', () => {
    // mock services
    class ConfiguratorService {
        static serviceName = 'ConfiguratorService';

        setSelectedAmount = jest.fn();
        setSelectedVariantIdentifier = jest.fn();
    }

    // add the mock services
    const configuratorService = new ConfiguratorService();

    ServiceLocator.provide(configuratorService);

    test('the setSelectedAmount function creates the correct action', () => {
        const identifier = 'test_identifier';
        const amount = 5;
        const isUpdatedByUser = false;
        expect(setSelectedAmount(identifier, amount)).toEqual({
            type: SET_SELECTED_AMOUNT,
            identifier,
            amount,
            isUpdatedByUser,
        });
    });

    test('the setSelectedCalculation function creates the correct action', () => {
        const identifier = 'test_identifier';
        const value = true;
        expect(setSelectedCalculation(identifier, value)).toEqual({
            type: SET_SELECTED_CALCULATION,
            identifier,
            value,
        });
    });

    test('applyVariantAmountPreSelection sets the correct amounts', () => {
        const mockConfigurator = {
            configuration: {
                item: {
                    itemGroup: {
                        children: [{ identifier: 'hoodie' }, { identifier: 'hoodie2' }],
                    },
                },
            },
        };

        const mockPreSelection = {
            itemAmounts: {
                hoodie: 3,
                hoodie2: 5,
            },
        };

        setConf('designerPreSelection', mockPreSelection);

        applyVariantAmountPreSelection(mockConfigurator);

        expect(configuratorService.setSelectedAmount).toBeCalledWith('hoodie', 3);
        expect(configuratorService.setSelectedAmount).toBeCalledWith('hoodie2', 5);
    });

    describe('receiveConfiguration', () => {
        const configurator = {
            configuration: {
                item: {},
                customdata: { selectedAmounts: {} },
            },
            selectedoptionclassification: {},
        };
        const configurationMode = {
            selectedMode: 'designer',
            availableModes: {
                designer: true,
            },
        };

        test('dispatches `addImagesFromDesignArea` if `configurator.loadCode` is there', () => {
            const dispatch = jest.fn();
            const getState = () => ({
                configurator: {
                    ...configurator,
                    loadCode: 'QWERTZ',
                },
                configurationMode,
            });
            const expectedAction = addImagesFromDesignArea({});

            receiveConfiguration({}, {})(dispatch, getState);

            expect(dispatch).toHaveBeenCalledWith(expectedAction);
        });

        test("doesn't dispatch `addImagesFromDesignArea` if `configurator.loadCode` is not there", () => {
            const dispatch = jest.fn();
            const getState = () => ({
                configurator: { ...configurator, loadCode: null },
                configurationMode,
            });
            const expectedAction = addImagesFromDesignArea({});

            receiveConfiguration({}, {})(dispatch, getState);

            expect(dispatch).not.toHaveBeenCalledWith(expectedAction);
        });
        test('clearBulkNames function calls the correct action', () => {
            expect(clearBulkNames()).toEqual({
                type: CLEAR_BULKNAMES,
            });
        });
    });
    test('saveBulkNames function creates the correct action', () => {
        const identifier = 'hoodie_blue_s';
        const bulkNamesData = ['Alex', 'Leon', 'Lea'];
        expect(saveBulkNames(identifier, bulkNamesData)).toEqual({
            type: SAVE_BULKNAMES,
            identifier,
            bulkNamesData,
        });
    });

    test('the setSelectedAmounts function creates the correct action', () => {
        const variant = {
            identifier: 'hoodie_blue_s',
            title: 'blau',
            url: 'http://localhost:10030/images/item/thumb/hoodie_blue_s.jpg',
            sizes: [
                {
                    identifier: 'hoodie_blue_s',
                    amount: 1,
                    size: 'Größe S',
                    key: 'hoodie_blue_s',
                    label: 'Größe S',
                    url: 'http://localhost:10030/images/item/thumb/hoodie_blue_s.jpg',
                },
                {
                    identifier: 'hoodie_green_m',
                    amount: 0,
                    size: 'Größe M',
                    key: 'hoodie_green_m',
                    label: 'Größe M',
                    url: 'http://localhost:10030/images/item/thumb/hoodie_green_m.jpg',
                },
            ],
        };
        const sizes = { hoodie_green_m: 5, hoodie_blue_s: 2 };
        expect(setSelectedAmounts(variant, sizes)).toEqual({
            type: SET_SELECTED_AMOUNTS,
            variant,
            sizes,
        });
    });

    test('the deleteSelectedAmounts function creates the correct action', () => {
        const variant = {
            identifier: 'hoodie_blue_s',
            title: 'blau',
            url: 'http://localhost:10030/images/item/thumb/hoodie_blue_s.jpg',
            sizes: [
                {
                    identifier: 'hoodie_blue_s',
                    amount: 1,
                    size: 'Größe S',
                    key: 'hoodie_blue_s',
                    label: 'Größe S',
                    url: 'http://localhost:10030/images/item/thumb/hoodie_blue_s.jpg',
                },
                {
                    identifier: 'hoodie_green_m',
                    amount: 1,
                    size: 'Größe M',
                    key: 'hoodie_green_m',
                    label: 'Größe M',
                    url: 'http://localhost:10030/images/item/thumb/hoodie_green_m.jpg',
                },
            ],
        };
        const sizes = { hoodie_green_m: 5, hoodie_blue_s: 2 };
        expect(deleteSelectedAmounts(variant, sizes)).toEqual({
            type: DELETE_SELECTED_AMOUNTS,
            variant,
            sizes,
        });
    });

    test('the setCalculationErrorsResolved function creates the correct action', () => {
        expect(setCalculationErrorsResolved()).toEqual({
            type: SET_CALCULATION_ERRORS_RESOLVED,
        });
    });

    test('the setCalculationAutoResolveEnabled function creates the correct action, sets the correct enabled value', () => {
        expect(setCalculationAutoResolveEnabled('skipNext')).toEqual({
            type: SET_CALCULATION_AUTO_RESOLVE_ENABLED,
            enabled: 'skipNext',
        });
    });
    test('the setCalculationAutoResolveEnabled function creates the correct action, sets the correct enabled value', () => {
        expect(setCalculationAutoResolveEnabled(true)).toEqual({
            type: SET_CALCULATION_AUTO_RESOLVE_ENABLED,
            enabled: true,
        });
    });
});
