import { LinkErrorTypes } from '../utils/error-types';
import { LinkPayEnvironment } from '../types/link-pay-environment';

export enum LinkCustomerStatus {
  Active = 'ACTIVE',
  Created = 'CREATED',
}

export enum LinkAccountStatus {
  Active = 'ACTIVE',
  Inactive = 'INACTIVE',
  Abandon = 'ABANDON',
  Created = 'CREATED',
}

export enum LinkAccountType {
  Checking = 'checking',
  Savings = 'savings',
}

export interface LinkCustomerAccount {
  accountId?: string;
  financialInstitutionId?: number;
  financialInstitutionName?: string;
  logoUrl?: string; // logo of financial institution logo
  iconUrl?: string; // logo of financial institution icon
  lastFour?: string;
  type?: LinkAccountType;
  status?: LinkAccountStatus;
  preferred?: boolean; // preferred account of customer.
  creationDate?: string;
}

export interface LinkCustomerDetails {
  id: string;
  creationDate: string;
  firstName?: string;
  lastName?: string;
  email?: string;
  status?: LinkCustomerStatus;
}

export class LinkService {
  accessToken: string;
  environment: LinkPayEnvironment;
  host: string;

  constructor(
    accessToken: string,
    environment: LinkPayEnvironment = LinkPayEnvironment.sandbox
  ) {
    this.accessToken = accessToken;
    this.environment = environment;

    this.host =
      this.environment === LinkPayEnvironment.production
        ? 'https://api.link.money'
        : 'https://api.link-sandbox.money';
  }

  getCustomer = async (customerId: string) => {
    if (!customerId) {
      throw new Error(LinkErrorTypes.invalidParameters);
    }
    if (customerId.length !== 36)
      throw new Error(LinkErrorTypes.invalidCustomerId);

    let results = await fetch(`${this.host}/v1/customers/${customerId}`, {
      method: 'get',
      headers: {
        'content-type': 'application/json',
        Authorization: `Bearer ${this.accessToken}`,
      },
    });
    if (results.ok) {
      let json: any = await results.json();
      return {
        status: json.customerStatus,
        creationDate: json.creationDate,
        email: json.email,
        firstName: json.firstName,
        lastName: json.lastName,
        id: json.id,
      };
    } else {
      throw new Error(
        LinkErrorTypes.genericResponseErr(
          results.status,
          new Error(results.statusText)
        )
      );
    }
  };

  getAccounts = async (customerId: string) => {
    if (!customerId) {
      throw new Error(LinkErrorTypes.invalidParameters);
    }
    if (customerId.length !== 36)
      throw new Error(LinkErrorTypes.invalidCustomerId);

    let results = await fetch(
      `${this.host}/v1/customers/${customerId}/accounts`,
      {
        method: 'get',
        headers: {
          'content-type': 'application/json',
          Authorization: `Bearer ${this.accessToken}`,
        },
      }
    );
    if (results.ok) {
      let json: any = await results.json();
      const accounts = [];
      for (const account of json.accountDetails) {
        accounts.push({
          accountId: account.accountId,
          creationDate: account.creationDate,
          financialInstitutionId: account.financialInstitutionId,
          financialInstitutionName: account.financialInstitutionName,
          preferred: account.preferred,
          lastFour: account.accountLastFourDigits,
          status: account.accountStatus,
          type: account.accountType,
          iconUrl: account.iconUrl,
          logoUrl: account.logoUrl,
        });
      }
      return accounts;
    } else {
      throw new Error(
        LinkErrorTypes.genericResponseErr(
          results.status,
          new Error(results.statusText)
        )
      );
    }
  };
}
