import {
  Utility,
  Random,
  TripTileType,
  utilitySelector,
  Timeouts
} from '@utility-lib/index';
import { HotelInvoiceValidation } from '@commerce-lib/hotels/invoice_validation';

export const hotelCheckoutSelector = {
  hotelBookingPolicyContinue:
    '[qaid="hotelCheckoutBookingPolicy"] ta-info-banner [class^="info-banner__right"] [theme="primary"] div.ta-button__content',
  phoneNumber: '[class^="hotel-checkout__phone-number"] .ta-button__content',
  acceptAcknowledgement: 'ta-hotel-checkout-summary .info-banner__checkbox',
  bookNow: '[class^="info-banner__right"] .ta-button__content',
  bookingSuccessMsg: '.booking-success .booking-success__left__title',
  outOfPolicy: '[qaid="hotelCheckoutOutOfPolicy"]',
  outOfPolicyReasonSubmit: '[formcontrolname="reason"]',
  outOfPolicyAcknowledgment:
    '[qaid="hotelCheckoutOutOfPolicy"] .mat-checkbox-inner-container',
  outOfPolicyContinue: '[qaid="hotelCheckoutOutOfPolicy"] .ta-button__content',
  numberOfRooms:
    '.hotel-in-this-booking__breakdown__room-nums .hotel-in-this-booking__medium',
  numberOfGuests:
    '.hotel-in-this-booking__breakdown__guests .hotel-in-this-booking__medium',
  closeBookingSuccessModel:
    '.booking-success [qaid="bookingSuccessClose"] .booking-success__close__icon',
  bookCarPopup: 'div.booking-success__close ta-svg-image div',
  vaccine: 'ta-vaccination-proof',
  vaccineAcknowledgement: '[titleicon = "vaccine"] [class^= "info-banner__left"]',
  acceptVaccineAcknowledgement: '[titleicon="vaccine"] [qaid="infoBannerPrimaryButton"]',
  hotelCancellationAndChargePolicy:
    '[qaid="hotelCheckoutBookingPolicy"] .ta-button__content',
  requireDataSection: 'ta-checkout-traveler-require-data',
  requireDataEmail: 'ta-checkout-traveler-require-data input[type="email"]',
  requireDataSave: 'ta-checkout-traveler-require-data ta-button[theme="primary"]',
  paymentMethodCard: '[class^="ta-payment-card__image"]',
  paymentDue: '.payment-schedule__item__amount',
  paymentDueItem: '[qaid="hotelPaymentScheduleTotalDueNow"]',
  paymentDueAdditionalMessage: '.payment-schedule__description',
  approvalButton: '.hard-approval-explanation-modal button ',
  customFields: '[qaid="tripCheckoutCustomField"]',
  yourPolicy: '[headerprimarybuttonlabel="Your policy"] [qaid="infoBannerPrimaryButton"]',
  saveTripInfo: '[qaid="tripCheckoutCreateButton"]',
  checkoutHeading: '.hotel-checkout__heading'
};

export class HotelCheckout {
  static waitToBeLoaded(matchingTrips = true): void {
    cy.allure().logStep('wait for hotel checkout page APIs to complete');
    cy.wait('@waitForHotelContract');
    if (matchingTrips) cy.wait('@waitForMatchingTrips');
  }

  static checkForHotelCheckoutHeading(): void {
    cy.get(hotelCheckoutSelector.checkoutHeading, {
      timeout: Timeouts.MEDIUM_TIMEOUT_10_SEC.timeout
    }).should('be.visible');
  }

  static setTripInfo() {
    cy.wait(Timeouts.MEDIUM_TIMEOUT_10_SEC.timeout);
    cy.get(hotelCheckoutSelector.paymentMethodCard).should('be.visible');
    Utility.saveTripInformation();
    const maxRetryCount = 3;
    let retryCount = 0;
    cy.get(utilitySelector.bodySelector).then(($body) => {
      if ($body.find(hotelCheckoutSelector.saveTripInfo).length > 0) {
        Utility.saveTripInformation();
      } else {
        retryCount++;
        if (retryCount < maxRetryCount) {
          cy.wait(Timeouts.SHORT_TIMEOUT_5_SEC.timeout);
          Utility.saveTripInformation();
        } else {
          cy.log('Trip info is not loaded on hotel checkout');
        }
      }
    });
  }

