import { User_Type } from '@support-onboard/index';
import {
  CompanyLoginOptions,
  CompanyLoginOptionsInitial,
  CompanyUtility,
  Timeouts
} from '@utility-lib/index';
import { BookingParams } from '@fixtures/travelxen/booking_data';
/**
 * Create a new company and login with users of specified types.
 * @param {CompanyLoginOptions} options - The options for creating a new company and logging in.
 * @param {CompanyLoginOptionsInitial} options - The options for init {CompanyLoginOptions} object via {CompanyUtility.initCompanyLoginOptions(options)}.
 */

const loginPageSelectors = {
  emailField: '#userEmail',
  emailContinueButton: '[qaid="emailContinue"]',
  passwordField: '#userPassword',
  auth0PasswordField: '#password',
  passwordContinueButton: '[qaid="passwordContinue"]',
  auth0PasswordContinueButton: 'button[type="submit"][value="default"]',
  authEmail: '.auth-email__welcome-row',
  toastMessage: '.ta-toastr-event__message',
  forgotPassword: '.auth-login__password a',
  auth0ForgotPassword: '[href^="/u/reset-password"]',
  resetButton: '.auth-pwd button.ta-button--primary-theme',
  auth0PasswordResetButton: 'button[type="submit"]',
  resetMessage: '.auth-pwd-sent .auth__form-row:nth-child(2)',
  auth0RestMessage: '[value="resend-email-action"]',
  superAdminToggle: '.mat-slide-toggle-bar',
  auth0LoginPasswordError: '#error-element-password'
};

type AuthMethod = 'legacy' | 'auth0';

export class LoginPage {
  static visitTALoginPage(loginText = 'Welcome to') {
    const NUM_RETRIES = 4; // number of retries
    const RETRY_INTERVAL = Timeouts.SHORT_TIMEOUT_3_SEC.timeout; // interval between retries

    cy.allure().logStep('visit login page');
    cy.visit('app/user2');
    cy.get(loginPageSelectors.authEmail, Timeouts.MEDIUM_TIMEOUT_60_SEC)
      .contains(loginText)
      .should('be.visible');
    let retries = 0;
    let isUrlChecked = false;
    const checkUrl = () => {
      cy.url().then((url) => {
        if (url.includes('/auth')) {
          isUrlChecked = true;
        }
      });
    };
    const checkUrlWithRetry = () => {
      checkUrl();
      if (!isUrlChecked && retries < NUM_RETRIES) {
        retries += 1;
        cy.allure().logStep(`Try count: ${retries}`);
        cy.log(`Try count: ${retries}`);
        cy.wait(RETRY_INTERVAL).then(() => {
          checkUrlWithRetry();
        });
      } else if (!isUrlChecked) {
        cy.url().should('include', '/auth');
      }
    };
    checkUrlWithRetry();
  }

  static visitSuperAdminLoginPage(loginText = 'SuperAdmin') {
    cy.allure().logStep('visit login page');
    cy.visit('app/superAdmin');
    cy.get(loginPageSelectors.authEmail, Timeouts.MEDIUM_TIMEOUT_60_SEC)
      .contains(loginText)
      .should('be.visible');
    cy.url().should('include', '/auth');
  }

  static waitForLoadLoginPage() {
    cy.wait('@waitForLoadLoginPage');
  }

  static clickResetButton() {
    cy.allure().logStep('click reset button');
    cy.get(loginPageSelectors.resetButton).click();
  }

  static verifyLoginWithEmailOptionIsAvailable() {
    cy.get(loginPageSelectors.emailField).should('be.visible');
    cy.allure().logStep('verify login with email option is available');
  }

  static loginWithCredentials(email: string, password: string, authMethod?: AuthMethod) {
    cy.allure().logStep(`login with credentials: ${email}`);
    this.enterEmailAndContinue(email, false);
    this.enterPasswordAndContinue(password, authMethod);
  }

  static superAdminLoginWithCredentials(email: string, password: string) {
    cy.allure().logStep(`login with credentials: ${email}`);
    this.enterEmailAndContinue(email, true);
    this.enterPasswordAndContinue(password);
  }

