import { INITIAL_APPLICATION_STATE } from './application.state';
import * as actions from './application.actions';
import { applicationReducer } from './application.reducer';
import { ApplicationProcess } from '../defs';
import { ApplicationState } from './application.state';

describe('applicationReducer', () => {
  describe('setSection()', () => {
    it('should return modified state with section customer', () => {
      const initialState = INITIAL_APPLICATION_STATE;

      const action = actions.setSection({ section: 'customer' });
      const state = applicationReducer(initialState, action);

      expect(state).toEqual({
        ...initialState,
        section: 'customer',
      });
    });

    it('should return modified state with section branch', () => {
      const initialState = INITIAL_APPLICATION_STATE;

      const action = actions.setSection({ section: 'branch' });
      const state = applicationReducer(initialState, action);

      expect(state).toEqual({
        ...initialState,
        section: 'branch',
      });
    });
  });

  describe('addProcess()', () => {
    it('should return modified state with new process if no processes are registered in the state', () => {
      const initialState = INITIAL_APPLICATION_STATE;

      const process: ApplicationProcess = {
        id: 1,
        name: 'Vorgang',
        section: 'customer',
        type: 'cart',
        data: {},
      };

      const action = actions.addProcess({ process });
      const state = applicationReducer(initialState, action);
      expect(state.processes[0]).toEqual(process);
    });
  });

  describe('patchProcess()', () => {
    it('should return modified state with updated process when id is found', () => {
      const initialState = INITIAL_APPLICATION_STATE;

      const process: ApplicationProcess = {
        id: 1,
        name: 'Vorgang',
        section: 'customer',
        type: 'cart',
      };

      const action = actions.patchProcess({ processId: process.id, changes: { ...process, name: 'Test' } });
      const state = applicationReducer(
        {
          ...initialState,
          processes: [process],
        },
        action
      );
      expect(state.processes[0].name).toEqual('Test');
    });

    it('should return unmodified state when id is not existing', () => {
      const initialState = INITIAL_APPLICATION_STATE;

      const process: ApplicationProcess = {
        id: 1,
        name: 'Vorgang',
        section: 'customer',
        type: 'cart',
      };

      const action = actions.patchProcess({ processId: process.id, changes: { ...process, id: 2 } });
      const state = applicationReducer(
        {
          ...initialState,
          processes: [process],
        },
        action
      );
      expect(state.processes).toEqual([process]);
    });
  });

  describe('removeProcess()', () => {
    it('should return initial state if no processes are registered in the state', () => {
      const initialState = INITIAL_APPLICATION_STATE;

      const action = actions.removeProcess({ processId: 2 });
      const state = applicationReducer(initialState, action);
      expect(state).toEqual(initialState);
    });

    it('should return the unmodified state if processId not found', () => {
      const initialState = INITIAL_APPLICATION_STATE;
      const modifiedState: ApplicationState = {
        ...initialState,
        section: 'customer',
        processes: [
          {
            id: 1,
            name: 'Vorgang',
            section: 'customer',
            type: 'cart',
          },
          {
            id: 4,
            name: 'Vorgang',
            section: 'customer',
            type: 'goods-out',
          },
        ] as ApplicationProcess[],
      };

      const action = actions.removeProcess({ processId: 2 });
      const state = applicationReducer(modifiedState, action);
      expect(state).toEqual(modifiedState);
    });

    it('should return modified state, after process gets removed', () => {
      const initialState = INITIAL_APPLICATION_STATE;
      const modifiedState: ApplicationState = {
        ...initialState,
        section: 'customer',
        processes: [
          {
            id: 1,
            name: 'Vorgang',
            section: 'customer',
            type: 'cart',
          },
          {
            id: 2,
            name: 'Vorgang',
            section: 'customer',
            type: 'goods-out',
          },
        ] as ApplicationProcess[],
      };

      const action = actions.removeProcess({ processId: 2 });
      const state = applicationReducer(modifiedState, action);
      expect(state.processes).toEqual([
        {
          id: 1,
          name: 'Vorgang',
          section: 'customer',
          type: 'cart',
        },
      ]);
    });
  });

  describe('setActivatedProcess()', () => {
    it('should return modified state with process.activated value', () => {
      const process: ApplicationProcess = {
        id: 3,
        name: 'Vorgang 3',
        section: 'customer',
      };
      const initialState: ApplicationState = {
        ...INITIAL_APPLICATION_STATE,
        processes: [process],
      };

      const action = actions.setActivatedProcess({ activatedProcessId: 3 });
      const state = applicationReducer(initialState, action);

      expect(state.processes[0].activated).toBeDefined();
    });

    it('should return modified state without process.activated value when activatedProcessId doesnt exist', () => {
      const process: ApplicationProcess = {
        id: 1,
        name: 'Vorgang 3',
        section: 'customer',
      };
      const initialState: ApplicationState = {
        ...INITIAL_APPLICATION_STATE,
        processes: [process],
      };

      const action = actions.setActivatedProcess({ activatedProcessId: 3 });
      const state = applicationReducer(initialState, action);

      expect(state.processes[0].activated).toBeUndefined();
    });
  });
});
