/**
 * Account information PNZ-API-CentreLib
 *
 * This file was automatically generated by APIMATIC v3.0 ( https://www.apimatic.io ).
 */

import { ApiResponse, RequestOptions } from '../core';
import {
  AC1Initiateclientcredentialsgrant,
  aC1InitiateclientcredentialsgrantSchema,
} from '../models/aC1Initiateclientcredentialsgrant';
import {
  AC2Createaccountaccessconsent,
  aC2CreateaccountaccessconsentSchema,
} from '../models/aC2Createaccountaccessconsent';
import { contentTypeEnumSchema } from '../models/contentTypeEnum';
import { string } from '../schema';
import { BaseController } from './baseController';
import { v4 as uuidv4 } from 'uuid';
import { ClientAssertionJWT } from '../utils';

export class SetupAccountAccessConsentsResourceController extends BaseController {
  /**
   * 
   * This step initiates a client credentials grant request for accounts-related activity. 
   * It requires a properly registered application with valid credentials in order to access its resources. 
   * Once you've registered your own Application, you will receive the ClientId, ClientSecret by setting up KeyId, PublicKey, RedirectURI 
   * to reflect details for your own Application. 
   * To call the method, you will need to provide the corresponding PrivateKey of the PublicKey that was entered in the application.
   *
   * @param clientID
   * @param privateKey
   * @param KID
   * @return Response from the API call
   */
  async initiateClientCredentialsGrant(
    clientID: string,
    privateKey: string,
    KID: string,
    requestOptions?: RequestOptions
  ): Promise<ApiResponse<AC1Initiateclientcredentialsgrant>> {
    const req = this.createRequest('POST', '/oauth/v2.0/token');
    req.baseUrl('server 1');
    const contentType = 'application/x-www-form-urlencoded';
    const grantType = 'client_credentials';
    const clientAssertionType =
      'urn:ietf:params:oauth:client-assertion-type:jwt-bearer';
    const scope = 'openid accounts';
    const payload: {
      sub: string;
      aud: string;
      iss: string;
      exp: number;
      iat: number;
      jti: string;
    } = {
      sub: clientID,
      aud: 'https://api-nomatls.apicentre.middleware.co.nz/oauth/v2.0/token',
      iss: clientID,
      exp: Math.floor(Date.now() / 1000) + 3599,
      iat: Math.floor(Date.now() / 1000) - 120,
      jti: uuidv4(),
    };
    const clientAssertion = ClientAssertionJWT(privateKey, KID, payload);
    const mapped = req.prepareArgs({
      contentType: [contentType, contentTypeEnumSchema],
      grantType: [grantType, string()],
      scope: [scope, string()],
      clientAssertion: [clientAssertion, string()],
      clientAssertionType: [clientAssertionType, string()],
    });
    req.header('Content-Type', mapped.contentType);
    req.form({
      grant_type: mapped.grantType,
      scope: mapped.scope,
      client_assertion: mapped.clientAssertion,
      client_assertion_type: mapped.clientAssertionType,
    });
    return req.callAsJson(
      aC1InitiateclientcredentialsgrantSchema,
      requestOptions
    );
  }

  /**
   * This step creates an account-access-consents resource.
   *
   * Preconditions:
   * + This step relies on the presence of an AccountAccessToken variable, which is
   * set upon successful completion of Step AC1 - Initiate client credentials grant.
   *
   * Response:
   * + The response should be an account-access-consents object, with a status 'AwaitingAuthorisation'.
   *
   * Troubleshooting:
   * + The most likely cause of errors is that the step is being attempted out of sequence. Be sure to
   * follow the steps in sequence
   * + Another likely cause of errors are out of date variable values. Try starting from Step AC1 -
   * Initiate client credentials grant again.
   *
   * @param authorization
   * @return Response from the API call
   */
  async createAccountAccessConsent(
    authorization: string,
    requestOptions?: RequestOptions
  ): Promise<ApiResponse<AC2Createaccountaccessconsent>> {
    const req = this.createRequest(
      'POST',
      '/open-banking-nz/v2.3/account-access-consents'
    );
    req.baseUrl('server 1');
    const accept = 'application/json';
    let date: Date = new Date();
    date.setDate(date.getDate() + 2);
    let datestring = '"' + date.toISOString() + '"';
    const body: string = `{
      "Data": {
          "Consent": {
              "TransactionToDateTime": "2025-05-08T00:00:00-00:00",
              "ExpirationDateTime": ${datestring},
              "Permissions": [
                  "ReadAccountsDetail",
                  "ReadBalances",
                  "ReadBeneficiariesDetail",
                  "ReadDirectDebits",
                  "ReadParty",
                  "ReadPartyAuthUser",
                  "ReadOffers",
                  "ReadScheduledPaymentsDetail",
                  "ReadStandingOrdersDetail",
                  "ReadStatementsBasic",
                  "ReadStatementsDetail",
                  "ReadTransactionsDetail",
                  "ReadTransactionsCredits",
                  "ReadTransactionsDebits"
              ],
              "TransactionFromDateTime": "2012-05-03T00:00:00-00:00"
          }
      },
      "Risk": {
          "EndUserAppName": "This is an app name that is long",
          "EndUserAppVersion": "App Version3.0",
          "PaymentContextCode": "EcommerceServices",
          "MerchantName": "This is a merchant name that is long",
          "MerchantNZBN": "This is an NZBN number",
          "MerchantCategoryCode": "5967",
          "MerchantCustomerIdentification": "This is a special customer identifier",
          "GeoLocation": {
              "Latitude": "45.516136",
              "Longitude": "-73.656830"
          },
          "DeliveryAddress": {
              "AddressLine": [
                  "This is address line 1"
              ],
              "StreetName": "Main Street",
              "BuildingNumber": "12345",
              "PostCode": "12345",
              "TownName": "Some Town",
              "CountrySubDivision": "Some Subdivision",
              "Country": "CA"
          }
      }
  }`;
    const mapped = req.prepareArgs({
      accept: [accept, string()],
      body: [body, string()],
      authorization: [authorization, string()],
    });
    req.header('Accept', mapped.accept);
    req.header('Content-Type', 'application/json');
    req.header('authorization', mapped.authorization);
    req.text(mapped.body);
    return req.callAsJson(aC2CreateaccountaccessconsentSchema, requestOptions);
  }
}