  static enterEmailAndContinue(email: string, isSuperAdmin: boolean) {
    cy.allure().logStep(`enter login email: ${email}`);
    cy.get(loginPageSelectors.emailField).type(email);
    if (isSuperAdmin) {
      cy.get(loginPageSelectors.superAdminToggle).click();
    }
    cy.get(loginPageSelectors.emailContinueButton).click();
  }

  static enterPasswordAndContinue(password: string, authMethod?: AuthMethod) {
    cy.url().should('include', 'login');
    cy.checkIfExist(loginPageSelectors.auth0PasswordField).then((hasAuth0) => {
      if (authMethod === 'auth0' && !hasAuth0) {
        throw new Error('Auth0 login form not found');
      }
      if (authMethod === 'legacy' && hasAuth0) {
        throw new Error('Auth0 login form found instead of legacy');
      }

      const passwordField = hasAuth0
        ? loginPageSelectors.auth0PasswordField
        : loginPageSelectors.passwordField;
      const passwordContinueButton = hasAuth0
        ? loginPageSelectors.auth0PasswordContinueButton
        : loginPageSelectors.passwordContinueButton;

      cy.get(passwordField).type(password, { log: false });
      // click the *LAST* element
      cy.get(passwordContinueButton).eq(-1).click();
    });
  }

  static clickForgotPassword() {
    cy.allure().logStep(`Click Forgot Password`);
    cy.get(loginPageSelectors.forgotPassword).click();
  }

  static loginWithAuthToken(email: string, password: string, isSA = false) {
    cy.allure().logStep(`login with credentials: ${email}`);
    cy.loginWithAuthToken({ email, password, isSA });
  }

  static clearExistingLoginSession() {
    cy.allure().logStep('clear existing login session');
    cy.clearLocalStorage();
    cy.reload();
  }

  static createNewCompanyAndLoginWithUserByType(
    options: CompanyLoginOptionsInitial = {}
  ): void {
    const companyLoginOptions: CompanyLoginOptions =
      CompanyUtility.initCompanyLoginOptions(options);
    cy.allure().logStep(
      'create new company and login with user from type: ' +
        companyLoginOptions.users.toString()
    );
    cy.initiateCompanyCreationFlow(companyLoginOptions);
  }

  static createHotelBookingForOnBoardingCompany(hotelBookingParams: BookingParams) {
    cy.allure().logStep('create hotel booking for newly created company');
    cy.createHotelBooking(hotelBookingParams);
  }

  static verifyIncorrectLoginMessage(authMethod: AuthMethod) {
    cy.allure().logStep('verify incorrect login message');
    if (authMethod === 'auth0') {
      cy.get(loginPageSelectors.auth0LoginPasswordError)
        .should('be.visible')
        .should('contain.text', 'Wrong username or password');
    } else {
      cy.get(loginPageSelectors.toastMessage).should('be.visible');
    }
  }

  static initiateSignUpFlow(newEmail: string) {
    cy.allure().logStep('initiate user signup flow');
    cy.get(loginPageSelectors.emailField).type(newEmail);
    cy.get(loginPageSelectors.emailContinueButton).click();
  }

  static loginAsCompanyDelegate(password: any) {
    const options = {
      users: [User_Type.DELEGATE]
    };

    LoginPage.createNewCompanyAndLoginWithUserByType(options);
    this.createNewTravelerAndLogin();
    cy.task('getDataFromCache', 'companyCreationEmail').then((email: any) => {
      cy.loginWithAuthToken({ email, password });
    });
  }

  static createNewTravelerAndLogin() {
    cy.task('getDataFromCache', 'userResponse').then((response: any) => {
      cy.addNewTraveler(response.companyDomain);
    });
  }

  static getResetPasswordMessage(email: string) {
    cy.allure().logStep('get reset password message');
    cy.get(loginPageSelectors.resetMessage)
      .should('be.visible')
      .should('contain.text', 'We’ve sent a confirmation email to ' + email);
  }
}
