import {
  Logs,
  verticalType,
  Utility,
  utilitySelector,
  Timeouts
} from '@utility-lib/index';
import { PolicyVertical } from '@support-policy/index';

export const flightSearchSelector = {
  dropDownButton: '.ta-select',
  advancedDropdownButton: '[class^="advanced-dropdown"]', // todo(hao): use qaId
  flightSearchField: '[aria-label="Flights"]',
  locationInput: '[class^="ta-airport-search"] input',
  airportDropdownItem: '[class^="ta-airport-search-v2__item"]',
  flightSearchButton: 'button[icon="search"]',
  selectFlightClass: '.fare-card__fare-name__title',
  flightTab: '[aria-label="Flights"]',
  flightTitle: '.flight-card-title',
  flightClass: '.fare-card__fare-name__title',
  travelers: '[qaid="flightPassengers"]',
  travellerInput: '[name="inputSearch"]',
  personalTravellerInput: '.ta-user-search-personal-group',
  flightSearchGuestButton: 'button.search-form-flight__button',
  travellerDropDown: '[class^="ta-user-search-v2__item"]',
  personalTravellerDropDown: '.ta-user-search-personal-list__email',
  userSelectModal: '[class^="user-group-v2__user-selector"]',
  personalUserSelectModal: '.ta-button__background',
  addAnotherFlightButton: '.search-form-x-v2__bot__policy',
  swapFlightDirection: '[aria-label="Swap origin and destination"]',
  warningMsg: '[class^="ta-toastr-event__message"]',
  flightEventSearch: '[class^="home-flight__button"] .ta-button__content',
  location: '.ta-airport-search-v2__item > :nth-child(2)',
  guestSearchButton: 'button[class^="home-flight__button ta-button"] .ta-button__content',
  travelerInput:
    '[class="user-group-v2 user-group-v2--with-users-rebranded"] .ta-chevron-toggle',
  personalTravelerInput:
    '[class="user-group-v2 user-group-v2--with-users-rebranded"] .user-group-v2__title',
  homeButton: '[data-qaid="HOME-button"]',
  upcomingTripCard: '.special-trip-card__trip',
  upcomingTripName: '.special-trip-card__trip__info--name',
  upcomingTripType: 'ta-special-trip-card .trip-type-tag',
  upcomingTripDate: '.special-trip-card__trip__info--header span',
  upcomingTripImage: '.special-trip-card__trip__img',
  upcomingTripManage: '.special-trip-card__trip__info--action button',
  hotelSuggestion: 'ta-hotel-upsell .ta-button__content',
  notNow: '.hotel-upsell__action__cancel span',
  popoverContentValue: (value: string) => `.popover-content [value="${value}"]`,
  addLoyaltyProgram: '[qaid="Add flight loyalty"]',
  searchLoyaltyCard: '[qaid="searchLoyalty"]',
  loyaltyProgram: '[class="ta-loyalty-card-modal__list-item-content"]',
  loyaltyCardNumber: '[formcontrolname="loyaltyNumber"]',
  saveLoyaltyCard: '[qaid="addLoyaltyCard"]'
};

export enum FlightTripType {
  ONEWAY = 'ONEWAY',
  ROUNDTRIP = 'ROUNDTRIP',
  MULTICITY_BUNDLE = 'MULTICITY',
  MULTICITY_CUSTOM = 'MULTICITY_CUSTOM'
}

export class Flights {
  static visitFlightSearchPage() {
    Utility.visitSearchPage();
    Utility.selectVertical('flight');
  }

  static selectFlightType(value: FlightTripType) {
    const flightTripType =
      value === FlightTripType.MULTICITY_CUSTOM ? FlightTripType.MULTICITY_BUNDLE : value;
    cy.allure().logStep(`select flight type is ${flightTripType}`);
    this.selectFromDropDown(flightTripType);
    if (value === FlightTripType.MULTICITY_CUSTOM) {
      this.switchToMultiCityFlex();
    }
  }

  static selectFromDropDown(value: FlightTripType) {
    cy.get(flightSearchSelector.dropDownButton).click();
    cy.get(flightSearchSelector.popoverContentValue(value)).click();
  }

  static switchToMultiCityFlex() {
    cy.get(flightSearchSelector.advancedDropdownButton).click();
    cy.get(flightSearchSelector.popoverContentValue('CUSTOM')).click();
  }

  static checkUpcomingTrip() {
    cy.allure().logStep('Check special trip card is available on home page');
    cy.get(flightSearchSelector.homeButton).click();
    cy.wait('@waitForFlightSearch');
    cy.get(flightSearchSelector.upcomingTripCard).should('be.visible');
    cy.get(flightSearchSelector.upcomingTripName).should('be.visible');
    cy.get(flightSearchSelector.upcomingTripDate).should('be.visible');
    cy.get(flightSearchSelector.upcomingTripType).should('be.visible');
    cy.get(flightSearchSelector.upcomingTripImage).should('be.visible');
    cy.get(flightSearchSelector.hotelSuggestion).should('be.visible');
    cy.get(flightSearchSelector.upcomingTripManage).should('be.visible').click();
  }

  static searchWithLocations(locations: string[]) {
    Flights.setOrigin(locations[0]);
    Flights.setDestination(locations[1]);
    Flights.searchFlight();
  }

  static verifyFlightSearchOptionsIsAvailable(vertical: verticalType) {
    cy.allure().logStep('expect flight search tab visible');
    cy.get(utilitySelector.dataTestID(vertical)).should('be.visible');
  }

  static setOrigin(location: string) {
    cy.allure().logStep(`select origin - ${location}`);
    this.location(`${location}`, 0);
  }

