import { TestBed } from '@angular/core/testing';
import { DictionariesService } from '@modules/components/page-filters/services/dictionaries-service';
import { CanActivateDepartureSearch } from '@online-board/guards/can-activate-departure-search';
import { CanActivateDateParams } from '@online-board/guards/utils/can-activate-date-params';
import { CanActivateRouteParams } from '@online-board/guards/utils/can-activate-route-params';
import { CanActivateStations } from '@online-board/guards/utils/can-activate-stations';
import { OnlineBoardDateValidationService } from '@online-board/services/date-validation.service';
import { OnlineBoardNavigationService } from '@online-board/services/navigation.service';
import { OnlineBoardUrlParserService } from '@online-board/services/url/url-parser.service';
import { AppSettingsService } from '@shared/services';
import { StationCodeValidationService } from '@shared/services/validators/station-code.service';
import { TimeRangeValidationService } from '@shared/services/validators/time-range.service';

describe('CanActivateDepartureSearch', () => {
    let service: CanActivateDepartureSearch;

    const boardMinDate = new Date(2022, 4, 23);
    const boardMaxDate = new Date(2022, 4, 29);
    const appSettingsService: Partial<AppSettingsService> = {
        getSettings: () => {
            return Promise.resolve({
                boardMinDate,
                boardMaxDate,
            }) as any;
        },
    };

    const toNotFoundMock = jasmine.createSpy('toNotFound');
    const toStartPageMock = jasmine.createSpy('toStartPage');
    const navigationService: Partial<OnlineBoardNavigationService> = {
        toNotFound: toNotFoundMock,
        toStartPage: toStartPageMock,
    };

    const dictionariesService: Partial<DictionariesService> = {
        ready$: Promise.resolve(),
        getCityOrAirport(code: string) {
            const map = new Map();
            map.set('MOW', true);
            map.set('LED', true);
            map.set('KUF', true);
            map.set('SVO', true);

            return map.has(code) as any;
        },
    };

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [
                CanActivateDepartureSearch,
                CanActivateRouteParams,
                CanActivateStations,
                CanActivateDateParams,
                StationCodeValidationService,
                OnlineBoardDateValidationService,
                TimeRangeValidationService,
                OnlineBoardUrlParserService,
                {
                    provide: AppSettingsService,
                    useValue: appSettingsService,
                },
                {
                    provide: OnlineBoardNavigationService,
                    useValue: navigationService,
                },
                {
                    provide: DictionariesService,
                    useValue: dictionariesService,
                },
            ],
        });

        service = TestBed.inject(CanActivateDepartureSearch);
    });

    it('should return true for valid departure params without time range', async () => {
        const params = 'MOW-20220528';
        const result = await service.canActivate({
            params: {
                params,
            },
        } as any);

        expect(result).toBe(true);
    });

    it('should return true for valid departure params with time range', async () => {
        const params = 'MOW-20220528-06002200';
        const result = await service.canActivate({
            params: {
                params,
            },
        } as any);

        expect(result).toBe(true);
    });

    it('should redirect to not found because departure city is invalid', async () => {
        const params = 'ABA-20220528';
        const result = await service.canActivate({
            params: {
                params,
            },
        } as any);

        expect(result).not.toBe(true);
        expect(toNotFoundMock).toHaveBeenCalled();
    });

    it('should redirect to start page because date is invalid', async () => {
        const params = 'MOW-20220521';
        const result = await service.canActivate({
            params: {
                params,
            },
        } as any);

        expect(result).not.toBe(true);
        expect(toStartPageMock).toHaveBeenCalled();
    });

    it('should redirect to start page because time range is invalid', async () => {
        const params = 'MOW-20220528-22000600';
        const result = await service.canActivate({
            params: {
                params,
            },
        } as any);

        expect(result).not.toBe(true);
        expect(toStartPageMock).toHaveBeenCalled();
    });
});
