import faker from '@faker-js/faker';
import { HttpRequest, HttpStatusCodes, Accept } from '../utilities/api';
import {
  AccountToOnboard,
  IAccount,
  IBankAccountParams,
  ILiquidCompanyInfoData,
  IOnboardingPerson
} from '../interface/company';

/**
 * Initiate liquid setup
 * @param authToken
 * @param companyId
 * @param userId
 * @returns Company Id
 */
export function liquidSetup(
  authToken: string,
  companyId: string,
  userId: string
): Cypress.Chainable<string> {
  return cy
    .request({
      method: HttpRequest.Post,
      url: `api/liquid/controlPanel/companies/${companyId}/users/${userId}/onboarding/setup?awsRegion=US_WEST_2`,
      headers: {
        Authorization: authToken,
        Accept: Accept.ApplicationJson
      },
      retryOnStatusCodeFailure: true,
      body: {
        achCreditTransferEnabled: false,
        currency: 'USD'
      }
    })
    .then(({ status }) => {
      expect(status, 'Initiated liquid setup').to.equal(HttpStatusCodes.Ok);
      return companyId;
    });
}

/**
 * Retrieve signup token for liquid
 * @param authToken
 * @returns Liquid on boarding token
 */
export function getLiquidOnboardingAccounts(
  userAuthToken: string
): Cypress.Chainable<AccountToOnboard[]> {
  return cy
    .request({
      method: HttpRequest.Get,
      url: 'api/liquid/user/me',
      headers: {
        Authorization: userAuthToken,
        Accept: Accept.ApplicationJson
      },
      retryOnStatusCodeFailure: true
    })
    .then(({ body, status }) => {
      expect(status, 'accounts to onboard retrieved').to.equal(HttpStatusCodes.Ok);
      const accountsToOnboard: AccountToOnboard[] = body.accountsToOnboard;
      return accountsToOnboard;
    });
}

/**
 * Get account information for given account id
 * @param authToken
 * @param accountId
 * @returns Account information
 */
export function getAccountInformation(
  authToken: string,
  accountId: string
): Cypress.Chainable<IAccount> {
  return cy
    .request({
      method: HttpRequest.Get,
      url: `api/liquid/admin/accounts/${accountId}`,
      headers: {
        Authorization: authToken,
        Accept: Accept.ApplicationJson
      },
      retryOnStatusCodeFailure: true
    })
    .then(({ body, status }) => {
      expect(status, 'Account information retrieved').to.equal(HttpStatusCodes.Ok);
      return body as IAccount;
    });
}

/**
 * Set company info by account id
 * @param authToken
 * @param accountId
 * @param companyInfo
 * @returns Account information
 */
export function setCompanyInfo(
  authToken: string,
  accountId: string,
  companyInfo: ILiquidCompanyInfoData
): Cypress.Chainable<IAccount> {
  const formData: FormData = new FormData();
  formData.append(
    'account',
    new Blob([
      JSON.stringify({
        address: {
          line1: '620 Jones street',
          line2: '',
          city: 'San Francisco',
          state: 'CA',
          postalCode: '94102',
          country: 'US'
        },
        name: companyInfo.name,
        phoneNumber: '+14845219652',
        taxId: '345896745'
      })
    ])
  );
  formData.append('companyVerificationDocumentFront', '');

  return cy
    .request({
      method: HttpRequest.Put,
      url: `/api/liquid/admin/accounts/${accountId}`,
      headers: {
        Authorization: authToken
      },
      retryOnStatusCodeFailure: true,
      body: formData
    })
    .then(({ body, status }) => {
      expect(status, 'Company info updated').to.equal(HttpStatusCodes.Ok);
      return body as IAccount;
    });
}

/**
 * Set personal info by account id
 * @param authToken
 * @param accountId
 * @param email
 * @returns Onboarding Person
 */
export function setPersonalInfo(
  authToken: string,
  accountId: string,
  email: string
): Cypress.Chainable<IOnboardingPerson> {
  const formData: FormData = new FormData();
  formData.append(
    'person',
    new Blob([
      JSON.stringify({
        birthdate: '1990-12-12',
        email: email,
        familyName: faker.name.lastName().replace(/'/g, ''),
        givenName: faker.name.firstName(),
        phoneNumber: '+14845219652',
        ssnLast4: '3214',
        title: 'SDT',
        address: {
          line1: '620 Jones street',
          line2: null,
          city: 'San Fransisco',
          state: 'CA',
          postalCode: '94102',
          country: 'US'
        }
      })
    ])
  );
  formData.append('identityDocumentFront', '');
  formData.append('additionalDocumentFront', '');

  return cy
    .request({
      method: HttpRequest.Put,
      url: `/api/liquid/admin/accounts/${accountId}/opener`,
      headers: {
        Authorization: authToken
      },
      retryOnStatusCodeFailure: true,
      body: formData
    })
    .then(({ status, body }) => {
      expect(status, 'Personal info updated').to.equal(HttpStatusCodes.Ok);
      return body as IOnboardingPerson;
    });
}

/**
 * Setup company bank account
 * @param authToken
 * @param accountId
 * @param bankAccountParams
 * @returns Bank account information
 */
export function setupCompanyBankAccount(
  authToken: string,
  accountId: string,
  bankAccountParams: IBankAccountParams
) {
  return cy
    .request({
      method: HttpRequest.Put,
      url: `api/liquid/admin/accounts/${accountId}/bankAccount`,
      headers: {
        Authorization: authToken
      },
      retryOnStatusCodeFailure: true,
      body: bankAccountParams
    })
    .then(({ status, body }) => {
      expect(status, 'Bank account setup').to.equal(HttpStatusCodes.Ok);
      return body;
    });
}

/**
 * Complete Liquid on boarding
 * @param authToken
 * @param accountToOnboard
 */
export function completeLiquidOnboarding(authToken: string, accountToOnboard: string) {
  cy.request({
    method: HttpRequest.Post,
    url: `api/liquid/admin/accounts/${accountToOnboard}/complete`,
    headers: {
      Authorization: authToken
    },
    retryOnStatusCodeFailure: true
  }).then(({ status }) => {
    expect(status, 'Liquid onboarding completed').to.equal(HttpStatusCodes.Ok);
  });
}
