import thesoap from "soap";
let soap: any = thesoap;
try {
  soap = require("soap");
} catch (error) {
  //my hackish way to make soap work on both esm and cjs
  //theshoap on esm is undefined
  //On esm require is not defined, however on cjs require can be used.
  //So we try to use require and if it fails we use the thesoap module
}

import { AuditRecord } from "@digigov-oss/gsis-audit-record-db";

/**
 * SOAP client
 * @class Soap
 * @description SOAP client
 * @param {string} wsdl - The URL of the SOAP service
 * @param {string} username
 * @param {string} password
 * @param {AuditRecord} auditRecord
 * @param {string} endpoint
 */
class Soap {
  private _wsdl: string;
  private _username: string;
  private _password: string;
  private _auditRecord: AuditRecord;
  private _endpoint: string;

  constructor(
    wsdl: string,
    username: string,
    password: string,
    auditRecord: AuditRecord,
    endpoint: string
  ) {
    this._wsdl = wsdl;
    this._username = username;
    this._password = password;
    this._auditRecord = auditRecord;
    this._endpoint = endpoint;
  }

  public async init() {
    try {
      const client = await soap.createClientAsync(this._wsdl, {
        wsdl_headers: {
          Authorization:
            "Basic " +
            Buffer.from(`${this._username}:${this._password}`).toString(
              "base64"
            ),
        },
      });
      if (this._endpoint) {
        client.setEndpoint(this._endpoint);
      }
      return client;
    } catch (e) {
      throw e;
    }
  }

  public async getValidDisabilityCertification(amka: string, date: string) { 
    try {
      const client = await this.init();
      var options = {
        hasNonce: true,
        actor: "actor",
      };
      var wsSecurity = new soap.WSSecurity(
        this._username,
        this._password,
        options
      );
      client.setSecurity(wsSecurity);
      const auditRecord = this._auditRecord;
      const args = {
        auditRecord: auditRecord,
        getValidDisabilityCertificationInputRecord: {
          amka: amka,
          date: date
        },
      };
      const result = await client.getValidDisabilityCertificationInputRecordAsync(args);
      const errorRecord = result[0].errorRecord;
      if (errorRecord) {
        return errorRecord;
      } else {
        return result[0].getValidDisabilityCertificationOutputRecord;
      }
    } catch (e) {
      throw e;
    }
  }

  public async getValidDisabilityCertPerc(amka: string, date: string) { 
    try {
      const client = await this.init();
      var options = {
        hasNonce: true,
        actor: "actor",
      };
      var wsSecurity = new soap.WSSecurity(
        this._username,
        this._password,
        options
      );
      client.setSecurity(wsSecurity);
      const auditRecord = this._auditRecord;
      const args = {
        auditRecord: auditRecord,
        getValidDisabilityCertPercInputRecord: {
          amka: amka,
          date: date
        },
      };
      const result = await client.getValidDisabilityCertPercAsync(args);
      const errorRecord = result[0].errorRecord;
      if (errorRecord) {
        return errorRecord;
      } else {
        return result[0].getValidDisabilityCertPercOutputRecord;
      }
    } catch (e) {
      throw e;
    }
  }  

}

export default Soap;
