import { SeatMap, TrainCheckout, TrainItinerary, TrainTripType } from '@train-lib/index';
import { Timeouts } from '@utility-lib/constants';
interface CheckoutOptions {
  loyaltyCardType?: string;
  dbSeat?: boolean;
  loyaltyCard?: boolean;
  noOfTravelers?: number;
  noOfSeats?: number;
  fareName?: string;
  seatMap?: boolean;
  tripType?: TrainTripType;
  multipleTravelers?: boolean;
  comfortOption?: string;
  subTotalDetail?: string;
}

export class CheckoutModal implements CheckoutOptions {
  noOfTravelers: number;
  loyaltyCardType?: string;
  dbSeat?: boolean;
  loyaltyCard?: boolean;
  seatMap?: boolean;
  tripType?: TrainTripType;
  multipleTravelers?: boolean;
  comfortOption?: string;
  subTotalDetail?: string;

  constructor({
    loyaltyCardType = '',
    dbSeat = false,
    loyaltyCard = false,
    noOfTravelers = 1,
    tripType
  }: CheckoutOptions = {}) {
    this.loyaltyCardType = loyaltyCardType;
    this.dbSeat = dbSeat;
    this.loyaltyCard = loyaltyCard;
    this.noOfTravelers = noOfTravelers;
    this.tripType = tripType;
  }

  static checkout(checkoutConfig: CheckoutOptions = {}) {
    const {
      dbSeat: useDbSeat = false,
      loyaltyCard = false,
      loyaltyCardType = '',
      noOfTravelers = 1,
      seatMap: useSeatMap = false,
      tripType,
      multipleTravelers = false,
      comfortOption = false,
      subTotalDetail = false
    } = checkoutConfig;

    TrainCheckout.setTripInfo();
    cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
    cy.log(`seat map is ${useSeatMap}`);

    if (useSeatMap) {
      this.handleSeatMapOptions(tripType, multipleTravelers);
    } else {
      this.handleNonSeatMapOptions();
    }

    if (useDbSeat) {
      this.handleDbSeatOption();
    }

    if (loyaltyCard) {
      TrainCheckout.expectBahnCardPresentInCheckout(loyaltyCardType, true);
    }

    if (noOfTravelers) {
      TrainCheckout.expectNoOfTravelers(noOfTravelers);
    }
    if (comfortOption) {
      this.expectComfortOptionIsPresent(comfortOption);
    }
    TrainCheckout.storeBookingData();
    TrainCheckout.acceptAcknowledgement();
    if (subTotalDetail) {
      this.expectSubTotalDetailIsPresent(subTotalDetail);
    }
    this.getTripDates(tripType);

    TrainCheckout.bookTrain();
    TrainCheckout.expectBookingStatus('Train booking confirmed!');
    cy.wait(Timeouts.SHORT_TIMEOUT_5_SEC.timeout);
    TrainItinerary.openTripItinerary();
  }

  private static handleSeatMapOptions(
    tripType: TrainTripType | undefined,
    multipleTravelers: boolean
  ) {
    if (tripType) {
      SeatMap.chooseSeatFromMap(tripType, multipleTravelers);
    } else {
      throw new Error('Missing tripType in options');
    }
    TrainCheckout.expectSeatNumberIsPresent();
  }

  private static handleNonSeatMapOptions() {
    TrainCheckout.skipSeatMaps();
    TrainCheckout.seatPreferences();
    TrainCheckout.selectTicketType('E-ticket');
  }

  private static handleDbSeatOption() {
    TrainCheckout.skipSeatMaps();
    cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
    TrainCheckout.selectDbSeat();
  }

  private static expectComfortOptionIsPresent(comfortOption?: string) {
    cy.get('[class="fare-policy__condition__fare-name"]').should(
      'contain',
      `${comfortOption}`
    );
  }

  private static expectSubTotalDetailIsPresent(subTotalDetail?: string) {
    cy.get('[class="train-checkout-summary__item-body--left"]').should(
      'contain',
      `${subTotalDetail}`
    );
  }

  static getTripDates(tripType: TrainTripType | undefined) {
    const getAndCacheDate = (selector: string, cacheKey: string) => {
      cy.get('.summary__item__title')
        .contains(selector)
        .next('.summary__item__value')
        .invoke('text')
        .then((dateText) => {
          cy.log(dateText);
          cy.task('putDataInCache', { key: cacheKey, data: dateText });
        });
    };

    if (tripType === TrainTripType.ONEWAY) {
      getAndCacheDate('Departure', 'departureDate');
    }

    if (tripType === TrainTripType.ROUND_TRIP) {
      getAndCacheDate('Departure', 'departureDate');
      getAndCacheDate('Return', 'returnDate');
    }
  }
}
