import { NO_ERRORS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ActivatedRoute } from '@angular/router';
import { OnlineBoardFlightNumberFilterValidationService } from '@online-board/components/filter/components/flight-number-filter/services/online-board-flight-number-filter-validation.service';
import { IOnlineBoardRouteData } from '@online-board/types';
import { getMockPipe } from '@shared/pipes/pipe.mock';
import { OnlineBoardFiltersStateService } from '@shared/services/filters/online-board-filters-state.service';
import { UserLocationService } from '@shared/services/user-location/user-location.service';
import { getUserLocationServiceMock } from '@shared/services/user-location/user-location.service.mock';
import { BehaviorSubject } from 'rxjs';

import { OnlineBoardFlightNumberFilterComponent } from './flight-number-filter.component';

describe('FlightNumberFilterComponent', () => {
    let component: OnlineBoardFlightNumberFilterComponent;
    let fixture: ComponentFixture<OnlineBoardFlightNumberFilterComponent>;
    let locationService;
    const data: IOnlineBoardRouteData = {
        urlParams: {},
    };

    beforeEach(async () => {
        locationService = getUserLocationServiceMock('MOW');

        await TestBed.configureTestingModule({
            declarations: [
                OnlineBoardFlightNumberFilterComponent,
                getMockPipe('translate'),
            ],
            providers: [
                OnlineBoardFlightNumberFilterValidationService,
                OnlineBoardFiltersStateService,
                {
                    provide: UserLocationService,
                    useValue: locationService,
                },
                {
                    provide: ActivatedRoute,
                    useValue: {
                        data: new BehaviorSubject(data),
                    },
                },
            ],
            schemas: [NO_ERRORS_SCHEMA],
        }).compileComponents();
    });

    beforeEach(() => {
        fixture = TestBed.createComponent(
            OnlineBoardFlightNumberFilterComponent,
        );
        component = fixture.componentInstance;
        data.urlParams = undefined;

        jasmine.clock().install();
    });

    afterEach(() => {
        jasmine.clock().uninstall();
    });

    it('should add zeros to flight number', () => {
        component.flightNumber = '1';
        component.addZeros();
        expect(component.flightNumber).toBe('0001');
    });

    it('should clear flight number', () => {
        component.flightNumber = '0001';
        component.clearInput();
        expect(component.flightNumber).toBe(undefined);
    });

    it('should emit valid params', () => {
        const flightNumber = '0001';
        const date = new Date(2022, 5, 6);

        component.onSearch.emit = jasmine.createSpy('onSearch.emit');
        component.flightNumber = flightNumber;
        component.date = date;
        component.search();

        expect(component.onSearch.emit).toHaveBeenCalledWith({
            flightNumber,
            carrier: 'SU',
            date,
        });
    });

    it('should not emit invalid params', () => {
        const flightNumber = '0001';
        const date = new Date('invalid');

        component.onSearch.emit = jasmine.createSpy('onSearch.emit');
        component.flightNumber = flightNumber;
        component.date = date;
        component.search();

        expect(component.onSearch.emit).not.toHaveBeenCalled();
    });

    it('should set state on init', () => {
        data.urlParams = {
            flightNumber: {
                flightNumber: '0001',
                carrier: 'SU',
                date: new Date(2022, 5, 6),
            },
        };

        expect(component.flightNumber).toBe(undefined);
        expect(component.date).toBe(undefined);

        component.ngOnInit();

        expect(component.flightNumber).toBe('0001');
        expect(component.date).toEqual(new Date(2022, 5, 6));
    });

    it('should not set state on init if urlParams were not provided', () => {
        data.urlParams = undefined;
        const setStateMock = jasmine.createSpy('setState');
        (component as any).setState = setStateMock;
        component.ngOnInit();

        expect(setStateMock).not.toHaveBeenCalled();
    });

    it('should not set state on init if there was no flightNumber field in urlParams', () => {
        data.urlParams = {};
        const setStateMock = jasmine.createSpy('setState');
        (component as any).setState = setStateMock;
        component.ngOnInit();

        expect(setStateMock).not.toHaveBeenCalled();
    });

    it('should set default state on init if geolocation is permitted', () => {
        const mockedToday = new Date(2022, 4, 28);
        expect(component.flightNumber).toBe(undefined);
        expect(component.date).toBe(undefined);

        jasmine.clock().mockDate(mockedToday);
        locationService.locate();
        component.ngOnInit();

        expect(component.flightNumber).toBe(undefined);
        expect(component.date.toDateString()).toBe(mockedToday.toDateString());
    });

    it('should not set default state on init if geolocation is not permitted', () => {
        component.ngOnInit();

        expect(component.flightNumber).toBe(undefined);
        expect(component.date).toBe(undefined);
    });
});
