import { HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { ApiService } from '@shared/services/api/api.service';
import { EndpointService } from '@shared/services/api/endpoint.service';
import { ApiFormatterService } from '@shared/services/api/formatter.service';
import { IParsedFlightId } from '@typings/flight/flight-id';
import { IBoardResponse, IDaysResponse } from '@typings/responses';
import { IOnlineBoardRoutePageUrlParams } from './url/types';

type IRouteRequestOptions = {
    dateFrom: string;
    dateTo: string;
    departure?: string;
    arrival?: string;
    timeFrom?: string;
    timeTo?: string;
};

type IFlightNumberRequestOptions = {
    flights: string;
    dates: string;
};

@Injectable()
export class OnlineBoardApiService {
    constructor(
        private apiService: ApiService,
        private apiFormatter: ApiFormatterService,
        private endpointService: EndpointService,
    ) {}

    public getFlightsByFlightNumber(
        requestParams: IParsedFlightId,
    ): Promise<IBoardResponse> {
        const params = new HttpParams({
            fromObject: {
                flightNumber: `${requestParams.carrier}${requestParams.flightNumber}${requestParams.suffix}`,
                date: this.apiFormatter.formatDate(requestParams.date),
            },
        });

        return this.getFlights(params);
    }

    public getFlightsByRoute(
        requestParams: IOnlineBoardRoutePageUrlParams,
    ): Promise<IBoardResponse> {
        const date = this.apiFormatter.formatDate(requestParams.date);
        const dateTill = this.apiFormatter.formatDate(this.addDays(requestParams.date, 1));
        this.addDays(requestParams.date, -1);

        const queryStringParams: IRouteRequestOptions = {
            dateFrom: date,
            dateTo: dateTill,
            departure: requestParams.departure,
            arrival: requestParams.arrival,
            ...this.formatTimeRange(
                requestParams.timeFrom,
                requestParams.timeTo,
            ),
        };

        let params = new HttpParams({
            fromObject: queryStringParams,
        });

        if (!requestParams.departure) {
            params = params.delete('departure');
        }

        if (!requestParams.arrival) {
            params = params.delete('arrival');
        }

        if (!requestParams.timeTo || !requestParams.timeFrom) {
            params = params.delete('timeTo').delete('timeFrom');
        }

        return this.getFlights(params);
    }

    public getFlightDetails(params: IParsedFlightId): Promise<IBoardResponse> {
        const date = this.apiFormatter.formatDate(params.date);
        const flightInfo = `${params.carrier}${params.flightNumber}`;

        const url = this.endpointService.buildLocalizedURL(
            'onlineboard/details',
        );
        const queryStringParams: IFlightNumberRequestOptions = {
            flights: flightInfo,
            dates: date,
        };

        const httpParams = new HttpParams({
            fromObject: queryStringParams,
        });

        return this.apiService
            .get<IBoardResponse>(url, { params: httpParams })
            .toPromise();
    }

    public getFlightDaysByNumber(date: Date, flightNumber: string): Promise<IDaysResponse> {
        const formatDate = this.apiFormatter.formatDate(date);

        const url = this.endpointService.buildLocalizedURL(
            `days/${formatDate}/31/flight/SU${flightNumber}/board/`, // `days/${formatDate}/16/flight/SU${flightNumber}/board`  расширено до 31, чтобы при нахождении на сайте нескольких дней актуальность календаря 
            'v1',                                             // сохранялась по заранее запрошенным данным (не делать автообновление, возможно на будущую доработку по автообновлению)
        );
        console.log(url);
        const httpParams = new HttpParams({
        });

        return this.apiService
            .get<IDaysResponse>(url, { params: httpParams })
            .toPromise();
    }

    public getFlightDaysByRoute(date: Date, src: string, dest: string): Promise<IDaysResponse> {
        const formatDate = this.apiFormatter.formatDate(date);

        const param = src ? (dest ? `route/${src}-${dest}` : `departure/${src}`) : `arrival/${dest}`;

        const url = this.endpointService.buildLocalizedURL(
            `days/${formatDate}/31/${param}/board/`, // `days/${formatDate}/16/${param}/board/`   расширено до 31, чтобы при нахождении на сайте нескольких дней актуальность календаря 
            'v1',                             // сохранялась по заранее запрошенным данным (не делать автообновление, возможно на будущую доработку по автообновлению)
        );
        console.log(url);
        const httpParams = new HttpParams({
        });

        return this.apiService
            .get<IDaysResponse>(url, { params: httpParams })
            .toPromise();
    }


    private formatTimeRange(timeFrom?: string, timeTo?: string) {
        return {
            timeFrom: this.apiFormatter.formatTime(timeFrom),
            timeTo: this.apiFormatter.formatTime(timeTo),
        };
    }

    private getFlights(params: HttpParams): Promise<IBoardResponse> {
        const url = this.endpointService.buildLocalizedURL('board');

        return this.apiService.cacheFirst<IBoardResponse>(url, params);
    }

    private addDays(date: Date, days: number): Date {
        date.setDate(date.getDate() + days);
        return date;
    }
}
