import { AmplitudeEvents, GrowthAmplitudeEvents } from './amplitude-events';
import { Timeouts } from '@utility-lib/index';
import { LoginPage } from '@admin-lib/login';

const delegateSelectors = {
  viewAllTripsButton: '[data-testid="view-all-trips"]',
  addTravelerButton: '[data-testid="add-first-traveler-empty"]',
  delegateUsersList: '[data-testid="delegateUsersList"]',
  delegateTripsList: '[data-testid="delegateTripsHeader"]',
  delegateTripsListCards: '[data-testid="delegateTripCard"]',
  welcomeDelegateModalCta: '[data-testid="ta-welcome-delegate-modal-cta"]',
  welcomeDelegateModalCtaButton: '[data-testid="ta-welcome-delegate-modal-cta"] > .ta-button-v2',
  topLeftMainMenu: '[data-qaid="PLATFORM_SWITCHER-button"]',
  mainMenuAdminButton: '[data-qaid="ADMIN"]',
  policyButton: '[data-qaid="POLICY-button"]',
  travelPolicyButtonInPolicy: '[data-qaid="TRAVEL_POLICY"]',
  homeTabInNavBar: '[data-qaid="HOME"]',
  tripsTabInNavBar: '[data-qaid="TRIPS"]',
  createCompanyAccountButton: '[data-testid="createCompanyAccountButton"]',
  newTripButton: '[data-testid="newTrip"]',
  editProfileButton: '[data-testid="editProfile"]',
  userRow: '[data-testid="userRowName"]',
  userRowContainer: '[data-testid="userRowContainer"]',
  removeTravelerIcon: '[data-testid="removeUserButton"]',
  noResultNewTrip: '[data-testid="noResultsNewTripLinkV2"]',
  travelerForBooking: '[data-testid="userGroupName"]',
  addTravelerCenterButton: '[data-testid="add-first-traveler-empty"] > .ta-button-v2',
  addTravelerBottomButton: '[data-testid="addButtonFooter"] > .ta-button-v2',
  addTravelerHighlight: '[data-testid="delegate-user-highlight"].selected',
  addedTravelerToastCloseButton: '[data-testid="ToastrCloseButton"]',
  addedTravelerToastText: '[data-testid="ToastrMessage"]',
  addedTravelerToastCtaEditButton: '[data-testid="ToastrSecondaryCtaButton"]',
  notificationTab: '[qaid="taProfileSideNav"] .ta-profile-side-nav__text:contains("Notifications")',
  editProfileLeftTabs: '[qaid="taProfileSideNav"]',
  profilePageHeader: '[data-testid="profileHeaderName"]',
  notificationBack: '[data-testid="profileBackArrow"]',
  firstNotificationCheckbox: '[data-testid="notification-checkbox-EMAIL-BOOKING_CONFIRMATIONS_MY_OWN_TRIPS"]',
  searchByTripInput: '[data-testid="searchTripInput"]',
  rewardsBanner: '[data-testid="delegate-header-rewards-banner"]',
  headerBFOBanner: '[data-testid="headerBannerINCENTIVIZE_BFO_1ST_BOOKING"]',
  rewardsBannerCta: '[data-testid="delegate-header-rewards-banner-cta"]',
  delegateTripsTabs: '[data-testid="delegateTripsTabs"]'
};

const createModalSelectors = {
  firstName: '[data-testid="ta-travel-planner-create-user-modal-first-name"]',
  lastName: '[data-testid="ta-travel-planner-create-user-modal-last-name"]',
  email: '[data-testid="ta-travel-planner-create-user-modal-email"]',
  toggle: '[data-testid="ta-travel-planner-create-user-modal-send-traveler-toggle"]',
  createButton: '[data-testid="ta-travel-planner-create-user-modal-save-button"]',
  tabs: '[data-testid="ta-travel-planner-modal"] [data-testid="verticalsTabGroup"] [role="tab"]',
  content: '[data-testid="ta-travel-planner-error-results"] p',
  searchInput: '[data-testid="ta-travel-planner-add-user-modal-search-input"]',
  results: '[data-testid="ta-travel-planner-add-user-modal__body-results"]',
  resultRowName: '[data-testid="ta-travel-planner-add-user-modal-name"]',
  resultRowAdd: '[data-test-id="ta-travel-planner-add-user-modal-add-button"]',
  cancelButton: '[data-testid="ta-travel-planner-add-user-modal-cancel-button"]',
  addButton: '[data-testid="ta-travel-planner-add-user-modal-save-button"]'
};

