import { utilitySelector, Timeouts } from '@utility-lib/index';
import { Interception } from 'cypress/types/net-stubbing';

export const trainSearchResultSelector = {
  priceFare: '.fare-price',
  proceedToCheckoutPageOrCheckout: '[qaid="trainNextButton"]',
  searchResult: '.ta-card',
  fareCards: '.results-container__content__options',
  allFareOptions: '[qaid="trainAllFareOptions"]',
  fareDescription: '.fare-row__fare-info__description',
  changeDate: '[icon="chevron-right"]',
  search: '.search-form-trains__search-row__button',
  outsideOfTravelWindowPopupDismiss: '[data-testid="proceedWithSelectedBooking"]',
  providerPng: (provider: string) => `[src*="/trains/operators/${provider}.png"]`,
  loader: '[viewBox="0 0 50 50"]',
  segmentsDetail: '[class="rail-summary__card-content"] [class="train-change"]',
  submit: '[qaid="trainSelectionSummary"] [qaid="trainNextButton"]',
  trainChange: '[class="train-change"] span',
  taCard: '[class="ta-card"]',
  summarySegment: '[class="rail-summary__segments"]',
  closePopUp: 'button[data-testid="modal-header-close-button"]',
  routeInfoSegment: '[class="route-info"] [class="route-info__duration__segments"]',
  trainClassDescription: '[class^="rail-card__class-tabs__header"]',
  segmentInfo: '.segment-info__operator__train-number',
  closeModal: '[class^="ta-modal-header__close__button"]',
  cardContainer: '.results-container__card-container',
  fareSummaryTrainChange: '[class="rail-summary__segments"] [class="train-change"] span'
};

export class TrainSearchResults {
  static expectSearchResultPresent() {
    cy.get(trainSearchResultSelector.priceFare, Timeouts.MAX_TIMEOUT_120_SEC).should('be.visible');
    cy.allure().logStep('expect search result present');
  }

  static expectProviderIsPresent(provider: string) {
    cy.get(trainSearchResultSelector.providerPng(provider), Timeouts.MAX_TIMEOUT_120_SEC)
      .should('have.attr', 'src')
      .should('include', `${provider}`);
  }

  static openAllFareOptions() {
    cy.get(trainSearchResultSelector.allFareOptions).click({ multiple: true });
    cy.wait(Timeouts.SHORT_TIMEOUT_1_SEC.timeout);
  }

  static chooseFare(fare?: string) {
    cy.get(trainSearchResultSelector.fareDescription)
      .filter((index, element) => Cypress.$(element).text().trim() === fare)
      .eq(0)
      .click({ force: true });
  }

  static selectCorrectFare(fare?: string) {
    this.openAllFareOptions();
    cy.get(utilitySelector.bodySelector).then(($body) => {
      cy.wrap($body);
      if ($body.text().includes(`${fare}`)) {
        this.chooseFare(fare);
      } else {
        this.changeSearchDate(fare);
      }
    });
  }

  static selectRoundTripFare(fare?: string) {
    this.selectCorrectFare(fare);
    this.selectReturn();
    this.selectCorrectFare(fare);
    this.getSegmentDetails();
  }
  static expectNoOfTravelers(noOfTravelers?: string) {
    cy.get(trainSearchResultSelector.searchResult).should('contain', noOfTravelers);
    cy.allure().logStep('expect no of travelers');
  }

  static changeSearchDate(fare?: string) {
    cy.get(trainSearchResultSelector.changeDate).eq(0).click();
    cy.get(trainSearchResultSelector.search).eq(1).click();
    cy.wait('@waitForSearchOrCheckout');
    this.openAllFareOptions();
    cy.get(utilitySelector.bodySelector).then(($body) => {
      cy.wrap($body);
      if ($body.text().includes(`${fare}`)) {
        this.chooseFare(fare);
      } else {
        throw new Error(`>>>>>>>>>> No fare found for ${fare} <<<<<<<<<<`);
      }
    });
  }

