import 'reflect-metadata';
import axios from 'axios';
import { plainToClass } from 'class-transformer';
import { BuildPayload } from '../RequestDTOs/PaymentRequest';
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 '../PayloadBuilders/BuildPayload';
import { createSign } from '../Utils/Util';
import { PayOutResponse } from '../ResponseDTOs/PayOutResponse';
import { QueryBankAccountResponse } from '../ResponseDTOs/QueryBankAccountResponse';
import { PayInCreateOrderResponseData } from '../ResponseDTOs/PayInCreateOrderResponseData';
import { PayInCreateOrderResponse } from '../ResponseDTOs/PayInCreateOrderResponse';
import { TransactionResultsResponse } from '../ResponseDTOs/TransactionResultsResponse';
import { MerchantBalanceResponse } from '../ResponseDTOs/MerchantBalanceResponse';
import { BankDetailsList } from '../ResponseDTOs/BankDetailsList';
import { API_ENDPOINTS_LIVE, API_ENDPOINTS_SANDBOX  } from '../EndpointsConstant'; 




export class PayOutService {

 

    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 createOrder(builder: BuildPayload): Promise<PayInCreateOrderResponse<PayInCreateOrderResponseData>>{
    const createOrderRequest = builder.build();
    
    try {
        const createOrderEndpoint = this.isTest ? API_ENDPOINTS_SANDBOX.CREATE_ORDER : API_ENDPOINTS_LIVE.CREATE_ORDER;
      const signedRequest = createSign(builder, this.privateKey)
        const header = createHeader(this.countryCode,signedRequest, 'Bearer '.concat(this.appId),'application/json')  
        const response = await axios.post(createOrderEndpoint, createOrderRequest.toJSON(), { headers: header });
        console.log("PayOut Response Data: ",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 fetchOrderStatus(builder: QueryOrderResultBuilder): Promise<PayInCreateOrderResponse<TransactionResultsResponse>> {
    const orderStatusRequest = builder.build();
    console.log(`Order Request: ${orderStatusRequest.toJSON}`)
    try {
        const orderStatusEndpoint = this.isTest ? API_ENDPOINTS_SANDBOX.ORDER_STATUS : API_ENDPOINTS_LIVE.ORDER_STATUS;
      const signedRequest = createSign(builder, this.privateKey);
      const header = createHeader(this.countryCode,signedRequest, 'Bearer '.concat(this.appId),'application/json'); 
      const response = await axios.post(orderStatusEndpoint, orderStatusRequest.toJSON(), { headers: header });
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error)) {
        throw new Error(`Error message: ${error.message}`);
      } else {
        throw new Error('Unexpected error');
      }
    }
  }

  async queryMerchantBalance2(builder: BuildPayload): Promise<PayInCreateOrderResponse<MerchantBalanceResponse>>{
    const merchantBalanceRequest = builder.build();
    
    try {
        const queryMerchantBalanceEndpoint = this.isTest ? API_ENDPOINTS_SANDBOX.QUERY_MERCHANT_BALANCE : API_ENDPOINTS_LIVE.QUERY_MERCHANT_BALANCE;
      const signedRequest = createSign(builder, this.privateKey)
        const header = createHeader(this.countryCode,signedRequest, 'Bearer '.concat(this.appId),'application/json')  
        const response = await axios.post(queryMerchantBalanceEndpoint, merchantBalanceRequest.toJSON(), { headers: header });
        console.log("queryMerchantBalance Response Data: ",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 queryBankList(builder: BuildPayload): Promise<PayInCreateOrderResponse<BankDetailsList>>{
    const queryBankListRequest = builder.build();
    
    try {
        const queryBankListEndpoint = this.isTest ? API_ENDPOINTS_SANDBOX.QUERY_BANK_LIST : API_ENDPOINTS_LIVE.QUERY_BANK_LIST;
      const signedRequest = createSign(builder, this.privateKey)
        const header = createHeader(this.countryCode,signedRequest, 'Bearer '.concat(this.appId),'application/json')  
        const response = await axios.post(queryBankListEndpoint, queryBankListRequest.toJSON(), { headers: header });
        console.log("queryBankListRequest Response Data: ",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 queryBankAccount(builder: BuildPayload): Promise<PayInCreateOrderResponse<QueryBankAccountResponse>>{
    const queryBankAccountRequest = builder.build();
    
    try {
        const queryBankAccountEndpoint = this.isTest ? API_ENDPOINTS_SANDBOX.QUERY_BANK_ACCOUNT : API_ENDPOINTS_LIVE.QUERY_BANK_ACCOUNT;
      const signedRequest = createSign(builder, this.privateKey)
        const header = createHeader(this.countryCode,signedRequest, 'Bearer '.concat(this.appId),'application/json')  
        const response = await axios.post(queryBankAccountEndpoint, queryBankAccountRequest.toJSON(), { headers: header });
        console.log("queryBankAccountRequest Response Data: ",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 queryPalmPayAccount(builder: BuildPayload): Promise<PayInCreateOrderResponse<QueryBankAccountResponse>>{
    const queryPalmPayAccountRequest = builder.build();
    
    try {
        const queryPalmPayAccountEndpoint = this.isTest ? API_ENDPOINTS_SANDBOX.QUERY_PALMPAY_ACCOUNT : API_ENDPOINTS_LIVE.QUERY_PALMPAY_ACCOUNT;
      const signedRequest = createSign(builder, this.privateKey)
        const header = createHeader(this.countryCode,signedRequest, 'Bearer '.concat(this.appId),'application/json')  
        const response = await axios.post(queryPalmPayAccountEndpoint, queryPalmPayAccountRequest.toJSON(), { headers: header });
        console.log("queryPalmPayAccountRequest Response Data: ",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
      }
    }
  }

  
}
