import { utilitySelector, Timeouts } from '@utility-lib/index';
import { createEventSelector } from './create_event';

const eventDetailsSelector = {
  eventLocationDeparture: '.ta-location-search input',
  selectDepartLocationFromDropDown: '.popover-content .ta-typeahead__item-text',
  removeAllBookingsType: '[class^="booking-types__item booking-types__item--active"]',
  bookingTypeItem: '[data-testid="bookingTypeItem"]',
  sendInvite: '[data-testid="sendInvites"] button',
  teamEventName: '[data-testid="eventNameTitle"]',
  teamEventEstimatedPriceField: '[data-testid="estimatedCost"]',
  roomBlockTab: '[data-testid="roomBlockTab"]',
  hotelDetailsField: '[data-testid="recommendedHotelField"]',
  hotelOption: '[data-testid="hotelOption"]',
  pricePerNightField: '[data-testid="pricePerNight"]',
  taxPerNightField: '[data-testid="taxPerNight"]',
  resortFeePerNightField: '[data-testid="resortFeePerNight"]',
  saveBlockDetailsBtn: '[data-testid="saveBlockDetailsButton"]',
  confirmRoomBlockBtn: '[data-testid="confirmRoomBlock"]',
  assignRoomBlock: '[data-testid="assignRoomBlock"]',
  travelWindowDatePicker: '[data-testid="travelWindowDepartureDate"]',
  travelWindowCalendarDay: '[data-testid="calendarDay"]',
  travelWindowDoneBtn: '[data-testid="datePickerDoneButton"]',
  travelWindowTime: '.ta-select__label-wrap',
  suggestedTravelTimeOption: '[data-testid="timeValue"]',
  homeButton: '[data-qaid="HOME"]',
  addParticipantsBtn: '[data-testid="Add participants button"]',
  addParticipantsModalHeader: '[data-testid="modal header"]',
  addParticipantsModalBtn: '[data-testid="Add participants modal button"]',
  addParticipantInputField: '[data-testid="participant input field"]',
  addParticipantModalCloseBtn: '[data-testid="modal-header-close-button"]',
  participantDropdown: '[data-testid="participant dropdown"]',
  participantEmptyDropdown: '[data-testid="emptyParticipantDropdown"]',
  userPill: 'ta-user-tag-simple',
  deleteDraftBtn: '[data-testid="deleteTeamEvent"]',
  deleteDraftModalBtn: '[data-testid="Delete draft modal button"]',
  eventSettingsTab: '[data-testid="settings"]',
  eventParticipantsTab: '[data-testid="participants"]',
  eventAccommodationTab: '[data-testid="accommodation"]',
  teamEventTabs: 'ta-tabs',
  saveChanges: '[data-testid="stickyPrimaryButton"]',
  extraGuestAllowed: '[data-testid="extraGuestAllowed"] label',
  participantCard: '[data-testid="eventUsers"]',
  userPillLabel: '[data-testid="userPillLabel"]',
  discardChanges: '[data-testid="discardChanges"]',
  allowedVerticalsGroup: '[data-testid="allowedVerticalsGroup"]',
  allowedVerticalOption: '.team-event-booking-verticals__option',
  allowedBookingsWarningBanner: '[data-testid="allowedBookingsWarningText"]',
  allowedVerticalCheckbox: 'input[type="checkbox"]',
  loader: '[viewBox="0 0 50 50"]',
  approvalPanel: 'ta-team-event-control-panel'
};

export class EventDetails {
  static allowExtraGuest() {
    cy.allure().logStep('allow extra guest');
    EventDetails.switchTabs('settings');
    cy.get(eventDetailsSelector.extraGuestAllowed).click({ force: true });
  }

  static setEventLocationDeparture(location: string) {
    cy.allure().logStep(`set event location departure: ${location}`);
    cy.get(eventDetailsSelector.eventLocationDeparture).type(`${location}`);

    cy.get(eventDetailsSelector.selectDepartLocationFromDropDown)
      .contains(`${location}`)
      .trigger('click', { force: true });
    cy.wait('@waitForLocation');
    cy.get(eventDetailsSelector.loader, Timeouts.MEDIUM_TIMEOUT_60_SEC).should(
      'not.exist'
    );
  }

  static allowHotelBooking() {
    cy.allure().logStep('allow hotel booking');
    cy.get(eventDetailsSelector.removeAllBookingsType).each((ele) => {
      cy.wrap(ele).click({ force: true });
    });
    cy.get(eventDetailsSelector.bookingTypeItem).eq(0).click();
  }

