/* eslint max-len: ["error", { "code": 150 }]*/
import './index';

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

    beforeEach(ngModule('route'));

    beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
        $httpBackend = _$httpBackend_;
        $scope = $rootScope.$new();
        const $element = angular.element('<vn-route-tickets></vn-route-tickets>');
        controller = $componentController('vnRouteTickets', {$element, $scope});
        controller.route = {id: 1};
        controller.$.model = {
            refresh: () => {},
            remove: () => {}
        };
        controller.card = {reload: () => {}};
    }));

    describe('route setter/getter', () => {
        it('should return the route id', () => {
            controller.route = 2;

            expect(controller.route).toEqual(2);
        });
    });

    describe('isChecked getter', () => {
        it('should return false if none of the tickets is checked or there are no tickets', () => {
            expect(controller.isChecked).toBeFalsy();
        });

        it('should return true if any of the tickets is checked', () => {
            controller.tickets = [{checked: true}];

            expect(controller.isChecked).toBeTruthy();
        });
    });

    describe('getHighestPriority()', () => {
        it('should return the highest value found in priorities plus 1', () => {
            controller.$.model = {data: [
                {priority: 99},
                {priority: 1},
                {priority: 2},
                {priority: 3},
                {priority: 4},
                {priority: 5},
            ]};

            let result = controller.getHighestPriority();

            expect(result).toEqual(100);
        });
    });

    describe('setHighestPriority()', () => {
        it('should set a ticket highest priority', () => {
            jest.spyOn(controller.vnApp, 'showSuccess');
            controller.$.model.data = [{priority: 3}];
            const ticket = {id: 1, priority: 2};
            const res = {data: {priority: 4}};

            $httpBackend.expectPATCH(`Tickets/${ticket.id}/`).respond(res);
            controller.setHighestPriority(ticket);
            $httpBackend.flush();

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

    describe('setPriority()', () => {
        it('should set a ticket priority', () => {
            jest.spyOn(controller.vnApp, 'showSuccess');
            const ticketId = 1;
            const priority = 999;

            $httpBackend.expectPATCH(`Tickets/${ticketId}/`).respond('ok');
            controller.setPriority(ticketId, priority);
            $httpBackend.flush();

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

    describe('deletePriority()', () => {
        it('should delete priority of all tickets', () => {
            jest.spyOn(controller.$.model, 'refresh');
            jest.spyOn(controller.vnApp, 'showSuccess');
            controller.tickets = [{id: 1, checked: true}];

            $httpBackend.expectPATCH(`Tickets/${controller.tickets[0].id}/`).respond();
            controller.deletePriority();
            $httpBackend.flush();

            expect(controller.vnApp.showSuccess).toHaveBeenCalled();
            expect(controller.$.model.refresh).toHaveBeenCalledWith();
        });
    });

    describe('setOrderedPriority()', () => {
        it('should set priority of all tickets starting by 1', () => {
            jest.spyOn(controller.$.model, 'refresh');
            jest.spyOn(controller.vnApp, 'showSuccess');
            const tickets = [{id: 1, checked: true}];

            $httpBackend.expectPATCH(`Tickets/${tickets[0].id}/`).respond();
            controller.setOrderedPriority(tickets);
            $httpBackend.flush();

            expect(controller.vnApp.showSuccess).toHaveBeenCalled();
            expect(controller.$.model.refresh).toHaveBeenCalledWith();
        });
    });

    describe('getSelectedItems()', () => {
        it('should return the selected items', () => {
            let items = [
                {id: 1, checked: true},
                {id: 2, checked: false},
                {id: 3, checked: true},
                {id: 4, checked: false},
                {id: 5, checked: true},
            ];

            let selectedItems = controller.getSelectedItems(items);

            expect(selectedItems).toMatchSnapshot();
        });
    });

    describe('goToBuscaman()', () => {
        it('should open buscaman with the given arguments', () => {
            jest.spyOn(window, 'open').mockReturnThis();
            const expectedUrl = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr=46460%20Av%20Espioca%20100+to:n19%20London%20my%20street';
            controller.route = {vehicleFk: 1};
            const url = `Routes/${controller.route.vehicleFk}/getDeliveryPoint`;
            $httpBackend.expectGET(url).respond('46460 Av Espioca 100');

            controller.tickets = [
                {
                    id: 1,
                    checked: true,
                    street: 'my street',
                    postalCode: 'n19',
                    city: 'London'
                },
            ];

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

            expect(window.open).toHaveBeenCalledWith(expectedUrl, '_blank');
        });
    });

    describe('showDeleteConfirm()', () => {
        it('should open a confirm dialog after setting the selected ticket into the controller', () => {
            controller.$.confirm = {show: () => {}};
            jest.spyOn(controller.$.confirm, 'show');
            let ticketId = 1;

            controller.showDeleteConfirm(ticketId);

            expect(controller.selectedTicket).toEqual(ticketId);
            expect(controller.$.confirm.show).toHaveBeenCalledWith();
        });
    });

    describe('removeTicketFromRoute()', () => {
        it('should perform a patch query then call showSuccess and updateVolume methods', () => {
            controller.$params = {id: 1101};

            jest.spyOn(controller.vnApp, 'showSuccess');
            jest.spyOn(controller.$.model, 'remove');

            let ticketId = 1;
            controller.selectedTicket = ticketId;

            $httpBackend.whenPOST(`Routes/${controller.$params.id}/updateVolume`).respond(200);
            $httpBackend.expectPATCH(`Tickets/${ticketId}/`).respond('ok');
            controller.removeTicketFromRoute();
            $httpBackend.flush();

            expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Ticket removed from route');
        });
    });

    describe('updateVolume()', () => {
        it('should perform a POST query then call both reload and refresh methods', () => {
            controller.$params = {id: 999};
            jest.spyOn(controller.$.model, 'refresh');
            jest.spyOn(controller.card, 'reload');

            let ticketId = 1;
            controller.selectedTicket = ticketId;

            const url = `Routes/${controller.$params.id}/updateVolume`;
            $httpBackend.expectPOST(url).respond('ok');
            controller.updateVolume();
            $httpBackend.flush();

            expect(controller.$.model.refresh).toHaveBeenCalledWith();
            expect(controller.card.reload).toHaveBeenCalledWith();
        });
    });

    describe('guessPriority()', () => {
        it('should perform a GET query then call both refresh and showSuccess methods', () => {
            jest.spyOn(controller.$.model, 'refresh');
            jest.spyOn(controller.vnApp, 'showSuccess');
            controller.$params = {id: 99};

            const url = `Routes/${controller.$params.id}/guessPriority/`;
            $httpBackend.expectGET(url).respond('ok');
            controller.guessPriority();
            $httpBackend.flush();

            expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Order changed');
            expect(controller.$.model.refresh).toHaveBeenCalledWith();
        });
    });

    describe('onDrop()', () => {
        it('should call the insert method when dragging a ticket number', () => {
            jest.spyOn(controller, 'insert');

            const expectedTicketId = '11';
            const draggedElement = '11';
            const $event = {
                dataTransfer: {
                    getData: () => draggedElement
                }
            };
            controller.onDrop($event);

            expect(controller.insert).toHaveBeenCalledWith(expectedTicketId);
        });

        it('should call the insert method when dragging a ticket link', () => {
            jest.spyOn(controller, 'insert');

            const expectedTicketId = '11';
            const draggedElement = 'http://arkamcity.com/#!/ticket/11/summary';
            const $event = {
                dataTransfer: {
                    getData: () => draggedElement
                }
            };
            controller.onDrop($event);

            expect(controller.insert).toHaveBeenCalledWith(expectedTicketId);
        });

        it('should throw an error when dragging an invalid ticket link', () => {
            jest.spyOn(controller.vnApp, 'showError');

            const draggedElement = 'http://arkamcity.com/#!/item/11/summary';
            const $event = {
                dataTransfer: {
                    getData: () => draggedElement
                }
            };
            controller.onDrop($event);

            expect(controller.vnApp.showError).toHaveBeenCalledWith('Ticket not found');
        });
    });

    describe('insert()', () => {
        it('should make a HTTP patch query and then call both refresh and showSuccess methods', () => {
            controller.$params = {id: 1101};

            jest.spyOn(controller.$.model, 'refresh').mockReturnThis();
            jest.spyOn(controller.vnApp, 'showSuccess');

            const ticketId = 11;
            const data = {ticketId};

            $httpBackend.whenPOST(`Routes/${controller.$params.id}/updateVolume`).respond(200);
            $httpBackend.expect('PATCH', `Routes/1/insertTicket`, data).respond();
            controller.insert(ticketId);
            $httpBackend.flush();

            expect(controller.vnApp.showSuccess).toHaveBeenCalled();
            expect(controller.$.model.refresh).toHaveBeenCalledWith();
        });
    });
});