import { TestBed } from '@angular/core/testing';
import { Router } from '@angular/router';
import { OnlineBoardFilterService } from '@online-board/services/filter/filter.service';
import {
    IOnlineBoardRoutePageUrlParams,
    ONLINE_BOARD_URL_BASE,
    OnlineBoardUrlBuilderService,
} from '@online-board/services/url';
import { ApiParserService } from '@shared/services/api/parser.service';
import { SearchHistoryService } from '@shared/services/history/search-history.service';
import { IParsedFlightId } from '@typings/flight/flight-id';

describe('OnlineBoardFilterService', () => {
    let service: OnlineBoardFilterService;
    let historyService: SearchHistoryService;
    const navigateByUrlMock = jasmine.createSpy('navigateByUrl');

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [
                OnlineBoardFilterService,
                SearchHistoryService,
                ApiParserService,
                OnlineBoardUrlBuilderService,
                {
                    provide: Router,
                    useValue: {
                        navigateByUrl: navigateByUrlMock,
                    },
                },
                {
                    provide: ONLINE_BOARD_URL_BASE,
                    useValue: 'onlineboard',
                },
            ],
        });

        service = TestBed.inject(OnlineBoardFilterService);
        historyService = TestBed.inject(SearchHistoryService);
        navigateByUrlMock.calls.reset();
        navigateByUrlMock.and.returnValue(Promise.resolve(true));
    });

    it('Should call navigateByUrl with flight number page url', () => {
        const params: IParsedFlightId = {
            flightNumber: '0001',
            carrier: 'SU',
            date: new Date(2022, 4, 28),
        };

        service.toFlightNumberPage(params);
        expect(navigateByUrlMock).toHaveBeenCalledWith(
            'onlineboard/flight/SU0001-20220528',
        );
    });

    it('Should call navigateByUrl with arrival page url', () => {
        const params: IOnlineBoardRoutePageUrlParams = {
            arrival: 'MOW',
            date: new Date(2022, 4, 28),
        };

        service.toRoutePage(params);
        expect(navigateByUrlMock).toHaveBeenCalledWith(
            'onlineboard/arrival/MOW-20220528',
        );
    });

    it('Should call navigateByUrl with departure page url', () => {
        const params: IOnlineBoardRoutePageUrlParams = {
            departure: 'MOW',
            date: new Date(2022, 4, 28),
        };

        service.toRoutePage(params);
        expect(navigateByUrlMock).toHaveBeenCalledWith(
            'onlineboard/departure/MOW-20220528',
        );
    });

    it('Should call navigateByUrl with route page url', () => {
        const params: IOnlineBoardRoutePageUrlParams = {
            departure: 'MOW',
            arrival: 'GDX',
            date: new Date(2022, 4, 28),
        };

        service.toRoutePage(params);
        expect(navigateByUrlMock).toHaveBeenCalledWith(
            'onlineboard/route/MOW-GDX-20220528',
        );
    });

    it('Should not call navigateByUrl if neither departure nor arrival were provided', () => {
        const params: IOnlineBoardRoutePageUrlParams = {
            date: new Date(2022, 4, 28),
        };

        service.toRoutePage(params);
        expect(navigateByUrlMock).not.toHaveBeenCalled();
    });

    it('Should add entry with flight number page url to history', async () => {
        const params: IParsedFlightId = {
            flightNumber: '0001',
            carrier: 'SU',
            date: new Date(2022, 4, 28),
        };

        await service.toFlightNumberPage(params);
        expect(historyService.items.length).toBe(1);
        expect(historyService.items[0].url).toBe(
            'onlineboard/flight/SU0001-20220528',
        );
    });

    it('Should not add entry with flight number page url to history if navigation failed', async () => {
        navigateByUrlMock.and.returnValue(Promise.resolve(false));
        const params: IParsedFlightId = {
            flightNumber: '0001',
            carrier: 'SU',
            date: new Date(2022, 4, 28),
        };

        await service.toFlightNumberPage(params);
        expect(historyService.items.length).toBe(0);
    });

    it('Should add entry with arrival page url to history', async () => {
        const params: IOnlineBoardRoutePageUrlParams = {
            arrival: 'MOW',
            date: new Date(2022, 4, 28),
        };

        await service.toRoutePage(params);
        expect(historyService.items.length).toBe(1);
        expect(historyService.items[0].url).toBe(
            'onlineboard/arrival/MOW-20220528',
        );
    });

    it('Should not add entry with arrival page url to history if navigation failed', async () => {
        navigateByUrlMock.and.returnValue(Promise.resolve(false));
        const params: IOnlineBoardRoutePageUrlParams = {
            arrival: 'MOW',
            date: new Date(2022, 4, 28),
        };

        await service.toRoutePage(params);
        expect(historyService.items.length).toBe(0);
    });

    it('Should add entry with departure page url to history', async () => {
        const params: IOnlineBoardRoutePageUrlParams = {
            departure: 'MOW',
            date: new Date(2022, 4, 28),
        };

        await service.toRoutePage(params);
        expect(historyService.items.length).toBe(1);
        expect(historyService.items[0].url).toBe(
            'onlineboard/departure/MOW-20220528',
        );
    });

    it('Should add entry with route page url to history', async () => {
        const params: IOnlineBoardRoutePageUrlParams = {
            departure: 'MOW',
            arrival: 'GDX',
            date: new Date(2022, 4, 28),
        };

        await service.toRoutePage(params);
        expect(historyService.items.length).toBe(1);
        expect(historyService.items[0].url).toBe(
            'onlineboard/route/MOW-GDX-20220528',
        );
    });
});
