import './index.js';

describe('Component vnWorkerTimeControl', () => {
    let $httpBackend;
    let $scope;
    let $element;
    let controller;
    let $httpParamSerializer;

    beforeEach(ngModule('worker'));

    beforeEach(inject(($componentController, $rootScope, $stateParams, _$httpBackend_, _$httpParamSerializer_) => {
        $stateParams.id = 1;
        $httpBackend = _$httpBackend_;
        $httpParamSerializer = _$httpParamSerializer_;
        $scope = $rootScope.$new();
        $element = angular.element('<vn-worker-time-control></vn-worker-time-control>');
        controller = $componentController('vnWorkerTimeControl', {$element, $scope});
        controller.card = {
            hasWorkCenter: true
        };
    }));

    describe('date() setter', () => {
        it(`should set the weekDays and the date in the controller`, () => {
            let today = Date.vnNew();
            jest.spyOn(controller, 'fetchHours').mockReturnThis();

            controller.date = today;

            expect(controller._date).toEqual(today);
            expect(controller.started).toBeDefined();
            expect(controller.ended).toBeDefined();
            expect(controller.weekDays.length).toEqual(7);
        });
    });

    describe('hours() setter', () => {
        it(`should set hours data at it's corresponding week day`, () => {
            let today = Date.vnNew();
            jest.spyOn(controller, 'fetchHours').mockReturnThis();

            controller.date = today;

            let hours = [
                {
                    id: 1,
                    timed: controller.started.toJSON(),
                    userFk: 1
                }, {
                    id: 2,
                    timed: controller.ended.toJSON(),
                    userFk: 1
                }, {
                    id: 3,
                    timed: controller.ended.toJSON(),
                    userFk: 1
                }
            ];

            controller.hours = hours;

            expect(controller.weekDays.length).toEqual(7);
            expect(controller.weekDays[0].hours.length).toEqual(1);
            expect(controller.weekDays[6].hours.length).toEqual(2);
        });
    });

    describe('getWorkedHours() ', () => {
        it('should set the weekdays expected and worked hours plus the total worked hours', () => {
            let today = Date.vnNew();
            jest.spyOn(controller, 'fetchHours').mockReturnThis();

            controller.date = today;

            let sixHoursInSeconds = 6 * 60 * 60;
            let tenHoursInSeconds = 10 * 60 * 60;
            let response = [
                {
                    dated: today,
                    expectedHours: sixHoursInSeconds,
                    workedHours: tenHoursInSeconds,

                },
            ];
            $httpBackend.whenRoute('GET', 'Workers/:id/getWorkedHours')
                .respond(response);

            $httpBackend.whenRoute('GET', 'WorkerTimeControlMails')
                .respond([]);

            today.setHours(0, 0, 0, 0);

            let weekOffset = today.getDay() - 1;
            if (weekOffset < 0) weekOffset = 6;

            let started = new Date(today.getTime());
            started.setDate(started.getDate() - weekOffset);
            controller.started = started;

            let ended = new Date(started.getTime());
            ended.setHours(23, 59, 59, 59);
            ended.setDate(ended.getDate() + 6);
            controller.ended = ended;

            controller.getWorkedHours(controller.started, controller.ended);
            $httpBackend.flush();

            expect(controller.weekDays.length).toEqual(7);
            expect(controller.weekDays[weekOffset].expectedHours).toEqual(response[0].expectedHours);
            expect(controller.weekDays[weekOffset].workedHours).toEqual(response[0].workedHours);
            expect(controller.weekTotalHours).toEqual('10:00');
        });

        describe('formatHours() ', () => {
            it(`should format a passed timestamp to hours and minutes`, () => {
                const result = controller.formatHours(3600);

                expect(result).toEqual('01:00');
            });
        });

        describe('save() ', () => {
            it(`should make a query an then call to the fetchHours() method`, () => {
                const today = Date.vnNew();

                jest.spyOn(controller, 'getWeekData').mockReturnThis();
                jest.spyOn(controller, 'getMailStates').mockReturnThis();

                controller.$.model = {applyFilter: jest.fn().mockReturnValue(Promise.resolve())};
                controller.date = today;
                controller.fetchHours = jest.fn();
                controller.selectedRow = {id: 1, timed: Date.vnNew(), direction: 'in'};
                controller.$.editEntry = {
                    hide: () => {}
                };
                const expectedParams = {direction: 'in'};
                $httpBackend.expect('POST', 'WorkerTimeControls/1/updateTimeEntry', expectedParams).respond(200);
                controller.save();
                $httpBackend.flush();

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

        describe('$postLink() ', () => {
            it(`should set the controller date as today if no timestamp is defined`, () => {
                controller.$.model = {applyFilter: jest.fn().mockReturnValue(Promise.resolve())};
                controller.$params = {timestamp: undefined};
                controller.$postLink();

                expect(controller.date).toEqual(jasmine.any(Date));
            });

            it(`should set the controller date using the received timestamp`, () => {
                const timestamp = 1;
                const date = new Date(timestamp);

                controller.$.model = {applyFilter: jest.fn().mockReturnValue(Promise.resolve())};
                controller.$.calendar = {};
                controller.$params = {timestamp: timestamp};

                controller.$postLink();

                expect(controller.date.toDateString()).toEqual(date.toDateString());
            });
        });

        describe('getWeekData() ', () => {
            it(`should make a query an then update the state and reason`, () => {
                const today = Date.vnNew();
                const response = [
                    {
                        state: 'SENDED',
                        reason: null
                    }
                ];

                controller._date = today;

                $httpBackend.whenRoute('GET', 'WorkerTimeControlMails')
                    .respond(response);

                controller.getWeekData();
                $httpBackend.flush();

                expect(controller.state).toBe('SENDED');
                expect(controller.reason).toBe(null);
            });
        });

        describe('isSatisfied() ', () => {
            it(`should make a query an then call three methods`, () => {
                const today = Date.vnNew();
                jest.spyOn(controller, 'getWeekData').mockReturnThis();
                jest.spyOn(controller, 'getMailStates').mockReturnThis();
                jest.spyOn(controller.vnApp, 'showSuccess');

                controller.$.model = {applyFilter: jest.fn().mockReturnValue(Promise.resolve())};
                controller.worker = {id: 1};
                controller.date = today;
                controller.weekNumber = 1;

                $httpBackend.expect('POST', 'WorkerTimeControls/updateWorkerTimeControlMail').respond();
                controller.isSatisfied();
                $httpBackend.flush();

                expect(controller.getMailStates).toHaveBeenCalledWith(controller.date);
                expect(controller.getWeekData).toHaveBeenCalled();
                expect(controller.vnApp.showSuccess).toHaveBeenCalled();
            });
        });

        describe('isUnsatisfied() ', () => {
            it(`should throw an error is reason is empty`, () => {
                let error;
                try {
                    controller.isUnsatisfied();
                } catch (e) {
                    error = e;
                }

                expect(error).toBeDefined();
                expect(error.message).toBe(`You must indicate a reason`);
            });

            it(`should make a query an then call three methods`, () => {
                const today = Date.vnNew();
                jest.spyOn(controller, 'getWeekData').mockReturnThis();
                jest.spyOn(controller, 'getMailStates').mockReturnThis();
                jest.spyOn(controller.vnApp, 'showSuccess');

                controller.$.model = {applyFilter: jest.fn().mockReturnValue(Promise.resolve())};
                controller.worker = {id: 1};
                controller.date = today;
                controller.weekNumber = 1;
                controller.reason = 'reason';

                $httpBackend.expect('POST', 'WorkerTimeControls/updateWorkerTimeControlMail').respond();
                controller.isSatisfied();
                $httpBackend.flush();

                expect(controller.getMailStates).toHaveBeenCalledWith(controller.date);
                expect(controller.getWeekData).toHaveBeenCalled();
                expect(controller.vnApp.showSuccess).toHaveBeenCalled();
            });
        });

        describe('resendEmail() ', () => {
            it(`should make a query an then call showSuccess method`, () => {
                const today = Date.vnNew();

                jest.spyOn(controller, 'getWeekData').mockReturnThis();
                jest.spyOn(controller, 'getMailStates').mockReturnThis();
                jest.spyOn(controller.vnApp, 'showSuccess');

                controller.$.model = {applyFilter: jest.fn().mockReturnValue(Promise.resolve())};
                controller.worker = {id: 1};
                controller.worker = {user: {emailUser: {email: 'employee@verdnatura.es'}}};
                controller.date = today;
                controller.weekNumber = 1;

                $httpBackend.expect('POST', 'WorkerTimeControls/weekly-hour-hecord-email').respond();
                controller.resendEmail();
                $httpBackend.flush();

                expect(controller.vnApp.showSuccess).toHaveBeenCalled();
            });
        });

        describe('getMailStates() ', () => {
            it(`should make a query an then call showSuccess method`, () => {
                const today = Date.vnNew();
                jest.spyOn(controller, 'repaint').mockReturnThis();

                controller.$params = {id: 1};

                $httpBackend.expect('GET', `WorkerTimeControls/1/getMailStates?month=1&year=2001`).respond();
                controller.getMailStates(today);
                $httpBackend.flush();

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