import 'reflect-metadata';
import axios from 'axios';
import { plainToClass } from 'class-transformer';
import { CreateOrderRequest } from '../RequestDTOs/CreateOrderRequest';
import { PayOutPaymentRequestBuilder } from '../RequestDTOs/PayOutPaymentRequest';
import { QueryOrderResultBuilder } from '../RequestDTOs/QueryOrderResultRequest';
import { VerifyUtil } from '../Utils/VerifyUtil';
import { verify } from 'crypto';
import { ErrorResponse } from '../ResponseDTOs/ErrorResponse';
import {  createHeader, removeUndefinedValues, transformUndefinedToNull } from '../Utils/Util'; 
import { BuildPayload } from '../RequestDTOs/PaymentRequest';
import { createSign } from '../Utils/Util';
import { CreateVirtualAccountResponse } from '../ResponseDTOs/CreateVirtualAccountResponse';
import { QueryPayInResponse } from '../ResponseDTOs/QueryPayInResponse';
import { PayInCreateOrderResponse } from '../ResponseDTOs/PayInCreateOrderResponse';
import { BulkQueryPayInResponse } from '../ResponseDTOs/BulkQueryPayInResponse';
import { API_ENDPOINTS_LIVE, API_ENDPOINTS_SANDBOX  } from '../EndpointsConstant'; 


export class VirtualAccountService {

 

    constructor(
        private appId: string,
        private countryCode: string,
        private privateKey: string,
        private isTest: boolean
      ) {
        this.appId = appId
        this.countryCode = countryCode;
        this.privateKey = privateKey;
        this.isTest = isTest
      }
    
      private getCountryCode() {
        return this.countryCode
    
      }
    
      private getAppId() {
        return this.appId
    
      }
    
      private getPrivateKey() {
        return this.privateKey
    
      }

      private getIsTest() {
        return this.isTest
    
      }  

  async createVirtualAccount(builder: BuildPayload): Promise<PayInCreateOrderResponse<CreateVirtualAccountResponse>>{
    const createVirtualAccountRequest = builder.build();
    
    try {
        const createVirtualAccountEndpoint = this.isTest ? API_ENDPOINTS_SANDBOX.CREATE_VIRTUAL_ACCOUNT : API_ENDPOINTS_LIVE.CREATE_VIRTUAL_ACCOUNT;
      const signedRequest = createSign(builder, this.privateKey)
        const header = createHeader(this.countryCode,signedRequest, 'Bearer '.concat(this.appId),'application/json')  
        const response = await axios.post(createVirtualAccountEndpoint, createVirtualAccountRequest.toJSON(), { headers: header });
        console.log("CreateVirtualAccount Response: ",response.data)
      return response.data;


    } catch (error) {
      if (axios.isAxiosError(error)) {
        throw new Error(`Error message: ${error.message}`);
      } else {
        console.log("Unexpected error", error)
        throw new Error
      }
    }
  }


  async updateVirtualAcctStatus(builder: BuildPayload): Promise<PayInCreateOrderResponse>{
    const updateVirtualAcctStatus = builder.build();
    
    try {
        const updateVirtualAcctStatusEndpoint = this.isTest ? API_ENDPOINTS_SANDBOX.UPDATE_VIRTUAL_ACCOUNT_STATUS : API_ENDPOINTS_LIVE.UPDATE_VIRTUAL_ACCOUNT_STATUS;
      const signedRequest = createSign(builder, this.privateKey)
        const header = createHeader(this.countryCode,signedRequest, 'Bearer '.concat(this.appId),'application/json')  
        const response = await axios.post(updateVirtualAcctStatusEndpoint, updateVirtualAcctStatus.toJSON(), { headers: header });
        console.log("updateVirtualAcctStatus Response: ",response.data)
      return response.data;


    } catch (error) {
      if (axios.isAxiosError(error)) {
        throw new Error(`Error message: ${error.message}`);
      } else {
        console.log("Unexpected error", error)
        throw new Error
      }
    }
  }

