import { NO_ERRORS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ScheduleFlightsMiniListComponent } from '@schedule/pages/flight-details/components/flights-mini-list/schedule-flights-mini-list.component';
import { ScheduleHelpersService } from '@schedule/services/schedule-helpers.service';
import { ScheduleItemModel } from '@shared/models-legacy';
import { RouteType } from '@typings/enums';

describe('ScheduleFlightsMiniListComponent', () => {
    let fixture: ComponentFixture<ScheduleFlightsMiniListComponent>;
    let component: ScheduleFlightsMiniListComponent;
    let scheduleInput: ScheduleItemModel[];

    const firstDate = new Date(2022, 4, 27);
    const secondDate = new Date(2022, 4, 28);
    const thirdDate = new Date(2022, 4, 29);

    const getFirstScheduleDayToAddMock = jasmine.createSpy(
        'getFirstScheduleDayToAdd',
    );
    const getLastScheduleDayToAddMock = jasmine.createSpy(
        'getLastScheduleDayToAdd',
    );
    const emitOpenMock = jasmine.createSpy('open.emit');

    beforeEach(async () => {
        await TestBed.configureTestingModule({
            declarations: [ScheduleFlightsMiniListComponent],
            providers: [
                {
                    provide: ScheduleHelpersService,
                    useValue: {
                        getFirstScheduleDayToAdd: getFirstScheduleDayToAddMock,
                        getLastScheduleDayToAdd: getLastScheduleDayToAddMock,
                    },
                },
            ],
            schemas: [NO_ERRORS_SCHEMA],
        }).compileComponents();
    });

    beforeEach(() => {
        fixture = TestBed.createComponent(ScheduleFlightsMiniListComponent);
        component = fixture.componentInstance;

        (component.open as any) = {
            emit: emitOpenMock,
        };

        component.flight = {
            routeType: RouteType.DIRECT,
            pId: '1',
            dateToSearchBy: secondDate,
        } as any;

        scheduleInput = [
            new ScheduleItemModel({
                flights: [],
                date: firstDate,
            }),
            new ScheduleItemModel({
                flights: [],
                date: secondDate,
            }),
            new ScheduleItemModel({
                flights: [],
                date: thirdDate,
            }),
        ];

        getFirstScheduleDayToAddMock.calls.reset();
        getLastScheduleDayToAddMock.calls.reset();
    });

    it('should not set initial date because flight is not provided', () => {
        component.flight = undefined;
        component.ngOnChanges({ flight: {} as any });
        expect(component.initialDate).toBe(undefined);
    });

    it('should return flight date because _initialDate is not set yet', () => {
        expect(component.initialDate).toBe(secondDate);
    });

    it('should return _initialDate', () => {
        component.ngOnChanges({ flight: {} as any });
        component.flight = {
            dateToSearchBy: firstDate,
        } as any;
        expect(component.initialDate).toBe(secondDate);
    });

    it('should not add days two schedule', () => {
        component.scheduleInput = scheduleInput;
        component.ngOnChanges({
            flight: {} as any,
            scheduleInput: {} as any,
        });
        expect(component.scheduleInput).toEqual(scheduleInput);
    });

    it('should add past day', () => {
        const newInput = [scheduleInput[1], scheduleInput[2]];
        getFirstScheduleDayToAddMock
            .withArgs(newInput)
            .and.returnValue(scheduleInput[0]);

        component.scheduleInput = newInput;
        component.ngOnChanges({
            flight: {} as any,
            scheduleInput: {} as any,
        });
        expect(component.schedule).toEqual(scheduleInput);
    });

    it('should add future day', () => {
        const newInput = [scheduleInput[0], scheduleInput[1]];
        getLastScheduleDayToAddMock
            .withArgs(newInput)
            .and.returnValue(scheduleInput[2]);

        component.scheduleInput = newInput;
        component.ngOnChanges({
            flight: {} as any,
            scheduleInput: {} as any,
        });
        expect(component.schedule).toEqual(scheduleInput);
    });

    it('shouldShowAccordion true if schedule length is more than 1', () => {
        expect(component.shouldShowAccordion).toBe(false);

        component.scheduleInput = [scheduleInput[0]];
        component.ngOnChanges({
            scheduleInput: {} as any,
        });
        expect(component.shouldShowAccordion).toBe(false);

        component.scheduleInput = scheduleInput;
        component.ngOnChanges({
            scheduleInput: {} as any,
        });
        expect(component.shouldShowAccordion).toBe(true);
    });

    it('should return true if items date equals to initialDate', () => {
        component.ngOnChanges({
            flight: {} as any,
        });
        expect(component.isInitiallySelected(scheduleInput[0])).toBe(false);
        expect(component.isInitiallySelected(scheduleInput[1])).toBe(true);
    });

    it('should return true if flights have same pIds', () => {
        expect(
            component.isFlightSelected({
                routeType: RouteType.DIRECT,
                pId: '2',
            } as any),
        ).toBe(false);
        expect(
            component.isFlightSelected({
                routeType: RouteType.DIRECT,
                pId: '1',
            } as any),
        ).toBe(true);
    });

    it('should emit provided flight', () => {
        const flight = { pId: '1' } as any;
        component.openFlight(flight);

        expect(emitOpenMock).toHaveBeenCalledWith(flight);
    });

    it('should not do anything', () => {
        component.flight = undefined;
        component.ngOnChanges({});

        expect(component.initialDate).toBe(undefined);
        expect(component.schedule).toBe(undefined);
        expect(getLastScheduleDayToAddMock).not.toHaveBeenCalled();
        expect(getFirstScheduleDayToAddMock).not.toHaveBeenCalled();
    });
});
