import {
  TrainSearchModalUtil,
  TrainTripType,
  TrainSearchResults,
  trainSearchResultSelector,
  CheckoutModal,
  TrainBookings
} from '@train-lib/index';
import { Timeouts } from '@utility-lib/constants';
import { utilitySelector } from '@utility-lib/utility';

interface BookingStandardOptions {
  tripType: TrainTripType;
  origin: string;
  destination: string;
  fareType: string[];
  corporateDiscount?: boolean;
  multipleTravelers?: boolean;
  noOfTravelers?: number;
  guestTraveler?: boolean;
}

interface StandardCLassTripOptions {
  tripType: TrainTripType;
  corporateDiscount?: boolean;
  fareType: string[];
  multipleTravelers?: boolean;
  noOfTravelers?: number;
  loyaltyCard?: boolean;
}

interface BookingFirstClassOptions {
  tripType: TrainTripType;
  origin: string;
  destination: string;
  trainClass: boolean;
  fareType: string[];
  isConcierge?: boolean;
  corporateDiscount?: boolean;
  SeatMap?: boolean;
}

interface FirstClassTripOptions {
  tripType: TrainTripType;
  fareType: string[];
  corporateDiscount?: boolean;
  trainClass?: boolean;
}

export class TrainBookingManager {
  static createStandardTrainBooking(options: BookingStandardOptions) {
    const {
      tripType,
      origin,
      destination,
      corporateDiscount = false,
      fareType = [],
      multipleTravelers = false,
      guestTraveler = false,
      noOfTravelers = 1
    } = options;
    TrainSearchModalUtil.executeTrainSearch({
      origin,
      destination,
      tripType,
      dbSeat: false,
      multipleTravelers,
      guestTraveler
    });
    this.selectStandardFareAndProcessForCheckout({
      tripType,
      corporateDiscount,
      fareType,
      noOfTravelers
    });
    CheckoutModal.checkout({
      multipleTravelers,
      noOfTravelers
    });
  }

  static selectStandardFareAndProcessForCheckout(options: StandardCLassTripOptions) {
    const { tripType, fareType = [], loyaltyCard } = options;
    TrainSearchResults.expectSearchResultPresent();
    if (loyaltyCard) {
      cy.log('Loyalty card is present');
      cy.get('[icon="rail-card-filled"]').should('be.visible');
    }

    if (tripType === TrainTripType.ONEWAY || tripType === TrainTripType.ROUND_TRIP) {
      cy.log('====:::>>>>  select Standard Fare <<<<::::====');
      this.selectStandardFare(tripType, fareType);
      TrainSearchResults.proceedToCheckoutPage();
    } else {
      return false;
    }
  }

  static selectStandardFare(tripType: TrainTripType, fareType: string[], corporateDiscount = false) {
    const selectFare = (fare: string) => {
      cy.log(`=====::::>>>> ${fare} fare found in the search results <<<<::::=====`);
      cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
      TrainSearchResults.chooseFare(fare);
    };

    const selectAndReturnFare = () => {
      cy.get(trainSearchResultSelector.allFareOptions).click({ multiple: true });
      cy.wait(Timeouts.SHORT_TIMEOUT_1_SEC.timeout);
      fareType.forEach((fare: string) => {
        cy.get(utilitySelector.bodySelector).then(($body) => {
          if ($body.text().includes(fare)) {
            selectFare(fare);
          } else {
            cy.log(`=====::::>>>> ${fare} fare not found in the search results <<<<::::=====`);
          }
        });
      });
    };

    cy.log('====:::>>>>  check fare  <<<<::::====');
    TrainSearchResults.expectSearchResultPresent();

    if (tripType === TrainTripType.ONEWAY) {
      if (corporateDiscount) {
        TrainBookings.expectCompanyPreferredFareIsPresent();
      }
      cy.log('====:::>>>> select Standard Fare <<<<::::====');
      selectAndReturnFare();
    } else if (tripType === TrainTripType.ROUND_TRIP) {
      selectAndReturnFare();
      TrainSearchResults.selectReturn();
      cy.wait(Timeouts.MEDIUM_TIMEOUT_10_SEC.timeout);
      if (corporateDiscount) {
        TrainBookings.expectCompanyPreferredFareIsPresent();
      }
      TrainSearchResults.expectSearchResultPresent();
      selectAndReturnFare();
    }
  }

  static createFirstClassBooking(options: BookingFirstClassOptions) {
    const {
      tripType,
      origin,
      destination,
      corporateDiscount = false,
      trainClass,
      fareType = [],
      SeatMap = false
    } = options;
    TrainSearchModalUtil.executeTrainSearch({
      origin,
      destination,
      tripType,
      dbSeat: false
    });
    this.selectCancelOrExchangeTripAndProcessForCheckout({
      tripType,
      corporateDiscount,
      trainClass,
      fareType
    });
    CheckoutModal.checkout({ seatMap: SeatMap, tripType });
  }

  static selectCancelOrExchangeTripAndProcessForCheckout(options: FirstClassTripOptions) {
    const { tripType, trainClass, fareType = [] } = options;
    TrainSearchResults.expectSearchResultPresent();
    if ((tripType === TrainTripType.ONEWAY || tripType === TrainTripType.ROUND_TRIP) && trainClass) {
      this.selectFirstClassFare(tripType, fareType);
      TrainSearchResults.proceedToCheckoutPage();
    }
  }

  static selectFirstClassFare(tripType: TrainTripType, fareType: string[]) {
    const selectFare = (fare: string) => {
      cy.log(`=====::::>>>> ${fare} fare found in the search results <<<<::::=====`);
      cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
      TrainSearchResults.chooseFare(fare);
      return false;
    };

    const selectAndReturnFare = () => {
      cy.get(trainSearchResultSelector.allFareOptions).click({ multiple: true });
      cy.wait(Timeouts.SHORT_TIMEOUT_1_SEC.timeout);
      cy.log('selectFirstClassFare');
      cy.get('.rail-card__class-tabs__tab.ng-star-inserted:nth-child(2)').click({
        multiple: true
      });
      fareType.forEach((fare: string) => {
        cy.get(utilitySelector.bodySelector).then(($body) => {
          if ($body.text().includes(fare)) {
            return selectFare(fare);
          } else {
            cy.log(`=====::::>>>> ${fare} fare not found in the search results <<<<::::=====`);
            return false;
          }
        });
      });
    };

    TrainSearchResults.expectSearchResultPresent();
    if (tripType === TrainTripType.ONEWAY) {
      selectAndReturnFare();
    } else if (tripType === TrainTripType.ROUND_TRIP) {
      selectAndReturnFare();
      TrainSearchResults.selectReturn();
      cy.wait(Timeouts.MEDIUM_TIMEOUT_10_SEC.timeout);
      TrainSearchResults.expectSearchResultPresent();
      selectAndReturnFare();
    }
  }
}