  async deleteVirtualAccount(builder: BuildPayload): Promise<PayInCreateOrderResponse>{
    const deleteVirtualAccount = builder.build();
    
    try {
        const deleteVirtualAccountEndpoint = this.isTest ? API_ENDPOINTS_SANDBOX.DELETE_VIRTUAL_ACCOUNT : API_ENDPOINTS_LIVE.DELETE_VIRTUAL_ACCOUNT;
      const signedRequest = createSign(builder, this.privateKey)
        const header = createHeader(this.countryCode,signedRequest, 'Bearer '.concat(this.appId),'application/json')  
        const response = await axios.post(deleteVirtualAccountEndpoint, deleteVirtualAccount.toJSON(), { headers: header });
        console.log("deleteVirtualAccount Response: ",response.data)
      return response.data;


    } catch (error) {
      if (axios.isAxiosError(error)) {
        throw new Error(`Error message: ${error.message}`);
      } else {
        console.log("Unexpected error", error)
        throw new Error
      }
    }
  }


  async queryVirtualAccount(builder: BuildPayload): Promise<PayInCreateOrderResponse<CreateVirtualAccountResponse>>{
    const queryVirtualAccount = builder.build();
    
    try {
        const queryVirtualAccountEndpoint = this.isTest ? API_ENDPOINTS_SANDBOX.QUERY_VIRTUAL_ACCOUNT : API_ENDPOINTS_LIVE.QUERY_VIRTUAL_ACCOUNT;
      const signedRequest = createSign(builder, this.privateKey)
        const header = createHeader(this.countryCode,signedRequest, 'Bearer '.concat(this.appId),'application/json')  
        const response = await axios.post(queryVirtualAccountEndpoint, queryVirtualAccount.toJSON(), { headers: header });
        console.log("queryVirtualAccount Response: ",response.data)
      return response.data;


    } catch (error) {
      if (axios.isAxiosError(error)) {
        throw new Error(`Error message: ${error.message}`);
      } else {
        console.log("Unexpected error", error)
        throw new Error
      }
    }
  }

  
  async querySinglePayInOrder(builder: BuildPayload): Promise<PayInCreateOrderResponse<QueryPayInResponse>>{
    const queryVirtualAccount = builder.build();
    
    try {
        const querySinglePayInOrderEndpoint = this.isTest ? API_ENDPOINTS_SANDBOX.QUERY_SINGLE_PAY_IN_ORDER : API_ENDPOINTS_LIVE.QUERY_SINGLE_PAY_IN_ORDER;
      const signedRequest = createSign(builder, this.privateKey)
        const header = createHeader(this.countryCode,signedRequest, 'Bearer '.concat(this.appId),'application/json')  
        const response = await axios.post(querySinglePayInOrderEndpoint, queryVirtualAccount.toJSON(), { headers: header });
        console.log("queryVirtualAccount Response: ",response.data)
      return response.data;


    } catch (error) {
      if (axios.isAxiosError(error)) {
        throw new Error(`Error message: ${error.message}`);
      } else {
        console.log("Unexpected error", error)
        throw new Error
      }
    }
  }

  async queryBulkPayInOrder(builder: BuildPayload): Promise<PayInCreateOrderResponse<BulkQueryPayInResponse>>{
    const queryBulkPayInOrder = builder.build();
    
    try {
        const queryBulkPayInOrderEndpoint = this.isTest ? API_ENDPOINTS_SANDBOX.QUERY_BULK_PAY_IN_ORDER : API_ENDPOINTS_LIVE.QUERY_BULK_PAY_IN_ORDER;
      const signedRequest = createSign(builder, this.privateKey)
        const header = createHeader(this.countryCode,signedRequest, 'Bearer '.concat(this.appId),'application/json')  
        const response = await axios.post(queryBulkPayInOrderEndpoint, queryBulkPayInOrder.toJSON(), { headers: header });
        console.log("queryBulkPayInOrder Response: ",response.data)
      return response.data;


    } catch (error) {
      if (axios.isAxiosError(error)) {
        throw new Error(`Error message: ${error.message}`);
      } else {
        console.log("Unexpected error", error)
        throw new Error
      }
    }
  }
  
}
