import { FlightBookingParams } from '@flight-modal/index';
import { LoyaltyInfo, CreditCard, LoyaltyPricingModel, LoyaltyName } from '@flight-modal/index';
import {
  FlightCheckout,
  FlightItinerary,
  Flights,
  FlightSearchResults,
  FlightTripType,
  FlightInterceptApis
} from '@flight-lib/index';
import { Random, Utility, Timeouts } from '@utility-lib/index';
import { faker } from '@faker-js/faker';
import { GuestDetails } from '@support-user/index';
import { FlightsInvoiceValidation } from '@commerce-lib/flights/invoice_validation';
import { StripeValidation } from '@commerce-lib/stripe/stripe_validation';
import { Invoice } from '@commerce-lib/invoice/invoice';
import { Provider_Type, User_Type } from '@support-onboard/index';
import { LoginPage } from '@admin-lib/index';
import { Affiliate } from '@growth-lib/affiliate';

const adminCreds = Cypress.env('newUser').NEW_USER_PASSWORD;

export class FlightUtility {
  static getLoyaltyFlightInfoObject(pricingModel: LoyaltyPricingModel): LoyaltyInfo {
    return {
      name: LoyaltyName.LHG,
      values: {
        pricingModel
      }
    };
  }

  static getDefaultCreditCardInfoForFareLogix(): CreditCard {
    return {
      fullName: 'JMeter',
      givenName: faker.name.firstName(),
      familyName: faker.name.lastName().replace(/'/g, ''),
      number: '5577810000000004',
      expirationMonth: '1',
      expirationYear: '2039',
      cvc: '100'
    };
  }

  static getDefaultCreditCardInfoForVisa(): CreditCard {
    return {
      fullName: 'Visa Card',
      givenName: faker.name.firstName(),
      familyName: faker.name.lastName().replace(/'/g, ''),
      number: '4111111111111111',
      expirationMonth: '1',
      expirationYear: '2025',
      cvc: '100'
    };
  }
  static getDefaultCreditCardInfoForAmex(): CreditCard {
    return {
      fullName: 'Amex Card',
      givenName: faker.name.firstName(),
      familyName: faker.name.lastName().replace(/'/g, ''),
      number: '371449635398431',
      expirationMonth: '1',
      expirationYear: '2025',
      cvc: '1000'
    };
  }
  static getSandboxCreditCardInfoForAmex(): CreditCard {
    return {
      fullName: 'Amex Card',
      givenName: faker.name.firstName(),
      familyName: faker.name.lastName().replace(/'/g, ''),
      number: '345678000000007',
      expirationMonth: '1',
      expirationYear: '2025',
      cvc: '1000'
    };
  }

  static runSearchFlow(flightBookingParams: FlightBookingParams): void {
    Flights.visitFlightSearchPage();
    if (flightBookingParams.tripTileType === 'Personal') {
      Utility.selectTripTileType('Personal');
    }

    FlightUtility.createAndAddGuests(flightBookingParams.guests);
    Flights.verifyFlightSearchOptionsIsAvailable('flight');

    Flights.selectFlightType(flightBookingParams.flightTripType);

    Flights.setLocations(flightBookingParams.locations);
    FlightSearchResults.selectFutureFlightDate();

    Flights.searchFlight();
  }

  static runSearchFlowFormSearchResult(source: string, destination: string): void {
    FlightSearchResults.selectFutureFlightDate();
    FlightSearchResults.setOrigin(source);
    FlightSearchResults.setDestination(destination);
    FlightSearchResults.searchFlight();
  }

  static createAndAddGuests(guests: GuestDetails[] = []): void {
    guests.forEach((guestDetails) => {
      cy.createGuest(guestDetails);
      Flights.selectPersonalTravelerByInput(
        guestDetails.email || `${guestDetails.givenName} ${guestDetails.familyName}`
      );
    });
  }

  static runChooseMockOnewayResultFlow() {
    FlightSearchResults.onewayMockSearchResult();
  }

  static runChooseMockRoundtripResultFlow() {
    FlightSearchResults.roundtripMockSearchResult();
  }

  static runChooseMockMultiCityBundleResultFlow() {
    FlightSearchResults.multiCityBundleMockSearchResult();
  }

  static runChooseResultFlow(flightParams: FlightBookingParams): void {
    cy.allure().logStep(`${flightParams.flightTripType}: Select flights from search list`);
    switch (flightParams.flightTripType) {
      case FlightTripType.ONEWAY:
        FlightSearchResults.onewaySearchResult(flightParams);
        break;
      case FlightTripType.ROUNDTRIP:
        FlightSearchResults.roundtripSearchResult(flightParams);
        break;
      case FlightTripType.MULTICITY_BUNDLE:
        FlightSearchResults.bundleSearchResult(flightParams);
        break;
      case FlightTripType.MULTICITY_CUSTOM:
        FlightSearchResults.multicityFlexSearchResult(flightParams);
        break;
    }
  }

  static runCheckoutFlow(flightBookingParams: FlightBookingParams): void {
    FlightCheckout.waitToPageBeLoaded();

    FlightCheckout.expectNumberOfTravelers(flightBookingParams.guests.length + 1);

    FlightCheckout.createTripInformation();

    FlightCheckout.checkCancellationPolicy();
    FlightCheckout.acceptOutOfPolicyFlight();
    FlightCheckout.validateIfPassportAndVisaInfoRequired();

    if (flightBookingParams.tripTileType === 'Personal') {
      FlightCheckout.skipSeatSelection();
    }

    if (flightBookingParams.tripTileType === 'Personal') {
      FlightCheckout.updateEmailDetails('personal-' + Random.randomString(12) + '@staging-prime.tripactions.xyz');
    }

    FlightCheckout.checkIn(flightBookingParams.checkInType);
    FlightCheckout.updateContactDetails();

    FlightCheckout.expectBookingSummary(
      flightBookingParams.checkOutConfirmText
        ? flightBookingParams.checkOutConfirmText
        : FlightUtility.getNameByType(flightBookingParams.flightTripType)
    );
    FlightCheckout.storeBookingData();
    FlightCheckout.storeCreditCardLastDigits();

    if (flightBookingParams.insurance) {
      cy.wait('@waitForInsurances');
      FlightCheckout.addInsurance();
    }
    FlightCheckout.bookAndPay(flightBookingParams);
    flightBookingParams.insurance && cy.wait('@waitForPostInsurances');
    FlightCheckout.expectFlightSuccessfullyConfirmed(flightBookingParams.flightConfirmText);
  }

  static runItineraryFlow(): void {
    FlightItinerary.viewItineraryPage();
    FlightItinerary.waitToBeLoaded();
  }

  static ticketSabreFlight(): void {
    FlightItinerary.syncAndTicketFlightBooking();
  }

  static syncSabreFlight(): void {
    cy.wait(Timeouts.MEDIUM_TIMEOUT_60_SEC.timeout);
    FlightItinerary.sabreSyncFlightBooking();
  }

  static verifyTripFeeInInvoice(): void {
    FlightsInvoiceValidation.checkInvoiceBookingId();
    FlightsInvoiceValidation.checkInvoiceTAFee();
    //StripeValidation.validateStripeFee();
  }

  static storeFlightBookingInformation(): void {
    FlightsInvoiceValidation.storeFlightTripItineraryTripData();
    FlightsInvoiceValidation.storeTicketNumber();
  }

  static verifyTripFeeSalesTaxDetails(): void {
    FlightsInvoiceValidation.checkInvoiceTripSalesTAXFee();
    FlightsInvoiceValidation.checkInvoicePriceSalesTaxRate();
    FlightsInvoiceValidation.checkInvoicePriceSalesTax();
    StripeValidation.validateStripeFee();
  }
  static verifyTripFeeOnly(): void {
    FlightsInvoiceValidation.storeFlightTripItineraryTripData();
    StripeValidation.validateStripeFee();
  }

  static searchFlowToCheckout(flightParams: FlightBookingParams, isPPBFlight?: boolean): void {
    Flights.visitFlightSearchPage();
    Flights.selectFlightType(flightParams.flightTripType);
    Flights.setOrigin(flightParams.locations[0]);
    Flights.setDestination(flightParams.locations[1]);
    FlightSearchResults.selectFutureFlightDate();
    Flights.searchFlight();
    isPPBFlight && Affiliate.clickOnBenefitPointsToggle();
    FlightSearchResults.onewaySearchResult(flightParams);
    FlightCheckout.waitToPageBeLoaded();
  }

  static getNameByType(tripType: FlightTripType): string {
    switch (tripType) {
      case FlightTripType.ONEWAY:
        return 'One-way';
      case FlightTripType.ROUNDTRIP:
        return 'Roundtrip';
      case FlightTripType.MULTICITY_CUSTOM:
      case FlightTripType.MULTICITY_BUNDLE:
        return 'Multi-city';
      default:
        return 'One-way';
    }
  }

  static isItMultiCityType(tripType: FlightTripType): boolean {
    return [FlightTripType.MULTICITY_BUNDLE, FlightTripType.MULTICITY_CUSTOM].includes(tripType);
  }
  static verifyVoidTransactionInInvoice(): void {
    FlightItinerary.forcePDFSyncAPI();
    Utility.loginAsAdmin(adminCreds);
    cy.task('getDataFromCache', 'ItineraryURL').then((searchURL: any) => {
      cy.visit(searchURL);
    });
    FlightsInvoiceValidation.visitViewTripFeePage();
    Invoice.retrieveDownloadInvoiceFile();
    Invoice.retrieveAndConvertPDFInvoiceDetailsToHTML();
    FlightsInvoiceValidation.checkInvoiceBookingId();
    FlightsInvoiceValidation.checkVoidInvoiceContent();
    Invoice.deleteFileFromFolder();
  }

  static prepareCompanyAndUserCreation(userType: User_Type, providerType: Provider_Type = Provider_Type.SABRE_FLIGHT) {
    FlightInterceptApis.interceptFlightsApis();
    LoginPage.createNewCompanyAndLoginWithUserByType({
      providers: [providerType],
      users: [userType]
    });
  }

  static verifyUnchangeableInvoice(): void {
    FlightItinerary.forcePDFSyncAPI();
    Utility.loginAsAdmin(adminCreds);
    FlightItinerary.goToItineraryPage();
    FlightsInvoiceValidation.visitViewTripFeePage();
    Invoice.retrieveDownloadInvoiceFile();
    Invoice.retrieveAndConvertPDFInvoiceDetailsToHTML();
    FlightsInvoiceValidation.checkInvoiceBookingId();
    FlightsInvoiceValidation.checkUnchangeableInvoiceContent();
  }
  static preCancelDoForcePDF() {
    FlightItinerary.forcePDFSyncAPI();
    Utility.loginAsAdmin(adminCreds);
    FlightItinerary.goToItineraryPage();
    FlightItinerary.waitToBeLoaded();
  }
  static storeItineraryBookingInfo() {
    Utility.loginAsAdmin(adminCreds);
    FlightItinerary.goToItineraryPage();
    FlightItinerary.waitToBeLoaded();
    FlightUtility.storeFlightBookingInformation();
  }
  static getInvoiceAndValidate() {
    FlightsInvoiceValidation.visitViewTripFeePage();
    Invoice.retrieveDownloadInvoiceFile();
    Invoice.retrieveAndConvertPDFInvoiceDetailsToHTML();
    FlightsInvoiceValidation.checkInvoiceBookingId();
    Invoice.deleteFileFromFolder();
  }
}