  static sendInvite() {
    cy.allure().logStep('send invite');
    cy.get(eventDetailsSelector.sendInvite).click();
  }

  static expectTeamEventCreated() {
    cy.allure().logStep('expect team event created');
    cy.get(eventDetailsSelector.sendInvite).should('not.exist');
  }

  static verifyTeamEventSetupPageOpened(eventName: string) {
    cy.allure().logStep('verify team event setup page opened');
    cy.get(eventDetailsSelector.teamEventName).contains(eventName);
  }

  static verifyEstimatedPrice() {
    cy.allure().logStep('verify estimated price');
    cy.get(eventDetailsSelector.teamEventEstimatedPriceField)
      .invoke('text')
      .then((text) => {
        return text.replace('$', '').trim();
      })
      .then(parseFloat)
      .should('be.gt', 0);
  }

  static visitHomePage() {
    cy.allure().logStep('visit home page');
    cy.get(eventDetailsSelector.homeButton).click();
  }

  static selectRoomBlock() {
    cy.allure().logStep('select room block');
    cy.get(eventDetailsSelector.roomBlockTab).click();
  }

  static searchHotel(hotelName: string, index = 0) {
    cy.allure().logStep(`search hotel: ${hotelName}`);
    cy.get(eventDetailsSelector.hotelDetailsField).type(`${hotelName}`);
    cy.get(eventDetailsSelector.hotelOption).eq(index).click();
  }

  static setPricePerNight(price: string, index = 0) {
    cy.allure().logStep(`set price per night: ${price}`);
    cy.get(eventDetailsSelector.pricePerNightField).eq(index).type(`${price}`);
  }

  static setTaxPerNight(tax: string, index = 0) {
    cy.allure().logStep(`set tax per night: ${tax}`);
    cy.get(eventDetailsSelector.taxPerNightField).eq(index).type(`${tax}`);
  }

  static setResortFeePerNight(resortFee: string, index = 0) {
    cy.allure().logStep(`set resort fee per night: ${resortFee}`);
    cy.get(eventDetailsSelector.resortFeePerNightField).eq(index).type(`${resortFee}`);
  }

  static setTravelWindowDates(departureDate: string, returnDate: string) {
    cy.allure().logStep('set event travel window dates');
    this.switchTabs('settings');
    cy.get(eventDetailsSelector.travelWindowDatePicker).click();
    cy.get(eventDetailsSelector.travelWindowCalendarDay).contains(departureDate).click();
    cy.get(eventDetailsSelector.travelWindowCalendarDay).contains(returnDate).click();
    cy.get(eventDetailsSelector.travelWindowDoneBtn).click();
  }

  static setLatestArrivalTime(latestArrivalTime: string) {
    cy.allure().logStep('set suggested latest arrival time');
    cy.get(eventDetailsSelector.travelWindowTime).eq(0).click();
    cy.get(eventDetailsSelector.suggestedTravelTimeOption)
      .contains(latestArrivalTime)
      .click();
  }

  static setEarliestReturningTime(earliestReturningTime: string) {
    cy.allure().logStep('set suggested earliest returning time');
    cy.get(eventDetailsSelector.travelWindowTime).eq(1).click();
    cy.get(eventDetailsSelector.suggestedTravelTimeOption)
      .contains(earliestReturningTime)
      .click();
  }

  static saveBlockDetails() {
    cy.allure().logStep('save block details');
    cy.get(eventDetailsSelector.saveBlockDetailsBtn).click();
  }

  static confirmRoomBlock() {
    cy.allure().logStep('confirm room block');

    cy.get(eventDetailsSelector.confirmRoomBlockBtn)
      .contains('Confirm and continue')
      .click();
    cy.wait('@waitForConfirmRoomBlock');
  }

  static assignRoomToParticipant() {
    cy.allure().logStep('assign room to participant');
    cy.get(eventDetailsSelector.assignRoomBlock).click();
  }

  static openAddParticipantsModal() {
    cy.allure().logStep('open Add participants modal on the team event setup page');
    EventDetails.switchTabs('participants');
    cy.get(eventDetailsSelector.addParticipantsBtn).click();
    cy.get(eventDetailsSelector.addParticipantsModalHeader).contains('Add participants');
    cy.get(eventDetailsSelector.addParticipantsModalBtn).children().should('be.disabled');
  }