  static verifyCustomFieldsInTripPurpose() {
    cy.allure().logStep('verify custom fields in trip purpose');
    cy.get(hotelCheckoutSelector.customFields).should('be.visible');
  }

  static createNewTripInfo() {
    Utility.createNewTrip();
    this.setTripInfo();
  }

  static acceptHotelBookingPolicy() {
    cy.get(utilitySelector.bodySelector).then((body) => {
      if (body.find(hotelCheckoutSelector.hotelBookingPolicyContinue).length > 0) {
        cy.allure().logStep('continue hotel booking policy');
        cy.get(
          hotelCheckoutSelector.hotelBookingPolicyContinue,
          Timeouts.MAX_TIMEOUT_120_SEC
        ).click();
        cy.log('Hotel policy accepted');
      } else {
        cy.allure().logStep('Hotel policy not required');
        cy.log('Hotel policy not required');
      }
    });
    this.acceptYourPolicy();
  }

  static acceptOutOfPolicyHotelWithReason() {
    cy.get(utilitySelector.bodySelector).then((body) => {
      if (body.find(hotelCheckoutSelector.hotelBookingPolicyContinue).length > 0) {
        cy.allure().logStep('continue hotel booking policy');
        cy.get(
          hotelCheckoutSelector.hotelBookingPolicyContinue,
          Timeouts.MAX_TIMEOUT_120_SEC
        ).click();
        cy.log('Hotel policy accepted');
      } else {
        cy.allure().logStep('Hotel policy not required');
        cy.log('Hotel policy not required');
      }
    });
    HotelCheckout.expectOutOfPolicyReasonIsPresent();
    HotelCheckout.setOutOfPolicyReasonIfRequired();
  }

  static acceptYourPolicy() {
    cy.get(utilitySelector.bodySelector).then((body) => {
      if (body.find(hotelCheckoutSelector.yourPolicy).length > 0) {
        cy.allure().logStep('continue policy is within range');
        cy.get(hotelCheckoutSelector.yourPolicy, Timeouts.MAX_TIMEOUT_120_SEC).click();
        cy.log('continue policy is within range');
      } else {
        cy.allure().logStep('continue policy not found');
        cy.log('Hotel policy not found');
      }
    });
  }
  static hotelCancellationAndChargePolicy() {
    cy.wait('@waitForPaymentMethods');
    cy.get(utilitySelector.bodySelector).then((body) => {
      if (body.find(hotelCheckoutSelector.hotelCancellationAndChargePolicy).length > 0) {
        cy.allure().logStep('continue hotel booking policy');
        cy.log('Hotel cancellation accepted');
        cy.get(
          hotelCheckoutSelector.hotelCancellationAndChargePolicy,
          Timeouts.MAX_TIMEOUT_120_SEC
        )
          .contains(' Continue ')
          .click();
      } else {
        cy.allure().logStep('Hotel cancellation policy not required');
        cy.log('Hotel cancellation policy not required');
      }
    });
  }

  static setPhoneNumber() {
    cy.get(utilitySelector.bodySelector).then((phoneNumber) => {
      if (phoneNumber.find(hotelCheckoutSelector.phoneNumber).length > 0) {
        cy.allure().logStep('Set phone number');
        cy.get(hotelCheckoutSelector.phoneNumber, Timeouts.MAX_TIMEOUT_120_SEC).click();
      } else {
        cy.allure().logStep('Phone number not required');
        cy.log('Phone number not required');
      }
    });
  }
  static checkIfProofOfVaccineRequired() {
    cy.get(utilitySelector.bodySelector).then((vaccine) => {
      if (vaccine.find(hotelCheckoutSelector.vaccine).length > 0) {
        cy.allure().logStep('vaccine acknowledgement found');
        cy.get(
          hotelCheckoutSelector.vaccineAcknowledgement,
          Timeouts.MAX_TIMEOUT_120_SEC
        ).click();
        cy.get(hotelCheckoutSelector.acceptVaccineAcknowledgement).click();
      } else {
        cy.allure().logStep('vaccine acknowledgement not required');
        cy.log('vaccine acknowledgement not required');
      }
    });
  }