const adminPageConsts = {
  url: 'app/admin2/en/dashboard',
  reportsTab: '[data-qaid="REPORTS"]',
  safetyTab: '[data-qaid="SAFETY"]',
  policyTab: '[data-qaid="POLICY"]',
  dashboardTab: '[data-qaid="DASHBOARD"]',
  analysisTab: '[data-qaid="ANALYSIS"]',
  settingsTab: '[data-qaid="SETTINGS"]',

  teamOffsiteTab: '[data-qaid="EVENTS"]',
  teamOffsiteCreate: '[data-testid="createEventButton"]',
  teamOffsiteUrl: 'group-travel/list'
};

export class DelegatePage {
  static verifyDelegateHomePageOpened(): void {
    cy.allure().logStep('Verify go to home page');
    cy.url().should('include', '/trips/delegate');
    cy.get(delegateSelectors.delegateUsersList).should('exist');
    cy.get(delegateSelectors.delegateTripsList).should('exist');
    AmplitudeEvents.addExpectedAmplitudeEvents(GrowthAmplitudeEvents.OPEN_DELEGATE_HOME_SCREEN);
  }

  static verifyDelegateIsLandingPage(): void {
    cy.allure().logStep('verify delegate is landing page - navgiate to home page route');
    this.verifyDelegateHomePageOpened();
  }

  static loginUserAfterLogout(token: string): void {
    cy.allure().logStep('login user after logout');
    cy.task('getDataFromCache', 'userEmail').then((email: any) => {
      LoginPage.visitTALoginPage();
      LoginPage.loginWithCredentials(email, token);
      cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
    });
  }

  static navigateToAdminPage(): void {
    cy.allure().logStep('nevigate to admin menu');
    cy.get(delegateSelectors.topLeftMainMenu).click();
    cy.get(delegateSelectors.mainMenuAdminButton).click();
  }

  static navigateToAdminClaim(): void {
    cy.allure().logStep('nevigate to admin claim');
    cy.get(delegateSelectors.policyButton).click();
    cy.get(delegateSelectors.travelPolicyButtonInPolicy).click();
    cy.get(delegateSelectors.createCompanyAccountButton).click();
  }

  static closeWelcomeModal(): void {
    cy.get(delegateSelectors.welcomeDelegateModalCtaButton).click();
  }

  static verifyNavBarHasTravelPlanner(): void {
    cy.allure().logStep('verify nav bar has travel planner tab');
    cy.get(delegateSelectors.tripsTabInNavBar + ' > .ta-menu-button > .ta-nav-button--label').contains(
      'Travel planner'
    );
  }

  static verifyTeamOffsite(): void {
    cy.allure().logStep('verify team offsite for delegate user');
    cy.get(adminPageConsts.teamOffsiteTab).click();
    cy.url().should('include', adminPageConsts.teamOffsiteUrl);
    cy.get(adminPageConsts.teamOffsiteCreate).click();
    cy.url().should('include', '/home');
    cy.get(delegateSelectors.tripsTabInNavBar).click();
  }

  static checkAddTravelerCenterButtonYellowMark(): void {
    cy.allure().logStep('check add traveler center button yellow mark and click');
    cy.get(delegateSelectors.addTravelerCenterButton).should('exist');
    cy.get(delegateSelectors.addTravelerHighlight).should('exist');
  }

  static checkFiltersShown(): void {
    cy.allure().logStep('check filters shown');
    cy.get(delegateSelectors.delegateTripsTabs).should('exist');
    cy.get(delegateSelectors.delegateTripsTabs).within(() => {
      ['Upcoming', 'Past', 'Canceled'].forEach((tabName) => {
        cy.contains(tabName).should('exist');
      });
    });
  }