  static selectProvider(provider: string) {
    cy.get(trainSearchResultSelector.providerPng(provider)).eq(1).click();
    cy.allure().logStep(`select - ${provider}`);
  }

  static proceedToCheckoutPage() {
    cy.get(trainSearchResultSelector.proceedToCheckoutPageOrCheckout).click();
    this.continueBookingIfOutsideTravelWindows();
    cy.allure().logStep('proceed to checkout page');
    cy.wait('@waitForSearchOrCheckout').then((interception: Interception) => {
      cy.logTaRequestUuid(interception);
    });
    cy.get(trainSearchResultSelector.loader, Timeouts.MEDIUM_TIMEOUT_60_SEC).should('not.exist');
  }

  static selectReturn() {
    cy.get(trainSearchResultSelector.proceedToCheckoutPageOrCheckout).click();
    cy.allure().logStep('selectReturn');
  }

  static continueBookingIfOutsideTravelWindows() {
    cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
    cy.get(utilitySelector.bodySelector).then(($body) => {
      if ($body.find(trainSearchResultSelector.outsideOfTravelWindowPopupDismiss).length > 0) {
        cy.get(trainSearchResultSelector.outsideOfTravelWindowPopupDismiss)
          .contains('Continue with selected train')
          .click();
        cy.allure().logStep('Continue booking when outside of travel window');
      } else {
        cy.log('Booking is within travel window');
        cy.allure().logStep('Booking is within travel window');
      }
    });
  }

  static getSegmentDetails() {
    cy.get(trainSearchResultSelector.segmentsDetail)
      .invoke('text')
      .then((buttonText) => {
        const text = buttonText.trim();
        cy.log('Extracted text:', text);
        cy.task('putDataInCache', {
          key: 'noOfSegmentsFromSearchResults',
          data: text
        });
      });
  }

  static selectTrain(tripType: number) {
    for (let i = 0; i <= tripType; i++) {
      TrainSearchResults.expectSearchResultPresent();
      cy.get(trainSearchResultSelector.submit).click();
      cy.wait(Timeouts.MEDIUM_TIMEOUT_10_SEC.timeout);
    }
  }

  static reviewAndContinueIfOutsideOfTravelWindowChanged() {
    cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
    cy.get(utilitySelector.bodySelector).then(($body) => {
      if ($body.find(trainSearchResultSelector.outsideOfTravelWindowPopupDismiss).length > 0) {
        cy.get(trainSearchResultSelector.outsideOfTravelWindowPopupDismiss)
          .contains('Continue with selected flight')
          .click();
        cy.allure().logStep('Continue booking when outside of travel window');
      } else {
        cy.log('Booking is within travel window');
        cy.allure().logStep('Booking is within travel window');
      }
    });
  }

  static getTrenItaliaAvailableCheckInTrain() {
    TrainSearchResults.expectSearchResultPresent();

    cy.get(trainSearchResultSelector.routeInfoSegment).then((segments: JQuery<HTMLElement>) => {
      checkSegmentsForRVorRE(segments, 0);
    });
    function checkSegmentsForRVorRE(segments: JQuery<HTMLElement>, index: number) {
      if (index >= segments.length) {
        cy.log('------------------>>>>>>>>>>>>>TRAIN RV or RE not found');
        return;
      }

      cy.wrap(segments.eq(index)).click();
      cy.get('body').then(($body) => {
        if ($body.text().includes('RV') || $body.text().includes('RE')) {
          cy.log('------------------>>>>>>>>>>>>>RV or RE found');
          cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
          cy.get(trainSearchResultSelector.closePopUp).click();
          TrainSearchResults.selectTrain(0);
        } else {
          cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
          cy.get(trainSearchResultSelector.closePopUp).click();

          checkSegmentsForRVorRE(segments, index + 1);
        }
      });
    }
  }
}