  static closeAddParticipantsModal() {
    cy.get(eventDetailsSelector.addParticipantModalCloseBtn).click();
  }

  static discardChanges() {
    cy.get(eventDetailsSelector.discardChanges).click();
  }

  static typeAndAddOneParticipant(userNamePart: string) {
    cy.allure().logStep(
      'type participant name in Add participants modal and add it to the list'
    );
    cy.get(eventDetailsSelector.addParticipantInputField).type(userNamePart);
    cy.get(eventDetailsSelector.participantDropdown).eq(0).click();
    cy.get(eventDetailsSelector.userPill).contains(userNamePart, { matchCase: false });
    cy.get(eventDetailsSelector.addParticipantsModalBtn).click();
    cy.get(utilitySelector.warningMsg).contains('Successfully added 1 participants.');
  }

  static deleteDraftEvent() {
    cy.allure().logStep('delete draft event from the team event setup page');
    EventDetails.switchTabs('settings');
    cy.get(eventDetailsSelector.deleteDraftBtn).click();
    cy.get(eventDetailsSelector.deleteDraftModalBtn).click();
  }

  static switchTabs(tab: 'settings' | 'participants' | 'accommodation') {
    switch (tab) {
      case 'settings':
        cy.get(eventDetailsSelector.eventSettingsTab).click({ force: true });
        break;

      case 'participants':
        cy.get(eventDetailsSelector.eventParticipantsTab).click({ force: true });
        break;

      case 'accommodation':
        cy.get(eventDetailsSelector.eventParticipantsTab).click({ force: true });
        break;

      default:
        break;
    }
  }

  static verifyEventTabs() {
    const settingsTab = 'Event settings';
    cy.allure().logStep('verify team event tabs on split');
    cy.get(eventDetailsSelector.teamEventTabs).contains(settingsTab);
  }

  static setEventParticipant() {
    cy.allure().logStep('add participant to the event');
    cy.task('getDataFromCache', 'userResponse').then((response: any) => {
      EventDetails.switchTabs('participants');
      cy.get(eventDetailsSelector.addParticipantsBtn).click();
      cy.wait('@waitForTeamEvent');
      cy.get(eventDetailsSelector.addParticipantInputField).type(response.familyName);
      cy.wait('@waitForTeamEventBookableUser');
      cy.get(eventDetailsSelector.participantDropdown).eq(0).click();
      cy.get(eventDetailsSelector.addParticipantsModalBtn).click();
      cy.wait('@waitForTeamEventBulkAdd');
    });
  }

  static setExistingEventParticipant(email: string) {
    cy.allure().logStep('add participant to the event');
    EventDetails.switchTabs('participants');
    cy.get(eventDetailsSelector.addParticipantsBtn).click();
    cy.wait('@waitForTeamEvent');
    cy.get(eventDetailsSelector.addParticipantInputField).type(email);
    cy.wait('@waitForTeamEventBookableUser');
    cy.get(eventDetailsSelector.participantDropdown).eq(0).click();
    cy.get(eventDetailsSelector.addParticipantsModalBtn).click();
    cy.wait('@waitForTeamEventBulkAdd');
  }

  // prerequisite: additional user should be added
  // see cypress/e2e/team_events/test/booking/event_flight_booking_tw.cy.ts as example
  static setSecondEventParticipant() {
    cy.allure().logStep('add second participant to the event');
    cy.task('getDataFromCache', 'travelerEmail').then((email: any) => {
      EventDetails.switchTabs('participants');
      cy.get(eventDetailsSelector.addParticipantsBtn).click();
      cy.wait('@waitForTeamEvent');
      cy.get(eventDetailsSelector.addParticipantInputField).type(email);
      cy.wait('@waitForTeamEventBookableUser');
      cy.get(eventDetailsSelector.participantDropdown).eq(0).click();
      cy.get(eventDetailsSelector.addParticipantsModalBtn).click();
      cy.wait('@waitForTeamEventBulkAdd');
    });
  }

  static saveChanges() {
    cy.allure().logStep('save changes made on "Event settings" tab');
    cy.get(eventDetailsSelector.saveChanges).click();
    cy.wait('@waitForSaveChanges');
    cy.get(eventDetailsSelector.saveChanges).should('not.exist');
  }