  static verifyRewardsBannerShown(): void {
    cy.allure().logStep('check rewards banner shown');
    cy.get(delegateSelectors.rewardsBanner).should('exist');
    cy.get(delegateSelectors.headerBFOBanner).should('not.exist');
  }

  static verifyRewardsBannerCta(): void {
    cy.allure().logStep('check rewards banner cta navigating and disappearing');
    cy.get(delegateSelectors.rewardsBannerCta).click();
    cy.url().should('include', 'rewards');
    cy.go('back');
    cy.get(delegateSelectors.rewardsBannerCta).should('not.exist');
  }

  static verifyBFOBannerShown(): void {
    cy.allure().logStep('check bfo header banner shown');
    cy.get(delegateSelectors.headerBFOBanner).should('exist');
    cy.get(delegateSelectors.rewardsBanner).should('not.exist');
  }

  static verifyBFOBannerShownAlsoInHomePage(): void {
    cy.allure().logStep('check bfo header banner shown home page and travel planner');
    cy.get(delegateSelectors.homeTabInNavBar).click();
    cy.get(delegateSelectors.headerBFOBanner).should('exist');
    cy.get(delegateSelectors.tripsTabInNavBar).click();
    cy.get(delegateSelectors.headerBFOBanner).should('exist');
  }

  static clickOnViewAllTrips(): void {
    cy.allure().logStep('click on view all trips');
    cy.get(delegateSelectors.viewAllTripsButton).click();
  }

  static searchTrip(tripName?: string): void {
    const uniqExistingTripName = 'Cypress Test - Dont change';
    cy.get(delegateSelectors.searchByTripInput).type(tripName || uniqExistingTripName);
  }

  static verifyExistingTripsMoreThanOne(): void {
    cy.get(delegateSelectors.delegateTripsListCards).should('have.length.greaterThan', 1);
  }

  static verifySingleTrip(): void {
    cy.get(delegateSelectors.delegateTripsListCards).should('have.length', 1);
  }

  static clickAddTravelerCenter(): void {
    cy.get(delegateSelectors.addTravelerCenterButton).click();
  }

  static clickAddTraveler(): void {
    cy.allure().logStep('click add traveler');
    cy.get(delegateSelectors.addTravelerBottomButton).click();
  }

  static createNewTravelerUser(firstName: string, lastName: string): void {
    cy.allure().logStep('create new traveler user');
    cy.get(createModalSelectors.firstName).type(firstName);
    cy.get(createModalSelectors.lastName).type(lastName);
    const timestamp = Date.now().toString();
    const randomNumber = Math.floor(Math.random() * 1000).toString();
    const randomEmail = `test${randomNumber}-${timestamp}@nvBFOTest.com`;
    cy.get(createModalSelectors.email).type(randomEmail);
    cy.get(createModalSelectors.createButton).click();
    this.checkUserRowExists(`${firstName} ${lastName}`);
  }

  static checkUserRowExists(fullName: string): void {
    cy.allure().logStep(`check user row exists ${fullName}`);
    this.getUserRow(fullName).should('exist');
  }

  static removeTraveler() {
    cy.allure().logStep('removing traveler from list (first one)');
    // need this because the remove element is visible only when css event hover
    // this is the way I found to make it v
    cy.window().then((win) => {
      if (win.document.querySelector(delegateSelectors.removeTravelerIcon)) {
        const el2: any = win.document.querySelector(delegateSelectors.removeTravelerIcon);
        el2.style.display = 'block';
        // Now the element should be visible, so we can click on it
        cy.get(delegateSelectors.removeTravelerIcon).eq(0).click();
      }
    });
  }

  static checkAddTravelerFromListEmpty(close = true, moveBackToFirstTab = false): void {
    cy.allure().logStep('check add traveler from list');
    this.moveToTabInModal(1);
    cy.get(createModalSelectors.results).should('not.exist');
    cy.get(createModalSelectors.content).contains('No recently added users');
    if (close) {
      cy.get(createModalSelectors.cancelButton).click();
      return;
    }
    if (moveBackToFirstTab) {
      this.moveToTabInModal(0);
      return;
    }
  }

