import { Flights, FlightTripType } from '@flight-lib/index';
import { LocationUtility, MakeRequiredSomeFields, TripTileType, Utility, verticalType } from '@utility-lib/index';
import { GuestDetails } from '@user-lib/interface/guest-details';
import { FlightReSearchUtility, FlightUtility } from '@flight-modal/index';
import { AmplitudeEvents } from '@growth-lib/amplitude-events';

export type FlightBookingParams = {
  flightTripType: FlightTripType;
  tripTileType: TripTileType;
  locations: string[];
  numberOfLeg: number;
  guests: GuestDetails[];
  continueIfNoResultFound: boolean;
  insurance: boolean;
  verticalType: verticalType;
  flightConfirmText: string;
  checkInType: string | undefined;
  checkOutConfirmText: string | undefined;
  isItEventSearch: boolean;
  countAttempt: number;
  isExchangeFlow?: boolean;
  airportForEventRetryFn: () => string;
  airportsForBaseFlowRetryFn: () => string[];
};

type FlightBookingParamsBase = MakeRequiredSomeFields<FlightBookingParams, 'locations' | 'flightTripType'>;

export class FlightBookingUtility {
  static initFlightBookingParams(bookingParams: FlightBookingParamsBase): FlightBookingParams {
    const defaultAirportFunctions = FlightReSearchUtility.initAirportFnsForBookingParams(bookingParams.flightTripType);
    return {
      locations: bookingParams.locations,
      flightTripType: bookingParams.flightTripType,
      tripTileType: bookingParams.tripTileType || 'Business',
      checkInType: bookingParams.checkInType || undefined,
      checkOutConfirmText: bookingParams.checkOutConfirmText || undefined,
      flightConfirmText: bookingParams.flightConfirmText || 'Flight confirmed',
      verticalType: bookingParams.verticalType || 'flight',
      continueIfNoResultFound: bookingParams.continueIfNoResultFound ?? true,
      guests: bookingParams.guests ?? [],
      insurance: bookingParams.insurance ?? false,
      numberOfLeg: bookingParams.numberOfLeg ?? 2,
      isItEventSearch: bookingParams.isItEventSearch ?? false,
      countAttempt: bookingParams.countAttempt ?? 0,
      airportForEventRetryFn: bookingParams.airportForEventRetryFn ?? defaultAirportFunctions.airportForEventFn,
      airportsForBaseFlowRetryFn:
        bookingParams.airportsForBaseFlowRetryFn ?? defaultAirportFunctions.airportsForBaseFlowFn
    };
  }

  static bookOneWayFlight(tripTileType: TripTileType, guests: GuestDetails[] = []) {
    const flightParams = FlightBookingUtility.initFlightBookingParams({
      locations: LocationUtility.getRandomAcrossUnitedStatesAirports(),
      flightTripType: FlightTripType.ONEWAY,
      tripTileType,
      checkInType: ' Add EarlyBird Check-In® ',
      guests
    });
    FlightBookingUtility.runBookingFlow(flightParams);
  }

  static bookMockOneWayFlight(tripTileType: TripTileType, guests: GuestDetails[] = []) {
    const flightParams = FlightBookingUtility.initFlightBookingParams({
      locations: LocationUtility.getRandomAcrossUnitedStatesAirports(),
      flightTripType: FlightTripType.ONEWAY,
      tripTileType,
      checkInType: ' Add EarlyBird Check-In® ',
      guests
    });
    FlightUtility.runSearchFlow(flightParams);
    FlightUtility.runChooseMockOnewayResultFlow();
    FlightUtility.runCheckoutFlow(flightParams);
    FlightUtility.runItineraryFlow();
  }

  static bookRoundTrip(tripTileType: TripTileType, guests: GuestDetails[] = []) {
    const flightParams = FlightBookingUtility.initFlightBookingParams({
      locations: LocationUtility.getRandomAcrossUnitedStatesAirports(),
      flightTripType: FlightTripType.ROUNDTRIP,
      tripTileType,
      checkInType: ' Continue without EarlyBird Check-In® ',
      guests
    });
    FlightBookingUtility.runBookingFlow(flightParams);
  }