  static verifyDuplicateParticipant(email: string) {
    cy.allure().logStep('verify duplicate participant has (duplicate) in its name');
    cy.get(eventDetailsSelector.addParticipantsBtn).click();
    cy.wait('@waitForTeamEvent');
    cy.get(eventDetailsSelector.addParticipantInputField).type(email + ',' + email);
    cy.get(eventDetailsSelector.userPillLabel).contains('duplicate');
    cy.get(eventDetailsSelector.addParticipantsModalBtn).click();
    cy.wait('@waitForTeamEventBulkAdd');
    cy.get(eventDetailsSelector.participantCard).should('have.length', 1);
  }

  static verifyParticipantHasBeenAlreadyAdded(email: string) {
    cy.allure().logStep(
      'verify participant has been already added to the participants list'
    );
    cy.get(eventDetailsSelector.addParticipantsBtn).click();
    cy.wait('@waitForTeamEvent');
    cy.get(eventDetailsSelector.addParticipantInputField).type(email);
    cy.wait('@waitForTeamEventBookableUser');
    cy.get(eventDetailsSelector.participantEmptyDropdown).contains('No results found');
    cy.get(eventDetailsSelector.addParticipantsModalBtn)
      .children()
      .should('have.attr', 'disabled');
  }

  static verifyNotFoundParticipant(email: string) {
    cy.allure().logStep('verify participant has (not found) in its name');
    cy.get(eventDetailsSelector.addParticipantsBtn).click();
    cy.wait('@waitForTeamEvent');
    cy.get(eventDetailsSelector.addParticipantInputField).type(email + ',' + email);
    cy.get(eventDetailsSelector.userPillLabel).contains('not found');
  }

  static verifyDefaultAllowedVerticals(vertical1: string, vertical2: string) {
    cy.allure().logStep('verify default vertical options are selected');
    cy.get(eventDetailsSelector.allowedVerticalsGroup).within(() => {
      cy.get(eventDetailsSelector.allowedVerticalCheckbox)
        .eq(0)
        .should('have.class', 'has-icon');
      cy.get(eventDetailsSelector.allowedVerticalOption).contains(vertical1);
      cy.get(eventDetailsSelector.allowedVerticalCheckbox)
        .eq(1)
        .should('have.class', 'has-icon');
      cy.get(eventDetailsSelector.allowedVerticalOption).contains(vertical2);
    });
  }

  static uncheckAllowedVertical(index: number) {
    cy.allure().logStep('uncheck an allowed vertical in Allowed Verticals section');
    cy.get(eventDetailsSelector.allowedVerticalsGroup).within(() => {
      cy.get(eventDetailsSelector.allowedVerticalCheckbox)
        .eq(index)
        .should('have.class', 'has-icon')
        .click({ force: true });
    });
  }

  static checkAllowedVertical(index: number) {
    cy.allure().logStep('check an allowed vertical in Allowed Verticals section');
    cy.get(eventDetailsSelector.allowedVerticalsGroup).within(() => {
      cy.get(eventDetailsSelector.allowedVerticalCheckbox)
        .eq(index)
        .should('not.have.class', 'has-icon')
        .click({ force: true });
    });
  }

  static verifyAllowedBookingsWarning(text: string) {
    cy.allure().logStep('verify there is a warning message if no verticals are selected');
    cy.get(eventDetailsSelector.allowedBookingsWarningBanner).contains(text);
  }

  static verifySelectedVerticalIsEnabledForParticipant(index: number) {
    cy.allure().logStep(
      'verify only verticals selected in Allowed bookings section are allowed for participant'
    );
    cy.get(eventDetailsSelector.bookingTypeItem)
      .eq(index)
      .should('have.class', 'booking-types__item--active');
  }

  static verifyAllowedBookingVerticalsDisabled() {
    cy.allure().logStep('verify all options in Allowed bookings section are disabled');
    cy.get(eventDetailsSelector.allowedVerticalsGroup).within(() => {
      cy.get(eventDetailsSelector.allowedVerticalCheckbox).each((item) => {
        cy.wrap(item).should('be.disabled');
      });
    });
  }

  static verifyAllowedBookingsCheckboxesAreNotVisible() {
    cy.allure().logStep('verify Allowed bookings section does not contail checkboxes');
    cy.get(eventDetailsSelector.allowedVerticalsGroup).should('not.exist');
  }

  static verifyApprovalIsNotRequired() {
    cy.allure().logStep('verify approval is not required to send invites');
    cy.get(eventDetailsSelector.approvalPanel).should('not.exist');
  }

  static verifyApprovalIsRequired() {
    cy.allure().logStep('verify approval is required to send invites');
    cy.get(eventDetailsSelector.approvalPanel).should('exist');
  }
}