  static setOutOfPolicyReasonIfRequired() {
    cy.get(utilitySelector.bodySelector).then((outOfPolicyReason) => {
      if (outOfPolicyReason.find(hotelCheckoutSelector.outOfPolicy).length > 0) {
        cy.allure().logStep('Accept Acknowledgement');
        cy.get(
          hotelCheckoutSelector.outOfPolicyReasonSubmit,
          Timeouts.MAX_TIMEOUT_120_SEC
        ).then((ele) => {
          cy.wrap(ele).type('need to book urgent');
          cy.wrap(ele).click();
        });

        cy.get(hotelCheckoutSelector.outOfPolicyAcknowledgment).click();
        cy.get(hotelCheckoutSelector.outOfPolicyContinue).contains(' Continue ').click();
      } else {
        cy.allure().logStep('Acknowledgement not required');
        cy.log('Acknowledgement not required');
      }
    });
  }

  static expectOutOfPolicyReasonIsPresent() {
    cy.get(hotelCheckoutSelector.outOfPolicyReasonSubmit).should('be.exist');
    cy.allure().logStep('Out of policy reason is present');
  }

  static acceptAcknowledgement() {
    cy.allure().logStep('accept acknowledgement');
    cy.get(hotelCheckoutSelector.acceptAcknowledgement).click();
  }

  static bookNow() {
    cy.allure().logStep('book hotel');
    cy.get(hotelCheckoutSelector.bookNow).last().click();
    cy.wait('@waitForCheckout');
  }

  static expectHotelBookedSuccessfully(successMsg: string) {
    cy.get(hotelCheckoutSelector.bookingSuccessMsg, Timeouts.MAX_TIMEOUT_120_SEC).should(
      'be.contain',
      `${successMsg}`
    );
    cy.allure().logStep('Hotel booked successfully');

    HotelCheckout.closeBookingSuccessModel();
  }

  static expectNumberOfRooms(numOfRooms: number) {
    cy.get(hotelCheckoutSelector.numberOfRooms).contains(numOfRooms);
  }

  static expectNumberOfGuests(numOfGuests: number) {
    cy.get(hotelCheckoutSelector.numberOfGuests).contains(numOfGuests);
  }

  static closeBookingSuccessModel() {
    cy.allure().logStep('close booking success model');
    cy.get(
      hotelCheckoutSelector.closeBookingSuccessModel,
      Timeouts.MAX_TIMEOUT_120_SEC
    ).click({
      force: true
    });
  }

  static expectPrepayHotelRoomDueNowIsNotZero() {
    cy.allure().logStep(`expect prepay hotel room due now is not zero`);
    cy.get(utilitySelector.bodySelector).then(($body) => {
      if ($body.find(hotelCheckoutSelector.paymentDueItem).length) {
        cy.get(hotelCheckoutSelector.paymentDueItem).should('not.contain', `$0.0`);
      } else {
        cy.get(hotelCheckoutSelector.paymentDueAdditionalMessage).contains(
          'Payment may be charged at booking or check-in.'
        );
      }
    });
  }

  static updateEmailDetails(email: string) {
    cy.allure().logStep('checking if personal email required');
    cy.get(utilitySelector.bodySelector).then(($body) => {
      if ($body.find(hotelCheckoutSelector.requireDataSection).length) {
        cy.allure().logStep('enter required email details');
        cy.get(hotelCheckoutSelector.requireDataEmail).type(email);
        cy.get(hotelCheckoutSelector.requireDataSave).click();
      }
    });
  }

  static checkoutFLow(tripTileType: TripTileType) {
    this.createNewTripInfo();
    HotelCheckout.hotelCancellationAndChargePolicy();
    HotelCheckout.acceptHotelBookingPolicy();
    HotelCheckout.setPhoneNumber();
    HotelCheckout.checkIfProofOfVaccineRequired();
    if (tripTileType === 'Personal') {
      HotelCheckout.updateEmailDetails(
        'personal-' + Random.randomString(12) + '@staging-prime.tripactions.xyz'
      );
    }
    HotelCheckout.acceptAcknowledgement();
    HotelInvoiceValidation.storeBookingData();
    HotelCheckout.bookNow();
  }
  static bookNowAndAskForApproval() {
    cy.allure().logStep('Book now and ask for approval');
    cy.get(hotelCheckoutSelector.bookNow).last().click();
    cy.get(hotelCheckoutSelector.approvalButton).last().click();
    cy.wait('@waitForCheckout');
  }
}