  static setDestination(location: string) {
    cy.allure().logStep(`select destination - ${location}`);
    this.location(`${location}`, 1);
  }

  static setLocations(locations: string[]): void {
    cy.get(flightSearchSelector.locationInput).then((elements) => {
      const numberOfFlight = locations.length - 1;
      const numberOfFlightToAdd = numberOfFlight - elements.length / 2;
      for (let i = 0; i < numberOfFlightToAdd; i++) {
        cy.get(flightSearchSelector.addAnotherFlightButton).click();
      }
    });
    locations.forEach((location, index) => {
      cy.allure().logStep(`select location ${index} - ${location}`);
      if (index === 0 || index === 1) {
        this.setAirport(`${location}`, index);
      } else {
        this.setAirport(`${location}`, index * 2 - 1);
      }
    });
  }

  static setAirport(airport: string, index: number) {
    cy.get(flightSearchSelector.locationInput)
      .eq(index)
      .then((ele) => {
        cy.wrap(ele).clear();
        cy.wrap(ele).type(`${airport}`);
      });

    cy.get(
      flightSearchSelector.airportDropdownItem,
      Timeouts.MEDIUM_TIMEOUT_30_SEC
    ).should('be.visible');
    cy.get(flightSearchSelector.airportDropdownItem).eq(0).trigger('click', {
      force: true
    });
  }

  static setFinalDestination(location: string) {
    cy.allure().logStep(`select final destination - ${location}`);
    this.location(`${location}`, 3);
  }

  // todo(hao): deprecate this function, do not hardcode wait
  static location(location: string, index: number) {
    cy.get(flightSearchSelector.locationInput)
      .eq(index)
      .then((ele) => {
        cy.wrap(ele).clear();
        cy.wrap(ele).type(`${location}`);
        cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
      });

    cy.get(utilitySelector.bodySelector).then(() => {
      cy.get(utilitySelector.ariaLabel(location.substring(0, 3))).trigger('click', {
        force: true
      });
    });
  }

  static getValueFromLocationInput(index: number) {
    return cy.get(flightSearchSelector.locationInput).eq(index).invoke('val');
  }

  static searchFlight(eventSearch = false) {
    cy.allure().logStep('search flight');
    eventSearch
      ? cy.get(flightSearchSelector.flightEventSearch).click({ force: true })
      : cy.get(flightSearchSelector.flightSearchButton).click();
    cy.wait('@waitForFlightSearch');
  }

  static searchFlightGuest() {
    cy.allure().logStep('search flight');
    cy.get(flightSearchSelector.guestSearchButton).contains('Search').click();
    cy.wait('@waitForFlightSearch');
  }

  static clickSearchGuestButton() {
    cy.get(flightSearchSelector.flightSearchGuestButton).contains('Search').click();
  }

  static createFlightPolicy(policyVertical?: PolicyVertical) {
    cy.allure().logStep('create flight policy');
    cy.createFlightPolicy(policyVertical);
  }

  static selectTravelerByInput(input: string) {
    cy.allure().logStep('set traveller');
    cy.get(flightSearchSelector.travelerInput).click({ force: true });
    cy.get(flightSearchSelector.travellerInput).type(input);
    cy.wait('@waitForTravellers').then((xhr) => {
      Logs.cypressResponseLog('TRAVELERS RESPONSE', xhr);
    });
    cy.get(flightSearchSelector.travellerDropDown).eq(0).click({ force: true });
    cy.get(flightSearchSelector.userSelectModal).should('be.visible');
    cy.get(utilitySelector.closeTravelerInputModal).click({ force: true });
  }

  static selectPersonalTravelerByInput(input: string) {
    cy.allure().logStep('set traveller');
    cy.get(flightSearchSelector.personalTravelerInput).click();
    cy.get(flightSearchSelector.personalTravellerInput).type(input);
    cy.wait('@waitForPersonalTravellers').then((xhr) => {
      Logs.cypressResponseLog('TRAVELERS RESPONSE', xhr);
    });
    cy.get(flightSearchSelector.personalTravellerDropDown).eq(0).click({ force: true });
    cy.get(utilitySelector.closePersonalTravelerInputModal).contains('Done').click();
  }

  static getTripUuidFromSearchUrlAndCache() {
    cy.url().then((url: string) => {
      expect(url, 'page url should include search part').include('/search');
      const match = url.match('tripUuid=([^&]*)');
      const tripUuid = match && match[1];
      expect(tripUuid, 'tripUuid should be in url query').not.be.null;
      cy.task('putDataInCache', {
        key: 'tripUuid',
        data: tripUuid
      });
    });
  }

  static SpecialTripCardDisappearOnClickNotNow() {
    cy.allure().logStep(
      'Check special trip card disappear from home page after clicking not now'
    );
    cy.wait('@invoice');
    cy.get(flightSearchSelector.homeButton).click();
    cy.wait('@waitForFlightSearch');
    cy.get(flightSearchSelector.notNow).then((ele) => {
      cy.wrap(ele).should('be.visible').click();
      cy.wrap(ele).should('not.be.visible');
    });
  }

  static addLoyaltyCard(programName: string, loyaltyNumber: string) {
    cy.get(flightSearchSelector.addLoyaltyProgram).click();
    cy.get(flightSearchSelector.searchLoyaltyCard).type(programName);
    cy.wait(Timeouts.SHORT_TIMEOUT_2_SEC.timeout);
    cy.get(flightSearchSelector.loyaltyProgram).contains(programName).click();
    cy.get(flightSearchSelector.loyaltyCardNumber).type(loyaltyNumber);
    cy.get(flightSearchSelector.saveLoyaltyCard).click();
    cy.wait('@waitForLoyaltyPrograms');
  }
}