  static bookMockRoundtripFlight(tripTileType: TripTileType, guests: GuestDetails[] = []) {
    const flightParams = FlightBookingUtility.initFlightBookingParams({
      locations: LocationUtility.getRandomAcrossUnitedStatesAirports(),
      flightTripType: FlightTripType.ROUNDTRIP,
      tripTileType,
      checkInType: ' Continue without EarlyBird Check-In® ',
      guests
    });
    FlightUtility.runSearchFlow(flightParams);
    FlightUtility.runChooseMockRoundtripResultFlow();
    FlightUtility.runCheckoutFlow(flightParams);
    FlightUtility.runItineraryFlow();
  }

  static runBookingFlow(flightBookingParams: FlightBookingParams): void {
    FlightUtility.runSearchFlow(flightBookingParams);
    FlightUtility.runChooseResultFlow(flightBookingParams);
    FlightUtility.runCheckoutFlow(flightBookingParams);
    FlightUtility.runItineraryFlow();
  }

  static bookMultiCityTripBundleOrCustom(flightBookingParams: FlightBookingParams) {
    cy.allure().logStep(`Book ${flightBookingParams.flightTripType} trip`);
    Flights.visitFlightSearchPage();
    Flights.verifyFlightSearchOptionsIsAvailable('flight');
    if (flightBookingParams.tripTileType === 'Personal') {
      Utility.selectTripTileType('Personal');
    }
    Flights.selectFlightType(flightBookingParams.flightTripType);
    Flights.setLocations(flightBookingParams.locations);
    Utility.selectFutureDate();
    Flights.searchFlight();
    FlightUtility.runChooseResultFlow(flightBookingParams);
    FlightUtility.runCheckoutFlow(flightBookingParams);
  }

  static bookMockMultiCityBundleFlight() {
    const flightParams = FlightBookingUtility.initFlightBookingParams({
      locations: LocationUtility.getOriginsDestinationsForMultiCity(),
      flightTripType: FlightTripType.MULTICITY_BUNDLE,
      tripTileType: 'Business',
      checkInType: ' Continue without EarlyBird Check-In® '
    });
    Flights.visitFlightSearchPage();
    Flights.verifyFlightSearchOptionsIsAvailable('flight');
    Flights.selectFlightType(FlightTripType.MULTICITY_BUNDLE);
    Flights.setLocations(flightParams.locations);
    Utility.selectFutureDate();
    Flights.searchFlight();
    FlightUtility.runChooseMockMultiCityBundleResultFlow();
    FlightUtility.runCheckoutFlow(flightParams);
    FlightUtility.runItineraryFlow();
  }

  static bookOneWayInsuranceFlight(flightBookingParams: FlightBookingParams) {
    FlightUtility.runSearchFlow(flightBookingParams);
    AmplitudeEvents.addExpectedAmplitudeEvents('homescreen loaded', 'home search flight clicked', 'search flight');
    FlightUtility.runChooseResultFlow(flightBookingParams);
    FlightUtility.runCheckoutFlow(flightBookingParams);
    AmplitudeEvents.addExpectedAmplitudeEvents('load search results filters', 'select flight');
    AmplitudeEvents.addExpectedAmplitudeEvents('create flight contract', 'book flight');
    AmplitudeEvents.expectAmplitudeEventsToBeSent();
  }

  static runBookingFlowRyanairTravelFusion(): void {
    const flightParams = FlightBookingUtility.initFlightBookingParams({
      flightTripType: FlightTripType.ONEWAY,
      locations: ['STN', 'BER']
    });
    Flights.visitFlightSearchPage();
    Flights.selectFlightType(flightParams.flightTripType);
    Flights.setOrigin(flightParams.locations[0]);
    Flights.setDestination(flightParams.locations[1]);
    Utility.selectFutureDate();
    Flights.searchFlight();
    FlightUtility.runChooseResultFlow(flightParams);
    FlightUtility.runCheckoutFlow(flightParams);
    FlightUtility.runItineraryFlow();
  }
}
