import { HttpParams } from '@angular/common/http';
import { TestBed } from '@angular/core/testing';
import { OnlineBoardApiService } from '@online-board/services/api.service';
import { IOnlineBoardRoutePageUrlParams } from '@online-board/services/url/types';
import { LocalizationService } from '@shared/services';
import { ApiService } from '@shared/services/api/api.service';
import { EndpointService } from '@shared/services/api/endpoint.service';
import { ApiFormatterService } from '@shared/services/api/formatter.service';

describe('OnlineBoardApiService', () => {
    let service: OnlineBoardApiService;
    const cacheFirstMock = jasmine.createSpy('cacheFirst');
    const getMock = jasmine
        .createSpy('get')
        .and.returnValue({ toPromise: () => {} });

    const mockApiService: Partial<ApiService> = {
        cacheFirst: cacheFirstMock,
        get: getMock,
    };

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [
                OnlineBoardApiService,
                ApiFormatterService,
                EndpointService,
                {
                    provide: ApiService,
                    useValue: mockApiService,
                },
                {
                    provide: LocalizationService,
                    useValue: {
                        Language: 'ru',
                    },
                },
            ],
        });

        cacheFirstMock.calls.reset();
        getMock.calls.reset();
        service = TestBed.inject(OnlineBoardApiService);
    });

    function assertCacheFirst(url, expectedParams) {
        expect(cacheFirstMock.calls.mostRecent().args[0]).toBe(url);
        expect(cacheFirstMock.calls.mostRecent().args[1].toString()).toEqual(
            new HttpParams({
                fromObject: expectedParams,
            }).toString(),
        );
    }

    it('should call cacheFirst with flight info and formatted date', () => {
        const flightNumber = '0001';
        const carrier = 'SU';
        const date = new Date(2022, 4, 28);
        const url = '/api/flights/v1.1/ru/board';
        const expectedParams = {
            flightNumber: 'SU0001',
            date: '2022-05-28T00:00:00',
        };

        service.getFlightsByFlightNumber({ flightNumber, carrier, date });
        assertCacheFirst(url, expectedParams);
    });

    it('should call cacheFirst with valid arrival params', () => {
        const params: IOnlineBoardRoutePageUrlParams = {
            date: new Date(2022, 4, 28),
            arrival: 'LED',
        };
        const url = '/api/flights/v1.1/ru/board';
        const expectedParams = {
            dateFrom: '2022-05-28T00:00:00',
            dateTo: '2022-05-28T00:00:00',
            arrival: 'LED',
        };

        service.getFlightsByRoute(params);
        assertCacheFirst(url, expectedParams);
    });

    it('should call cacheFirst with valid departure params', () => {
        const params: IOnlineBoardRoutePageUrlParams = {
            date: new Date(2022, 4, 28),
            departure: 'LED',
        };
        const url = '/api/flights/v1.1/ru/board';
        const expectedParams = {
            dateFrom: '2022-05-28T00:00:00',
            dateTo: '2022-05-28T00:00:00',
            departure: 'LED',
        };

        service.getFlightsByRoute(params);
        assertCacheFirst(url, expectedParams);
    });

    it('should call cacheFirst with valid route params', () => {
        const params: IOnlineBoardRoutePageUrlParams = {
            arrival: 'MOW',
            date: new Date(2022, 4, 28),
            departure: 'LED',
        };
        const url = '/api/flights/v1.1/ru/board';
        const expectedParams = {
            dateFrom: '2022-05-28T00:00:00',
            dateTo: '2022-05-28T00:00:00',
            departure: 'LED',
            arrival: 'MOW',
        };

        service.getFlightsByRoute(params);
        assertCacheFirst(url, expectedParams);
    });

    it('should call cacheFirst with valid route params with time range', () => {
        const params: IOnlineBoardRoutePageUrlParams = {
            arrival: 'MOW',
            date: new Date(2022, 4, 28),
            departure: 'LED',
            timeFrom: '0600',
            timeTo: '2200',
        };
        const url = '/api/flights/v1.1/ru/board';
        const expectedParams = {
            dateFrom: '2022-05-28T00:00:00',
            dateTo: '2022-05-28T00:00:00',
            departure: 'LED',
            arrival: 'MOW',
            timeFrom: '06:00:00',
            timeTo: '22:00:00',
        };

        service.getFlightsByRoute(params);
        assertCacheFirst(url, expectedParams);
    });

    it('should call getMock with flight info and formatted date', () => {
        const flightNumber = '0001';
        const carrier = 'SU';
        const date = new Date(2022, 4, 28);
        const url = '/api/flights/v1.1/ru/onlineboard/details';

        const expectedParams = {
            flights: `${carrier}${flightNumber}`,
            dates: '2022-05-28T00:00:00',
        };

        service.getFlightDetails({ flightNumber, carrier, date });
        expect(getMock.calls.mostRecent().args[0]).toBe(url);
        expect(getMock.calls.mostRecent().args[1].params.toString()).toBe(
            new HttpParams({
                fromObject: expectedParams,
            }).toString(),
        );
    });
});
