import {
  completeLiquidOnboarding,
  getAccountInformation,
  getLiquidOnboardingAccounts,
  liquidSetup,
  setCompanyInfo,
  setPersonalInfo,
  setupCompanyBankAccount
} from './liquid';
import { AccountToOnboard, IAccount } from '../interface/company';
import { loginRequest } from '../admin/login';
import {
  addPersonalPaymentMethod,
  addPhoneNumber,
  addUserAgency,
  completeOnboarding,
  createAccount,
  createCompany,
  getSignUpToken,
  isUserRegistered,
  retrieveUserByEmail,
  sendPreSignupEmail,
  setTravelFrequency,
  setUserType,
  updatePassengerInfoDefault
} from './onboard';
import { addOffice, createLegalEntity } from './organization';
import { getUsersList, updateUserConfigurations } from './user';

export class LiquidCompanySetupHelper {
  activeAccountId = '';
  currentUserEmail = '';
  currentUserPassword: string;
  superAdminLogin: string;
  superAdminPassword: string;

  constructor(
    superAdminLogin: string,
    superAdminPassword: string,
    currentUserPassword: string
  ) {
    this.superAdminLogin = superAdminLogin;
    this.superAdminPassword = superAdminPassword;
    this.currentUserPassword = currentUserPassword;
  }

  createCompanyAndCompleteOnboarding(): Cypress.Chainable<{
    email: string;
    password: string;
  }> {
    let userToken = '';
    return this.createCompanyForExpense()
      .then((userInfo) => {
        userToken = userInfo.userToken;
        return getLiquidOnboardingAccounts(userInfo.userToken);
      })
      .then((liquidToken: AccountToOnboard[]) => {
        this.activeAccountId = liquidToken[0].id;
        return getAccountInformation(userToken, this.activeAccountId);
      })
      .then((accountInfo: IAccount) => {
        return setCompanyInfo(userToken, this.activeAccountId, {
          name: accountInfo.name || 'ABC Inc.',
          phoneNumber: accountInfo.phoneNumber || '+14157483333',
          taxId: accountInfo.taxId || '123456789',
          line1: accountInfo.address.line1 || '123 Main St',
          line2: '',
          city: accountInfo.address.city || 'San Francisco',
          state: accountInfo.address.state || 'CA',
          postalCode: accountInfo.address.postalCode || '94105',
          country: accountInfo.address.country || 'US'
        });
      })
      .then(() => setPersonalInfo(userToken, this.activeAccountId, this.currentUserEmail))
      .then(() =>
        setupCompanyBankAccount(userToken, this.activeAccountId, {
          accountHolderName: 'Michael Scott',
          routingNumber: '110000000',
          accountNumber: '000123456789'
        })
      )
      .then(() => completeLiquidOnboarding(userToken, this.activeAccountId))
      .then(() => {
        return { email: this.currentUserEmail, password: this.currentUserPassword };
      });
  }

  createCompanyForExpense(): Cypress.Chainable<{
    email: string;
    password: string;
    userToken: string;
  }> {
    let activeToken = '';
    let userToken = '';

    return loginRequest(this.superAdminLogin, this.superAdminPassword, true)
      .then((token) => {
        activeToken = token;
        return createCompany(token);
      })
      .then((companyResponse) =>
        addUserAgency(activeToken, companyResponse.uuid, companyResponse.domain)
      )
      .then((agencyResponse) => {
        return isUserRegistered(activeToken, agencyResponse.companyId);
      })
      .then((userEmailResponse) => sendPreSignupEmail(activeToken, userEmailResponse))
      .then((signUpEmailResponse) => getSignUpToken(activeToken, signUpEmailResponse))
      .then((tokenResponse) =>
        createAccount(
          activeToken,
          tokenResponse.email,
          tokenResponse.body,
          this.currentUserPassword
        )
      )
      .then((accountResponse) => retrieveUserByEmail(activeToken, accountResponse))
      .then((emailResponse) => setUserType(activeToken, emailResponse.uuid, 'admin'))
      .then((userTypeResponse) => {
        this.currentUserEmail = userTypeResponse.email;
        return loginRequest(this.currentUserEmail, this.currentUserPassword);
      })
      .then((userLoginToken) => {
        userToken = userLoginToken;
        return setTravelFrequency(userToken);
      })
      .then(() => addPhoneNumber(userToken))
      .then(() => completeOnboarding(userToken))
      .then(() => updatePassengerInfoDefault(userToken))
      .then(() => addPersonalPaymentMethod(userToken))
      .then(() => createLegalEntity(userToken))
      .then((legalEntityResponse) => {
        // use agencyCompanyAssociationUuid to add office
        return addOffice(userToken, legalEntityResponse.uuid);
      })
      .then(() => getUsersList(userToken))
      .then((userListResponse) =>
        updateUserConfigurations(userToken, userListResponse._embedded.users[0].uuid, {
          department: 'AMS'
        })
      )
      .then((updateUserResponse) =>
        liquidSetup(activeToken, updateUserResponse.companyUuid, updateUserResponse.uuid)
      )
      .then(() => loginRequest(this.currentUserEmail, this.currentUserPassword))
      .then((newUserToken) => {
        return {
          email: this.currentUserEmail,
          password: this.currentUserPassword,
          userToken: newUserToken
        };
      });
  }
}
