import get from 'lodash/get';
import omit from 'lodash/omit';
import configuratorReducer from '../Reducer';
import {
    SET_SELECTED_AMOUNT,
    SET_SELECTED_CALCULATION,
    CLEAR_BULKNAMES,
    SAVE_BULKNAMES,
    SET_SELECTED_AMOUNTS,
    DELETE_SELECTED_AMOUNTS,
    skipNextAutoResolve,
    RECEIVE_CALCULATION,
    setCalculationAutoResolveEnabled,
    SWITCH_SELECTED_AMOUNT,
} from '../Actions';

describe('Reducers/Configurator/Reducer', () => {
    let initialState;
    let stateWithSelectedAmount;
    let stateWithSelectedAmounts;
    let stateWithSelectedCalculation;

    beforeAll(() => {
        initialState = configuratorReducer();
    });

    test('returns the correct state for SET_SELECTED_AMOUNT action', () => {
        stateWithSelectedAmount = configuratorReducer(initialState, {
            type: SET_SELECTED_AMOUNT,
            identifier: 'test_identifier',
            amount: 3,
        });
        expect(get(stateWithSelectedAmount, 'configuration.customdata.selectedAmounts')).toEqual({
            test_identifier: 3,
        });
    });
    test('returns the correct state for SET_SELECTED_AMOUNT action if amount is set to 0', () => {
        stateWithSelectedAmount = configuratorReducer(stateWithSelectedAmount, {
            type: SET_SELECTED_AMOUNT,
            identifier: 'test_identifier',
            amount: 0,
        });
        expect(get(stateWithSelectedAmount, 'configuration.customdata.selectedAmounts')).toEqual({});
    });
    test('the SET_SELECTED_AMOUNT action does not touch anything else in the state', () => {
        // initially there is no customdata property, check the other parts
        expect(omit(stateWithSelectedAmount, 'configuration.customdata')).toEqual(initialState);
    });
    test('returns the correct state for SET_SELECTED_AMOUNT action if isUpdatedByUser is true', () => {
        const state = configuratorReducer(stateWithSelectedAmount, {
            type: SET_SELECTED_AMOUNT,
            identifier: 'test_identifier',
            amount: 1,
            isUpdatedByUser: true,
        });
        expect(get(state, 'selectedAmountsUpdated')).toEqual(true);
    });
    test('returns the correct state for SET_SELECTED_AMOUNT action if isUpdatedByUser is false', () => {
        const state = configuratorReducer(stateWithSelectedAmount, {
            type: SET_SELECTED_AMOUNT,
            identifier: 'test_identifier',
            amount: 1,
            isUpdatedByUser: false,
        });
        expect(get(state, 'selectedAmountsUpdated')).toEqual(false);
    });
    test('returns the correct state for SET_SELECTED_CALCULATION action', () => {
        stateWithSelectedCalculation = configuratorReducer(initialState, {
            type: SET_SELECTED_CALCULATION,
            identifier: 'test_identifier',
            value: true,
        });
        expect(get(stateWithSelectedCalculation, 'configuration.customdata.userSelectedCalculation')).toEqual(
            {
                test_identifier: true,
            }
        );
    });
    test('returns the correct state for SET_SELECTED_CALCULATION action when the value is false', () => {
        stateWithSelectedCalculation = configuratorReducer(initialState, {
            type: SET_SELECTED_CALCULATION,
            identifier: 'test_identifier',
            value: false,
        });
        expect(get(stateWithSelectedCalculation, 'configuration.customdata.userSelectedCalculation')).toEqual(
            {
                test_identifier: false,
            }
        );
    });
    test('the SET_SELECTED_CALCULATION action does not touch anything else in the state', () => {
        // initially there is no customdata property, check the other parts
        expect(omit(stateWithSelectedAmount, 'configuration.customdata')).toEqual(initialState);
    });
    test('returns the correct state for CLEAR_BULKNAMES', () => {
        const stateWithBulkNamesData = configuratorReducer(initialState, {
            type: CLEAR_BULKNAMES,
        });
        const bulkNames = get(stateWithBulkNamesData, 'configuration.customdata.bulkNames');
        expect(bulkNames).toEqual({});
    });
    test('returns the correct state for SAVE_BULKNAMES', () => {
        const identifier = 'hoodie_blue_s';
        const bulkNamesData = ['Alex', 'Leon', 'Lea'];
        const stateWithBulkNamesData = configuratorReducer(initialState, {
            type: SAVE_BULKNAMES,
            identifier,
            bulkNamesData,
        });
        const bulkNames = get(stateWithBulkNamesData, 'configuration.customdata.bulkNames');
        expect(bulkNames).toEqual({ [identifier]: bulkNamesData });
    });
    test('returns the correct state for SET_SELECTED_AMOUNTS 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 };
        stateWithSelectedAmounts = configuratorReducer(initialState, {
            type: SET_SELECTED_AMOUNTS,
            variant: variant,
            sizes: sizes,
        });
        expect(get(stateWithSelectedAmounts, 'configuration.customdata.selectedAmounts')).toEqual({
            hoodie_green_m: 5,
            hoodie_blue_s: 2,
        });
    });
    test('returns the correct state for DELETE_SELECTED_AMOUNTS 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_blue_s: 0 };
        stateWithSelectedAmounts = configuratorReducer(stateWithSelectedAmounts, {
            type: DELETE_SELECTED_AMOUNTS,
            variant: variant,
            sizes: sizes,
        });
        expect(get(stateWithSelectedAmounts, 'configuration.customdata.selectedAmounts')).toEqual({});
    });

    test('returns the correct state for SWITCH_SELECTED_AMOUNT action', () => {
        stateWithSelectedAmount = configuratorReducer(initialState, {
            type: SET_SELECTED_AMOUNT,
            identifier: 'test_identifier',
            amount: 3,
        });
        const stateWithSwitchedAmount = configuratorReducer(stateWithSelectedAmount, {
            type: SWITCH_SELECTED_AMOUNT,
            srcIdentifier: 'test_identifier',
            dstIdentifier: 'other_identifier',
        });
        expect(get(stateWithSwitchedAmount, 'configuration.customdata.selectedAmounts')).toEqual({
            other_identifier: 3,
        });
    });

    describe('auto resolving calculation errors', () => {
        test('skipNextAutoResolve sets the calculationAutoResolve to "skipNext"', () => {
            const state = configuratorReducer(initialState, skipNextAutoResolve());
            expect(state.calculationAutoResolve).toBe('skipNext');
        });

        test('if calculationAutoResolve is "skipNext", change it to true on RECEIVE_CALCULATION action', () => {
            const stateWithAutoResolveNext = configuratorReducer(initialState, skipNextAutoResolve());
            const state = configuratorReducer(stateWithAutoResolveNext, {
                type: RECEIVE_CALCULATION,
                data: {},
            });
            expect(state.calculationAutoResolve).toBe(true);
        });

        test('calculationAutoResolve is enabled by default', () => {
            expect(initialState.calculationAutoResolve).toBe(true);
        });

        test('setCalculationAutoResolveEnabled sets the calculationAutoResolve to the given value', () => {
            const state = configuratorReducer(initialState, setCalculationAutoResolveEnabled(false));
            expect(state.calculationAutoResolve).toBe(false);
        });
    });
});
