import { HttpParams } from '@angular/common/http';
import { TestBed } from '@angular/core/testing';
import {
    IScheduleRequestParams,
    ScheduleApiService,
} from '@schedule/services/api.service';
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('ScheduleApiService', () => {
    let service: ScheduleApiService;
    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: [
                ScheduleApiService,
                ApiFormatterService,
                EndpointService,
                {
                    provide: ApiService,
                    useValue: mockApiService,
                },
                {
                    provide: LocalizationService,
                    useValue: {
                        Language: 'ru',
                    },
                },
            ],
        });

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

    function assertCacheFirst(url: string, expectedParams: any) {
        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 valid params without time range', () => {
        const requestParams: IScheduleRequestParams = {
            dateFrom: new Date(2022, 4, 23),
            dateTo: new Date(2022, 4, 29),
            departure: 'MOW',
            arrival: 'LED',
        };
        const url = '/api/flights/1/ru/schedule';

        const expectedParams = {
            dateFrom: '2022-05-23T00:00:00',
            dateTo: '2022-05-29T00:00:00',
            departure: 'MOW',
            arrival: 'LED',
            connections: '1',
            attribute: '1',
        };

        service.getFlights(requestParams, 1);
        assertCacheFirst(url, expectedParams);

        service.getFlights(requestParams, 2);
        assertCacheFirst(url, { ...expectedParams, attribute: '2' });
    });

    it('should call cacheFirst with valid params with time range', () => {
        const requestParams: IScheduleRequestParams = {
            dateFrom: new Date(2022, 4, 23),
            dateTo: new Date(2022, 4, 29),
            departure: 'MOW',
            arrival: 'LED',
            timeFrom: '0630',
            timeTo: '2200',
            connections: 0,
        };

        const url = '/api/flights/1/ru/schedule';
        const expectedParams = {
            dateFrom: '2022-05-23T00:00:00',
            dateTo: '2022-05-29T00:00:00',
            departure: 'MOW',
            arrival: 'LED',
            timeFrom: '06:30:00',
            timeTo: '22:00:00',
            connections: '0',
        };

        service.getFlights(requestParams);
        assertCacheFirst(url, expectedParams);
    });

    it('should call get with valid params', () => {
        const flightsInfo = ['SU0001', 'SU0002'];
        const dates = [new Date(2022, 4, 27), new Date(2022, 4, 28)];
        const expectedParams = {
            'dates[0]': '2022-05-27T00:00:00',
            'dates[1]': '2022-05-28T00:00:00',
            'flights[0]': 'SU0001',
            'flights[1]': 'SU0002',
            'departure': 'MOW',
            'arrival': 'LED',
        };
        const url = '/api/flights/v1.1/ru/schedule/details';

        service.getFlightDetails(flightsInfo, dates, 'MOW', 'LED');
        expect(getMock.calls.mostRecent().args[0]).toBe(url);
        expect(getMock.calls.mostRecent().args[1].params.toString()).toBe(
            new HttpParams({
                fromObject: expectedParams,
            }).toString(),
        );
    });
});