  static moveToTabInModal(index = 0): void {
    cy.get(createModalSelectors.tabs).eq(index).click();
  }

  static checkAddTravelerFromListNotEmpty(close = false): void {
    cy.allure().logStep('check add traveler from list has results');
    cy.get(createModalSelectors.tabs).eq(1).click();
    cy.get(createModalSelectors.results).should('exist');
    if (close) {
      cy.get(createModalSelectors.cancelButton).click();
    }
  }

  static searchExistingTraveler(searchValue: string): void {
    cy.allure().logStep('search existing traveler');
    cy.get(createModalSelectors.searchInput).clear();
    cy.get(createModalSelectors.searchInput).type(searchValue);
    cy.wait(Timeouts.SHORT_TIMEOUT_2_SEC.timeout);
    cy.get(createModalSelectors.resultRowName).contains(searchValue);
  }

  static clearSearch(): void {
    cy.get(createModalSelectors.searchInput).clear();
  }

  static searchNotExistingTraveler(searchValue: string): void {
    cy.allure().logStep('search not existing traveler');
    cy.get(createModalSelectors.searchInput).clear();
    cy.get(createModalSelectors.searchInput).type(searchValue);
    cy.wait(Timeouts.SHORT_TIMEOUT_1_SEC.timeout);
    cy.get(createModalSelectors.content).contains('No travelers found');
  }

  static addSearchedTraveler(): void {
    cy.allure().logStep('add searched traveler for delegates list addition');
    this.addFirstTravelerInResults();
    cy.get(createModalSelectors.addButton).click();
  }

  static checkGuestUserShownInSuggestions(guestName: string): void {
    cy.allure().logStep('check guest user shown in suggestions');
    cy.get(createModalSelectors.resultRowName).contains(guestName);
  }

  static addFirstTravelerInResults(): void {
    cy.get(createModalSelectors.resultRowAdd).eq(0).click();
  }

  static checkMaxUsersAddShowsError(): void {
    cy.allure().logStep('check max number of travelers error is shown');
    cy.get(createModalSelectors.results).should('not.exist');
    cy.get(createModalSelectors.content).contains('Maximum number of travelers is reached');
  }

  static checkSideToastShown(clickEdit = false): void {
    cy.allure().logStep('check side toast Added traveler shown');
    cy.get(delegateSelectors.addedTravelerToastText).contains('Traveler added');
    if (clickEdit) {
      // otherwise it will open new tab
      cy.window().then((win) => {
        cy.stub(win, 'open').callsFake((url) => {
          win.location.href = url;
        });
      });
      cy.get(delegateSelectors.addedTravelerToastCtaEditButton).click();
    }
  }

  static checkEditProfileShownWithNotifications(fullName: string): void {
    cy.allure().logStep('check edit profile shown with notifications');
    cy.get(delegateSelectors.profilePageHeader).contains(fullName);
    cy.get(delegateSelectors.notificationTab).click();
  }

  static pressBackFromNotifications(): void {
    cy.allure().logStep('check press back from notifications');
    cy.get(delegateSelectors.notificationBack).click();
  }

  static verifyNotificationUpdated(): void {
    cy.allure().logStep('verify notification updated');
    cy.intercept('PATCH', '/api/delegate/notificationPreferences/users/*').as('waitForNotifications');
    cy.get(delegateSelectors.firstNotificationCheckbox).click();
    cy.wait('@waitForNotifications').then((interception) => {
      expect(
        interception?.response?.body?.userPreferences?.BOOKING_CONFIRMATIONS_MY_OWN_TRIPS?.channels?.EMAIL.enabled
      ).to.eq(false);
      expect(
        interception?.response?.body?.userPreferences?.BOOKING_CONFIRMATIONS_MY_OWN_TRIPS?.channels?.PUSH.enabled
      ).to.eq(true);
    });
  }

  static checkAddTravelerBottomButtonShown(): void {
    cy.allure().logStep('check button add traveler shown in bottom of list');
    cy.get(delegateSelectors.addTravelerCenterButton).should('not.exist');
    cy.get(delegateSelectors.addTravelerHighlight).should('not.exist');
    cy.get(delegateSelectors.addTravelerBottomButton).should('exist');
  }

