import { HttpRequest, Random, loginRequest } from 'cypress/artifacts';
import { CompanyAccountType, CompanySegmentType, CreateCompany, LaunchCompany } from './onboarding-guide.utils';
import { faker } from '@faker-js/faker';
import { CreateAccountPage } from '@onboarding-lib/index';
import { Timeouts } from '@utility-lib/constants';
import { Logs } from '@utility-lib/log';
const adminCreds = Cypress.env('newUser').NEW_USER_PASSWORD;

export class NewAccount {
  static companyEmail = '';
  static randomDomain = '';
  static SAToken = '';

  static createNewAccount(newAccountPayload: CreateCompany, launchCompany?: LaunchCompany) {
    const {
      accountSegment = CompanySegmentType.COMMERCIAL,
      accountType = CompanyAccountType.TRAVEL,
      onboardingCompanySource,
      address
    } = newAccountPayload;
    const randomId = Random.randomString(6);
    NewAccount.randomDomain = `${accountSegment.toLowerCase()}${randomId}.xyz`;
    const email = `cypress-traditional-onboarding-${randomId}@${NewAccount.randomDomain}`;
    const familyName = faker.name.lastName().replace(/'/g, '');
    const givenName = faker.name.firstName();

    const getCompanyPayload = (uuid: string): CreateCompany => ({
      category: 'COMMERCIAL',
      ae: uuid,
      globalCsm: uuid,
      launchManager: uuid,
      accountSegment,
      accountType,
      companyName: randomId,
      companyDomain: NewAccount.randomDomain,
      isLHGCustomer: false,
      lhgPriceModel: 'free',
      admin: {
        email,
        familyName,
        givenName
      },
      ...(onboardingCompanySource && { onboardingCompanySource }),
      ...(address && { address })
    });

    const getLaunchPayload = (company: { uuid: string }): LaunchCompany => ({
      companyUuid: company.uuid,
      billableEntityCountryCode: 'US',
      liquidCurrencyCode: 'USD',
      tripFee: launchCompany?.tripFee ?? '25',
      liquidApprovedLimit: launchCompany?.liquidApprovedLimit ?? '0',
      inviteToSelfOnboarding: launchCompany?.inviteToSelfOnboarding ?? 'YES',
      associateAgency: false,
      isComtravoOnboarding: false,
      admin: {
        email,
        givenName,
        familyName
      }
    });

    return NewAccount.getUserInfo().then(({ sub }) =>
      NewAccount.createCompany(getCompanyPayload(sub)).then(({ company }) =>
        NewAccount.launchCompany(getLaunchPayload(company)).then(() =>
          NewAccount.getSignUpToken(email).then((signupToken: string) =>
            NewAccount.createAccount({ email, signupToken, givenName, familyName })
          )
        )
      )
    );
  }

  static createAccount({
    email,
    signupToken,
    givenName,
    familyName
  }: {
    email: string;
    signupToken: string;
    givenName: string;
    familyName: string;
  }) {
    console.info(`%c ${email}`, 'background: black; color: lightgreen');
    Logs.logToCypressAndAllure(`*** email ${email}`);
    Logs.logToCypressAndAllure(`*** signupToken ${signupToken}`);
    NewAccount.visitCreateAccountPageWithToken(email, signupToken);
    CreateAccountPage.fillUserDetailsAndPassword(givenName, familyName, adminCreds);
    CreateAccountPage.createAccountButton();
    return loginRequest(email, adminCreds);
  }

  static visitCreateAccountPageWithToken(email: string, signupToken?: string) {
    Logs.logToCypressAndAllure(`*** /signup?token=${signupToken}&email=${email}`);
    cy.visit(`/signup?token=${signupToken}&email=${email}`);
    cy.get('.signup-welcome').should('be.visible');
    cy.wait('@waitForEmail');
    cy.wait(Timeouts.SHORT_TIMEOUT_5_SEC.timeout);
  }

  static createCompany(body: CreateCompany): Cypress.Chainable<any> {
    Logs.logToCypressAndAllure(`*** createCompany ${body}`);
    return cy
      .request({
        method: HttpRequest.Post,
        url: '/api/superAdmin/selfonboarding/v2/company',
        headers: {
          Authorization: NewAccount.SAToken
        },
        body,
        retryOnStatusCodeFailure: true
      })
      .then((xhr) => Logs.logResponseStatusAndBody(xhr))
      .then(({ body }) => {
        return body;
      });
  }

  static launchCompany(body: LaunchCompany): Cypress.Chainable<any> {
    Logs.logToCypressAndAllure(`*** launchPayload ${body}`);
    return cy
      .request({
        method: HttpRequest.Put,
        url: '/api/superAdmin/selfonboarding/v2/confirm',
        headers: {
          Authorization: NewAccount.SAToken
        },
        body,
        retryOnStatusCodeFailure: true
      })
      .then((xhr) => Logs.logResponseStatusAndBody(xhr))
      .then(({ body }) => {
        return body;
      });
  }

  static getSignUpToken(email: string): Cypress.Chainable<any> {
    return cy
      .request({
        method: HttpRequest.Get,
        url: '/api/superAdmin/signupToken?email=' + email,
        headers: {
          Authorization: NewAccount.SAToken
        },
        retryOnStatusCodeFailure: true
      })
      .then((xhr) => Logs.logResponseStatusAndBody(xhr))
      .then(({ body }) => {
        return body;
      });
  }

  static getUserInfo(): Cypress.Chainable<any> {
    return cy
      .request({
        method: HttpRequest.Get,
        url: `/api/uaa/userinfo`,
        headers: {
          Authorization: NewAccount.SAToken
        },
        retryOnStatusCodeFailure: true
      })
      .then((xhr) => Logs.logResponseStatusAndBody(xhr))
      .then(({ body }) => {
        return body;
      });
  }

  static setupUser(email: string): Cypress.Chainable<any> {
    const familyName = faker.name.lastName().replace(/'/g, '');
    const givenName = faker.name.firstName();
    return NewAccount.getSignUpToken(email).then((signupToken) =>
      NewAccount.createAccount({ email, signupToken, givenName, familyName })
    );
  }
}
