import './index';
import crudModel from 'core/mocks/crud-model';

describe('component vnZoneEvents', () => {
    let $scope;
    let controller;
    let $httpBackend;

    beforeEach(ngModule('zone'));

    beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
        $httpBackend = _$httpBackend_;
        $scope = $rootScope.$new();
        const $element = angular.element(`<vn-zone-events></vn-zone-events>`);
        controller = $componentController('vnZoneEvents', {$element, $scope});
        controller.$params = {id: 1};
    }));

    describe('refresh()', () => {
        it('should set the zone and then call both getSummary() and getWarehouses()', () => {
            const date = '2021-10-01';

            controller.$params.id = 999;
            controller.$.calendar = {
                firstDay: date,
                lastDay: date
            };

            const params = {
                zoneFk: controller.$params.id,
                started: date,
                ended: date
            };

            const query = `Zones/getEventsFiltered?ended=${date}&started=${date}&zoneFk=${params.zoneFk}`;
            const response = {
                events: 'myEvents',
                exclusions: 'myExclusions',
                geoExclusions: 'myGeoExclusions',
            };
            $httpBackend.whenGET(query).respond(response);
            controller.refresh();
            $httpBackend.flush();

            const data = controller.$.data;

            expect(data.events).toBeDefined();
            expect(data.exclusions).toBeDefined();
        });
    });

    describe('onSelection()', () => {
        it('should call the editInclusion() method', () => {
            jest.spyOn(controller, 'editInclusion').mockReturnThis();

            const weekday = {};
            const days = [];
            const type = 'EventType';
            const events = [{name: 'Event'}];
            const exclusions = [];
            const exclusionsGeo = [];
            controller.editMode = 'include';
            controller.onSelection(days, type, weekday, events, exclusions, exclusionsGeo);

            expect(controller.editInclusion).toHaveBeenCalledWith({name: 'Event'});
        });

        it('should call the createInclusion() method', () => {
            jest.spyOn(controller, 'createInclusion').mockReturnThis();

            const weekday = {dated: Date.vnNew()};
            const days = [weekday];
            const type = 'EventType';
            const events = [];
            const exclusions = [];
            const exclusionsGeo = [];
            controller.editMode = 'include';
            controller.onSelection(days, type, weekday, events, exclusions, exclusionsGeo);

            expect(controller.createInclusion).toHaveBeenCalledWith(type, days, weekday);
        });

        it('should call the editExclusion() method with exclusions', () => {
            jest.spyOn(controller, 'editExclusion').mockReturnThis();

            const weekday = {};
            const days = [];
            const type = 'EventType';
            const events = [];
            const exclusions = [{name: 'Exclusion'}];
            const exclusionsGeo = [];
            controller.editMode = 'exclude';
            controller.onSelection(days, type, weekday, events, exclusions, exclusionsGeo);

            expect(controller.editExclusion).toHaveBeenCalled();
        });

        it('should call the editExclusion() method with exclusionsGeo', () => {
            jest.spyOn(controller, 'editExclusion').mockReturnThis();

            const weekday = {};
            const days = [];
            const type = 'EventType';
            const events = [];
            const exclusions = [];
            const exclusionsGeo = [{name: 'GeoExclusion'}];
            controller.editMode = 'exclude';
            controller.onSelection(days, type, weekday, events, exclusions, exclusionsGeo);

            expect(controller.editExclusion).toHaveBeenCalled();
        });

        it('should call the createExclusion() method', () => {
            jest.spyOn(controller, 'createExclusion').mockReturnThis();

            const weekday = {};
            const days = [{dated: Date.vnNew()}];
            const type = 'EventType';
            const events = [];
            const exclusions = [];
            const exclusionsGeo = [];
            controller.editMode = 'exclude';
            controller.onSelection(days, type, weekday, events, exclusions, exclusionsGeo);

            expect(controller.createExclusion).toHaveBeenCalledWith(days);
        });
    });

    describe('editExclusion()', () => {
        it('shoud set the excludeSelected.type = "specificLocations" and then call the excludeDialog show() method', () => {
            controller.$.excludeDialog = {show: jest.fn()};

            const exclusionGeos = [{id: 1}];
            const exclusions = [];

            controller.editExclusion(exclusions, exclusionGeos);

            expect(controller.excludeSelected.type).toEqual('specificLocations');
            expect(controller.$.excludeDialog.show).toHaveBeenCalledWith();
        });

        it('shoud set the excludeSelected.type = "all" and then call the excludeDialog show() method', () => {
            controller.$.excludeDialog = {show: jest.fn()};

            const exclusionGeos = [];
            const exclusions = [{id: 1}];

            controller.editExclusion(exclusions, exclusionGeos);

            expect(controller.excludeSelected.type).toEqual('all');
            expect(controller.$.excludeDialog.show).toHaveBeenCalledWith();
        });
    });

    describe('createExclusion()', () => {
        it('shoud set the excludeSelected property and then call the excludeDialog show() method', () => {
            controller.$.excludeDialog = {show: jest.fn()};

            const days = [Date.vnNew()];
            controller.createExclusion(days);

            expect(controller.excludeSelected).toBeDefined();
            expect(controller.isNew).toBeTruthy();
            expect(controller.$.excludeDialog.show).toHaveBeenCalledWith();
        });
    });

    describe('createInclusion()', () => {
        it('shoud set the selected property and then call the includeDialog show() method', () => {
            controller.$.includeDialog = {show: jest.fn()};

            const type = 'weekday';
            const days = [Date.vnNew()];
            const weekday = 1;
            controller.createInclusion(type, days, weekday);

            const selection = controller.selected;
            const firstWeekday = selection.wdays[weekday];

            expect(selection.type).toEqual('indefinitely');
            expect(firstWeekday).toBeTruthy();
            expect(controller.isNew).toBeTruthy();
            expect(controller.$.includeDialog.show).toHaveBeenCalledWith();
        });

        it('shoud set the selected property with the first day and then call the includeDialog show() method', () => {
            controller.$.includeDialog = {show: jest.fn()};

            const type = 'nonListedType';
            const days = [Date.vnNew()];
            const weekday = 1;
            controller.createInclusion(type, days, weekday);

            const selection = controller.selected;

            expect(selection.type).toEqual('day');
            expect(selection.dated).toEqual(days[0]);
            expect(controller.isNew).toBeTruthy();
            expect(controller.$.includeDialog.show).toHaveBeenCalledWith();
        });
    });

    describe('onIncludeResponse()', () => {
        it('shoud call the onDelete() method', () => {
            jest.spyOn(controller, 'onDelete').mockReturnValue(
                new Promise(accept => accept())
            );

            controller.selected = {id: 1};
            controller.onIncludeResponse('delete');

            expect(controller.onDelete).toHaveBeenCalledWith(1);
        });

        it('shoud make an HTTP POST query to create a new one and then call the refresh() method', () => {
            jest.spyOn(controller, 'refresh').mockReturnThis();

            controller.selected = {id: 1};
            controller.isNew = true;

            $httpBackend.when('POST', `Zones/1/events`).respond(200);
            controller.onIncludeResponse('accept');
            $httpBackend.flush();

            expect(controller.refresh).toHaveBeenCalledWith();
        });

        it('shoud make an HTTP PUT query and then call the refresh() method', () => {
            jest.spyOn(controller, 'refresh').mockReturnThis();

            controller.selected = {id: 1};
            controller.isNew = false;

            const eventId = 1;
            $httpBackend.when('PUT', `Zones/1/events/${eventId}`).respond(200);
            controller.onIncludeResponse('accept');
            $httpBackend.flush();

            expect(controller.refresh).toHaveBeenCalledWith();
        });
    });

    describe('onExcludeResponse()', () => {
        it('should call the exclusionCreate() method', () => {
            jest.spyOn(controller, 'exclusionCreate').mockReturnThis();

            controller.excludeSelected = {type: 'all'};
            controller.onExcludeResponse('accept');

            expect(controller.exclusionCreate).toHaveBeenCalledWith();
        });

        it('should call the exclusionGeoCreate() method', () => {
            jest.spyOn(controller, 'exclusionGeoCreate').mockReturnThis();

            controller.excludeSelected = {type: 'specificLocations'};
            controller.onExcludeResponse('accept');

            expect(controller.exclusionGeoCreate).toHaveBeenCalledWith();
        });

        it('should call the exclusionDelete() method', () => {
            jest.spyOn(controller, 'exclusionDelete').mockReturnThis();

            controller.excludeSelected = {id: 1, type: 'all'};
            controller.onExcludeResponse('delete');

            expect(controller.exclusionDelete).toHaveBeenCalledWith(controller.excludeSelected);
        });
    });

    describe('onDeleteResponse()', () => {
        it('shoud make an HTTP DELETE query and then call the refresh() method', () => {
            jest.spyOn(controller, 'refresh').mockReturnThis();

            const eventId = 1;
            $httpBackend.expect('DELETE', `Zones/1/events/1`).respond({id: 1});
            controller.onDeleteResponse('accept', eventId);
            $httpBackend.flush();

            expect(controller.refresh).toHaveBeenCalledWith();
        });
    });

    describe('exclusionCreate()', () => {
        it('shoud make an HTTP POST query and then call the refresh() method', () => {
            jest.spyOn(controller, 'refresh').mockReturnThis();

            controller.excludeSelected = {};
            controller.isNew = true;
            $httpBackend.expect('POST', `Zones/1/exclusions`).respond({id: 1});
            controller.exclusionCreate();
            $httpBackend.flush();

            expect(controller.refresh).toHaveBeenCalledWith();
        });
    });

    describe('exclusionDelete()', () => {
        it('shoud make an HTTP DELETE query once and then call the refresh() method', () => {
            jest.spyOn(controller, 'refresh').mockReturnThis();

            const exclusions = {id: 1};
            const firstExclusionId = 1;
            $httpBackend.expectDELETE(`Zones/1/exclusions/${firstExclusionId}`).respond(200);
            controller.exclusionDelete(exclusions);
            $httpBackend.flush();

            expect(controller.refresh).toHaveBeenCalledWith();
        });
    });

    describe('onSearch()', () => {
        it('should call the applyFilter() method and then set the data', () => {
            jest.spyOn(controller, 'getChecked').mockReturnValue([1, 2, 3]);

            controller.$.treeview = {};
            controller.$.model = crudModel;
            controller.excludeSelected = {type: 'specificLocations'};
            controller._excludeSearch = 'es';

            controller.onSearch();
            const treeviewData = controller.$.treeview.data;

            expect(treeviewData).toBeDefined();
            expect(treeviewData.length).toEqual(3);
        });
    });

    describe('onFetch()', () => {
        it('should call the applyFilter() method and then return the model data', () => {
            jest.spyOn(controller, 'getChecked').mockReturnValue([1, 2, 3]);

            controller.$.model = crudModel;
            const result = controller.onFetch();

            expect(result.length).toEqual(3);
        });
    });
});