  static getUserRow(fullName: string): Cypress.Chainable<JQuery<HTMLElement>> {
    return cy.get(delegateSelectors.userRow + `[title="${fullName}"]`);
  }

  static checkUserSelectedAndEmptyTripState(fullName: string): void {
    cy.allure().logStep('check user selected and empty trip state');
    this.getUserRow(fullName)
      .closest(delegateSelectors.userRowContainer + '.active')
      .should('exist');
    this.checkEmptyState(fullName);
  }

  static checkEmptyState(fullName: string): void {
    cy.get(delegateSelectors.noResultNewTrip).should('exist');
    cy.get(delegateSelectors.noResultNewTrip).contains(fullName.split(' ')[0]);
  }

  static verifyUsersSorted(): void {
    cy.allure().logStep('verify user sorted');
    cy.get(delegateSelectors.userRow).then((users) => {
      const userTexts = users.map((index, user) => Cypress.$(user).text().trim()).get();
      const sortedUserTexts = [...userTexts].sort();
      expect(userTexts).to.deep.equal(sortedUserTexts);
    });
  }

  static selectSpecificStaticUser(fullName: string): void {
    cy.allure().logStep('selecting specific user');
    this.getUserRow(fullName).first().click();
  }

  static checkEditProfileLeftSide(fullName: string): void {
    this.selectSpecificStaticUser(fullName);
    this.clickEditProfile();
    this.checkButtonsOnTheLeftSide();
  }

  static getProfileTab(tabText: string) {
    return cy.get(`${delegateSelectors.editProfileLeftTabs} .ta-profile-side-nav__text`).contains(tabText);
  }

  static checkButtonsOnTheLeftSide(): void {
    cy.allure().logStep('check buttons on the left side');
    this.getProfileTab('Loyalty programs').should('exist');
    this.getProfileTab('Traveler info').should('exist');
    this.getProfileTab('Payment methods').should('not.exist');
    this.getProfileTab('Contact info').should('not.exist');
    this.getProfileTab('Notifications').should('not.exist');
  }

  static checkUserNotExist(fullName: string): void {
    this.getUserRow(fullName).should('not.exist');
  }

  static clickNewTrip(): void {
    cy.allure().logStep('navigate to new trip');
    cy.get(delegateSelectors.newTripButton).click();
  }

  static clickEditProfile(): void {
    cy.allure().logStep('navigate to edit profile');
    cy.get(delegateSelectors.editProfileButton).click();
  }

  static clickNewTripNoResults(name?: string): void {
    cy.allure().logStep('navigate to new trip from no results');
    if (name) {
      cy.get(delegateSelectors.noResultNewTrip).contains(name);
    }
    cy.get(delegateSelectors.noResultNewTrip).click();
  }

  static verifySearchPageShownWithSelectedUser(name: string): void {
    cy.allure().logStep('verify search page shown with selected user');
    cy.get(delegateSelectors.travelerForBooking).contains(name);
  }

  static verifyAdminPageShowThreeTabs(): void {
    cy.allure().logStep('verify admin page show three tabs - reports, policy, safty');
    cy.get(adminPageConsts.reportsTab).should('exist');
    cy.get(adminPageConsts.safetyTab).should('exist');
    cy.get(adminPageConsts.policyTab).should('exist');
    cy.get(adminPageConsts.dashboardTab).should('not.exist');
    cy.get(adminPageConsts.settingsTab).should('not.exist');
  }

  static verifyAdminPageShowAllTabs(): void {
    cy.allure().logStep('verify admin page show all tabs');
    cy.get(adminPageConsts.policyTab).should('exist');
    cy.get(adminPageConsts.reportsTab).should('exist');
    cy.get(adminPageConsts.safetyTab).should('exist');
    cy.get(adminPageConsts.dashboardTab).should('exist');
    cy.get(adminPageConsts.analysisTab).should('exist');
    cy.get(adminPageConsts.settingsTab).should('exist');
  }
}
