package com.myfatoorahreactnative.sdkhelper;

import android.app.Activity;
import android.content.Intent;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.myfatoorah.sdk.entity.MFError;
import com.myfatoorah.sdk.entity.MFSubmitCardViewResponse;
import com.myfatoorah.sdk.entity.executepayment.MFExecutePaymentRequest;
import com.myfatoorah.sdk.entity.executepayment.MFPaymentWithSavedTokenRequest;
import com.myfatoorah.sdk.entity.executepayment_cardinfo.MFCardInfo;
import com.myfatoorah.sdk.entity.executepayment_cardinfo.MFDirectPaymentResponse;
import com.myfatoorah.sdk.entity.googlepay.GooglePayRequest;
import com.myfatoorah.sdk.entity.initiatepayment.MFInitiatePaymentRequest;
import com.myfatoorah.sdk.entity.initiatepayment.MFInitiatePaymentResponse;
import com.myfatoorah.sdk.entity.initiatesession.MFInitiateSessionRequest;
import com.myfatoorah.sdk.entity.initiatesession.MFInitiateSessionResponse;
import com.myfatoorah.sdk.entity.paymentstatus.MFGetPaymentStatusRequest;
import com.myfatoorah.sdk.entity.paymentstatus.MFGetPaymentStatusResponse;
import com.myfatoorah.sdk.entity.sendpayment.MFSendPaymentRequest;
import com.myfatoorah.sdk.entity.sendpayment.MFSendPaymentResponse;
import com.myfatoorah.sdk.enums.MFCountry;
import com.myfatoorah.sdk.enums.MFEnvironment;
import com.myfatoorah.sdk.enums.PlatformType;
import com.myfatoorah.sdk.views.MFResult;
import com.myfatoorah.sdk.views.MFSDK;
import com.myfatoorah.sdk.views.embeddedpayment.googlepay.ExecutionMode;
import com.myfatoorah.sdk.views.embeddedpayment.googlepay.MFGooglePayHelper;
import com.myfatoorah.sdk.views.embeddedpayment.googlepay.MFGooglePayTokenHelper;
import com.myfatoorahreactnative.cardview.MFCardViewManager;
import com.myfatoorahreactnative.googlepay.MFGooglePayButton;
import com.myfatoorahreactnative.googlepay.MFGooglePayManager;
import com.myfatoorahreactnative.models.MFDirectPaymentRequest;
import com.myfatoorahreactnative.models.MFGooglePayRequest;
import com.myfatoorahreactnative.utils.MFConstants;
import com.myfatoorahreactnative.utils.MFExtentionsKt;
import com.myfatoorahreactnative.utils.MFGPayConstants;

import java.util.Objects;

import kotlin.Unit;

@ReactModule(name = MFConstants.MFModuleNAME)
public class MFModule extends ReactContextBaseJavaModule implements IMFModule, ActivityEventListener {
  private final String TAG = MFModule.class.getSimpleName();

  //#region ReactNative Module Required
  public MFModule(ReactApplicationContext reactContext) {
    super(reactContext);
    reactContext.addActivityEventListener(this);
  }

  @Override
  @NonNull
  public String getName() {
    return MFConstants.MFModuleNAME;
  }
  //#endregion

  //#region MFSDK Methods
  @Override
  @ReactMethod
  public void init(String apiKey, String country, String environment, Promise promise) {
    MFEnvironment currentEnvironment = getEnumEnvironment(environment);
    MFSDK.INSTANCE.init(apiKey, getEnumCountry(country), currentEnvironment);
    MFSDK.INSTANCE.setPlatForm(PlatformType.ReactNative);

    JsonObject json = new JsonObject();
    json.addProperty("isSuccess", true);
    OnSuccess(promise, json);
  }

  @Override
  @ReactMethod
  public void setUpActionBar(String toolBarTitle, int toolBarTitleColor,
                             int toolBarBackgroundColor, Boolean isShowToolBar, Promise promise) {
    MFSDK.INSTANCE.setUpActionBar(toolBarTitle, toolBarTitleColor, toolBarBackgroundColor, isShowToolBar);

    JsonObject json = new JsonObject();
    json.addProperty("isSuccess", true);
    OnSuccess(promise, json);
  }

  @Override
  @ReactMethod
  public void InitiatePayment(ReadableMap initiatePaymentRequest, String lang, Promise promise) {
    MFInitiatePaymentRequest mfInitiatePaymentRequest =
      HandleReadableMap(initiatePaymentRequest, MFInitiatePaymentRequest.class);

    MFSDK.INSTANCE.initiatePayment(mfInitiatePaymentRequest, lang, (MFResult<MFInitiatePaymentResponse> result) -> {
      if (result instanceof MFResult.Success) {
        MFInitiatePaymentResponse response = ((MFResult.Success<MFInitiatePaymentResponse>) result).getResponse();
        OnSuccess(promise, response);
      } else if (result instanceof MFResult.Fail) {
        MFError mfError = ((MFResult.Fail) result).getError();
        OnError(promise, mfError);
      }
      return Unit.INSTANCE;
    });
  }

  @Override
  @ReactMethod
  public void GetPaymentStatus(ReadableMap getPaymentStatusRequest, String lang, Promise promise) {
    MFGetPaymentStatusRequest mfGetPaymentStatusRequest = HandleReadableMap(getPaymentStatusRequest, MFGetPaymentStatusRequest.class);
    MFSDK.INSTANCE.getPaymentStatus(mfGetPaymentStatusRequest, lang, (MFResult<MFGetPaymentStatusResponse> result) -> {
      if (result instanceof MFResult.Success) {
        MFGetPaymentStatusResponse response = ((MFResult.Success<MFGetPaymentStatusResponse>) result).getResponse();
        OnSuccess(promise, response);
      } else if (result instanceof MFResult.Fail) {
        MFError mfError = ((MFResult.Fail) result).getError();
        OnError(promise, mfError);
      }
      return Unit.INSTANCE;
    });
  }

  @Override
  @ReactMethod
  public void SendPayment(ReadableMap sendPaymentRequest, String lang, Promise promise) {
    MFSendPaymentRequest mfSendPaymentRequest = HandleReadableMap(sendPaymentRequest, MFSendPaymentRequest.class);
    MFSDK.INSTANCE.sendPayment(mfSendPaymentRequest, lang, (MFResult<MFSendPaymentResponse> result) -> {
      if (result instanceof MFResult.Success) {
        //returnResponse(200,true , "success", gson.toJson(((MFResult.Success<MFSendPaymentResponse>) result).getResponse()));
        MFSendPaymentResponse response = ((MFResult.Success<MFSendPaymentResponse>) result).getResponse();
        OnSuccess(promise, response);
      } else if (result instanceof MFResult.Fail) {
        MFError mfError = ((MFResult.Fail) result).getError();
        OnError(promise, mfError);
      }
      return Unit.INSTANCE;
    });
  }

  @Override
  @ReactMethod
  public void ExecutePayment(ReadableMap executePaymentRequest, String lang, Promise promise) {
    MFExecutePaymentRequest mfExecutePaymentRequest = HandleReadableMap(executePaymentRequest, MFExecutePaymentRequest.class);
    MFSDK.INSTANCE.executePayment(
      Objects.requireNonNull(this.getCurrentActivity()),
      mfExecutePaymentRequest,
      lang,
      (String invoiceId) -> {
        OnInvoiceCreated(invoiceId);
        return Unit.INSTANCE;
      },
      (String invoiceId, MFResult<MFGetPaymentStatusResponse> result) -> {
        if (result instanceof MFResult.Success) {
          MFGetPaymentStatusResponse response = ((MFResult.Success<MFGetPaymentStatusResponse>) result).getResponse();
          OnSuccess(promise, response);
        } else if (result instanceof MFResult.Fail) {
          MFError mfError = ((MFResult.Fail) result).getError();
          OnError(promise, mfError);
        }
        return Unit.INSTANCE;
      });
  }

  @Override
  @ReactMethod
  public void ExecutePaymentWithSavedToken(ReadableMap savedTokenRequest, String lang, Promise promise) {
    MFPaymentWithSavedTokenRequest mfPaymentWithSavedTokenRequest = HandleReadableMap(savedTokenRequest, MFPaymentWithSavedTokenRequest.class);
    MFSDK.INSTANCE.executePaymentWithSavedToken(
      Objects.requireNonNull(this.getCurrentActivity()),
      mfPaymentWithSavedTokenRequest,
      lang,
      (String invoiceId) -> {
        OnInvoiceCreated(invoiceId);
        return Unit.INSTANCE;
      },
      (String invoiceId, MFResult<MFGetPaymentStatusResponse> result) -> {
        if (result instanceof MFResult.Success) {
          MFGetPaymentStatusResponse response = ((MFResult.Success<MFGetPaymentStatusResponse>) result).getResponse();
          OnSuccess(promise, response);
        } else if (result instanceof MFResult.Fail) {
          MFError mfError = ((MFResult.Fail) result).getError();
          OnError(promise, mfError);
        }
        return Unit.INSTANCE;
      });
  }

  @Override
  @ReactMethod
  public void ExecuteDirectPayment(ReadableMap directPaymentRequest, String lang, Promise promise) {
    MFDirectPaymentRequest request = HandleReadableMap(directPaymentRequest, MFDirectPaymentRequest.class);
    MFExecutePaymentRequest mfExecutePaymentRequest = request.ExecutePaymentRequest;
    MFCardInfo mfCardInfo;
    if (request.Token != null && !request.Token.equals("")) {
      mfCardInfo = new MFCardInfo(request.Token);
    } else if (request.Card != null) {
      mfCardInfo = new MFCardInfo(
        request.Card.getNumber(), request.Card.getExpiryMonth(), request.Card.getExpiryYear(),
        request.Card.getSecurityCode(), request.Card.getCardHolderName(),
        false, true);
      mfCardInfo.setBypass3DS(false);
    } else {
      MFError mfError = new MFError("000", "Please provide Token or Card");
      OnError(promise, mfError);
      return;
    }

    MFSDK.INSTANCE.executeDirectPayment(
      Objects.requireNonNull(getCurrentActivity()),
      mfExecutePaymentRequest,
      mfCardInfo,
      lang,
      (String invoiceId) -> {
        OnInvoiceCreated(invoiceId);
        return Unit.INSTANCE;
      },
      (String invoiceId, MFResult<MFDirectPaymentResponse> result) -> {
        if (result instanceof MFResult.Success) {
          MFDirectPaymentResponse response = ((MFResult.Success<MFDirectPaymentResponse>) result).getResponse();
          OnSuccess(promise, response);
        } else if (result instanceof MFResult.Fail) {
          MFError mfError = ((MFResult.Fail) result).getError();
          OnError(promise, mfError);
        }
        return Unit.INSTANCE;
      });
  }

  @Override
  @ReactMethod
  public void cancelToken(String token, String lang, Promise promise)//Boolean
  {
    MFSDK.INSTANCE.cancelToken(token, lang, (MFResult<Boolean> result) -> {
      if (result instanceof MFResult.Success) {
        Boolean response = ((MFResult.Success<Boolean>) result).getResponse();
        promise.resolve(response);
      } else if (result instanceof MFResult.Fail) {
        MFError mfError = ((MFResult.Fail) result).getError();
        OnError(promise, mfError);
      }
      return Unit.INSTANCE;
    });
  }

  @Override
  @ReactMethod
  public void cancelRecurringPayment(String recurringId, String lang, Promise promise) {
    MFSDK.INSTANCE.cancelRecurringPayment(recurringId, lang, (MFResult<Boolean> result) -> {
      if (result instanceof MFResult.Success) {
        Boolean response = ((MFResult.Success<Boolean>) result).getResponse();
        promise.resolve(response);
      } else if (result instanceof MFResult.Fail) {
        MFError mfError = ((MFResult.Fail) result).getError();
        OnError(promise, mfError);
      }
      return Unit.INSTANCE;
    });
  }
  //#endregion

  //#region CardView Methods
  @Override
  @ReactMethod
  public void InitiateSession(ReadableMap initiateSessionRequest, Promise promise) {
    MFInitiateSessionRequest mfInitiateSessionRequest = HandleReadableMap(initiateSessionRequest, MFInitiateSessionRequest.class);

    MFSDK.INSTANCE.initiateSession(mfInitiateSessionRequest, (MFResult<MFInitiateSessionResponse> result) -> {
      if (result instanceof MFResult.Success) {
        MFInitiateSessionResponse response = ((MFResult.Success<MFInitiateSessionResponse>) result).getResponse();
        OnSuccess(promise, response);
      } else if (result instanceof MFResult.Fail) {
        MFError mfError = ((MFResult.Fail) result).getError();
        OnError(promise, mfError);
      }
      return Unit.INSTANCE;
    });
  }

  @Override
  @ReactMethod
  public void LoadCardView(ReadableMap initiateSessionResponse, Promise promise) {
    if (MFCardViewManager.paymentCardView == null) {
      MFError mfError = new MFError("009", "cardView must be initialized");
      OnError(promise, mfError);
      return;
    }
    MFCardViewManager.paymentCardView.post(() -> {
      MFInitiateSessionResponse mfInitiateSessionResponse = HandleReadableMap(initiateSessionResponse, MFInitiateSessionResponse.class);
      MFCardViewManager.paymentCardView.load(mfInitiateSessionResponse, (String bin) ->
      {
        OnCardBinChanged(bin);
        return Unit.INSTANCE;
      }, (Float height) ->
      {
        Log.d(TAG, "height: " + height);
        return Unit.INSTANCE;
      }, false);
      promise.resolve("CardView Loaded");
    });
  }

  @Override
  @ReactMethod
  public void Validate(String currency, Promise promise) {
    MFCardViewManager.paymentCardView.validate(currency, (MFResult<String> result) -> {
      if (result instanceof MFResult.Success) {
        String response = ((MFResult.Success<String>) result).getResponse();
        promise.resolve(response);
      } else if (result instanceof MFResult.Fail) {
        MFError mfError = ((MFResult.Fail) result).getError();
        OnError(promise, mfError);
      }
      return Unit.INSTANCE;
    });
  }

  @Override
  @ReactMethod
  public void Submit(String currency, Promise promise) {
    MFCardViewManager.paymentCardView.submit(currency, (MFResult<MFSubmitCardViewResponse> result) -> {
      if (result instanceof MFResult.Success) {
        MFSubmitCardViewResponse response = ((MFResult.Success<MFSubmitCardViewResponse>) result).getResponse();
        promise.resolve(response);
      } else if (result instanceof MFResult.Fail) {
        MFError mfError = ((MFResult.Fail) result).getError();
        OnError(promise, mfError);
      }
      return Unit.INSTANCE;
    });
  }

  @Override
  @ReactMethod
  public void Pay(ReadableMap executePaymentRequest, String lang, String currency, Promise promise) {
    MFExecutePaymentRequest mfExecutePaymentRequest = HandleReadableMap(executePaymentRequest, MFExecutePaymentRequest.class);
    MFCardViewManager.paymentCardView.pay(
      Objects.requireNonNull(MFCardViewManager.reactContext.getCurrentActivity()),
      mfExecutePaymentRequest,
      lang,
      currency,
      (String invoiceId) -> {
        OnInvoiceCreated(invoiceId);
        return Unit.INSTANCE;
      },
      (String invoiceId, MFResult<MFGetPaymentStatusResponse> result) -> {
        if (result instanceof MFResult.Success) {
          MFGetPaymentStatusResponse response = ((MFResult.Success<MFGetPaymentStatusResponse>) result).getResponse();
          OnSuccess(promise, response);
        } else if (result instanceof MFResult.Fail) {
          MFError mfError = ((MFResult.Fail) result).getError();
          OnError(promise, mfError);
        }
        return Unit.INSTANCE;
      });
  }
  //#endregion

  //#region GooglePay Methods
  /**
   * @deprecated Use {@link com.myfatoorahreactnative.googlepay.MFGPayModule} instead.
   * This method uses deprecated native helpers and will be removed in a future release.
   * Migrate to MFGPayModule for better lifecycle handling and new features.
   */
  private MFGooglePayHelper mfGooglePayHelper = null;
  private MFGooglePayTokenHelper mfGooglePayTokenHelper = null;

  @Deprecated
  @Override
  @ReactMethod
  public void SetupGooglePayHelper(String sessionId, ReadableMap googlePayRequest, Promise promise) {
    MFGooglePayButton googlePayButton = MFGooglePayManager.googlePayButton;
    if (googlePayButton == null) {
      MFError mfError = new MFError("010", "googlePayButton must be initialized");
      OnError(promise, mfError);
      return;
    }

    GooglePayRequest request = getGooglePayRequest(googlePayRequest);

    boolean autoExecutePayment = true;

    mfGooglePayHelper = new MFGooglePayHelper(
      Objects.requireNonNull(getCurrentActivity()),
      MFConstants.GooglePayRequestCODE,
      sessionId,
      request,
      autoExecutePayment,
      (String updatedSessionId) -> {
        OnGPaySessionUpdated(updatedSessionId);
        return Unit.INSTANCE;
      },
      (String invoiceId) -> {
        OnInvoiceCreated(invoiceId);
        Log.d(TAG, invoiceId);
        return Unit.INSTANCE;
      },
      (String invoiceId, MFGetPaymentStatusResponse getPaymentStatusResponse) -> {
        OnGPayExecutePaymentSuccess(invoiceId, getPaymentStatusResponse);
        return Unit.INSTANCE;
      },
      (MFError error) -> {
        OnGPayError(error);
        return Unit.INSTANCE;
      },
      (String invoiceId, MFResult<MFGetPaymentStatusResponse> result) -> {
        if (result instanceof MFResult.Success) {
          MFGetPaymentStatusResponse response = ((MFResult.Success<MFGetPaymentStatusResponse>) result).getResponse();
          OnSuccess(promise, response);
        } else if (result instanceof MFResult.Fail) {
          MFError mfError = ((MFResult.Fail) result).getError();
          OnError(promise, mfError);
        }
        return Unit.INSTANCE;
      });

    if (googlePayButton.getButton() != null)
      mfGooglePayHelper.setGooglePayButton(googlePayButton.getButton());
  }

  @Deprecated
  @Override
  @ReactMethod
  public void SetupGooglePayHelperAuto(String sessionId, ReadableMap googlePayRequest, Promise promise) {
    MFGooglePayButton googlePayButton = MFGooglePayManager.googlePayButton;
    if (googlePayButton == null) {
      MFError mfError = new MFError("010", "googlePayButton must be initialized");
      OnError(promise, mfError);
      return;
    }

    GooglePayRequest request = getGooglePayRequest(googlePayRequest);

    ExecutionMode autoExecutePayment = new ExecutionMode.Auto(
      (String invoiceId) -> {
        OnInvoiceCreated(invoiceId);
        return Unit.INSTANCE;
      },
      (String invoiceId, MFGetPaymentStatusResponse getPaymentStatusResponse) -> {
        OnGPayExecutePaymentSuccess(invoiceId, getPaymentStatusResponse);
        OnSuccess(promise, getPaymentStatusResponse);
        return Unit.INSTANCE;
      }
    );

    mfGooglePayHelper = new MFGooglePayHelper(
      Objects.requireNonNull(getCurrentActivity()),
      MFConstants.GooglePayRequestCODE,
      sessionId,
      request,
      autoExecutePayment,
      (MFError error) -> {
        OnGPayError(error);
        OnError(promise, error);
        return Unit.INSTANCE;
      });

    if (googlePayButton.getButton() != null)
      mfGooglePayHelper.setGooglePayButton(googlePayButton.getButton());
  }

  @Deprecated
  @Override
  @ReactMethod
  public void SetupGooglePayHelperManual(String sessionId, ReadableMap googlePayRequest, Promise promise) {
    MFGooglePayButton googlePayButton = MFGooglePayManager.googlePayButton;
    if (googlePayButton == null) {
      MFError mfError = new MFError("010", "googlePayButton must be initialized");
      OnError(promise, mfError);
      return;
    }

    GooglePayRequest request = getGooglePayRequest(googlePayRequest);

    ExecutionMode manualExecutionMode = new ExecutionMode.Manual(
      (String updatedSessionId) -> {
        OnGPaySessionUpdated(updatedSessionId);

        JsonObject json = new JsonObject();
        json.addProperty("sessionId", updatedSessionId);
        OnSuccess(promise, json);

        return Unit.INSTANCE;
      }
    );
    mfGooglePayHelper = new MFGooglePayHelper(
      Objects.requireNonNull(getCurrentActivity()),
      MFConstants.GooglePayRequestCODE,
      sessionId,
      request,
      manualExecutionMode,
      (MFError error) -> {
        OnGPayError(error);
        OnError(promise, error);
        return Unit.INSTANCE;
      });

    if (googlePayButton.getButton() != null)
      mfGooglePayHelper.setGooglePayButton(googlePayButton.getButton());
  }

  @Deprecated
  @Override
  @ReactMethod
  public void ExecutePaymentWithGooglePay(ReadableMap executePaymentRequest, String lang, Promise promise) {
    MFExecutePaymentRequest mfExecutePaymentRequest = HandleReadableMap(executePaymentRequest, MFExecutePaymentRequest.class);
    MFSDK.INSTANCE.executePaymentWithGooglePay(
      Objects.requireNonNull(this.getCurrentActivity()),
      mfExecutePaymentRequest,
      lang,
      (String invoiceId) -> {
        OnInvoiceCreated(invoiceId);
        return Unit.INSTANCE;
      },
      (String invoiceId, MFResult<MFGetPaymentStatusResponse> result) -> {
        if (result instanceof MFResult.Success) {
          MFGetPaymentStatusResponse response = ((MFResult.Success<MFGetPaymentStatusResponse>) result).getResponse();
          OnSuccess(promise, response);
        } else if (result instanceof MFResult.Fail) {
          MFError mfError = ((MFResult.Fail) result).getError();
          OnError(promise, mfError);
        }
        return Unit.INSTANCE;
      });
  }

  @Deprecated
  @Override
  @ReactMethod
  public void SetupGooglePayTokenHelper(ReadableMap googlePayRequest, Promise promise) {
    MFGooglePayButton googlePayButton = MFGooglePayManager.googlePayButton;
    if (googlePayButton == null) {
      MFError mfError = new MFError("010", "googlePayButton must be initialized");
      OnError(promise, mfError);
      return;
    }

    GooglePayRequest request = getGooglePayRequest(googlePayRequest);

    mfGooglePayTokenHelper = new MFGooglePayTokenHelper(
      Objects.requireNonNull(getCurrentActivity()),
      MFConstants.GooglePayRequestCODE,
      request,

      (MFResult<String> result) -> {
        if (result instanceof MFResult.Success) {
          String token = ((MFResult.Success<String>) result).getResponse();
          promise.resolve(token);
        } else if (result instanceof MFResult.Fail) {
          MFError mfError = ((MFResult.Fail) result).getError();
          OnError(promise, mfError);
        }
        return Unit.INSTANCE;
      });
    if (googlePayButton.getButton() != null)
      mfGooglePayTokenHelper.setGooglePayButton(googlePayButton.getButton());
  }

  @Deprecated
  @Override
  @ReactMethod
  public void GooglePayTokenConfig(ReadableMap googlePayRequest, Promise promise) {
    GooglePayRequest request = getGooglePayRequest(googlePayRequest);

    mfGooglePayTokenHelper = new MFGooglePayTokenHelper(
      Objects.requireNonNull(getCurrentActivity()),
      MFConstants.GooglePayRequestCODE,
      request,
      (MFResult<String> result) -> {
        if (result instanceof MFResult.Success) {
          String token = ((MFResult.Success<String>) result).getResponse();
          promise.resolve(token);
        } else if (result instanceof MFResult.Fail) {
          MFError mfError = ((MFResult.Fail) result).getError();
          OnError(promise, mfError);
        }
        return Unit.INSTANCE;
      });
  }

  @Deprecated
  @Override
  @ReactMethod
  public void GooglePayOpenSheet(Promise promise) {
    mfGooglePayTokenHelper.openGooglePaySheet();
    JsonObject json = new JsonObject();
    json.addProperty("isInvoked", true);
    OnSuccess(promise, json);
  }

  /**
   * @deprecated This method is only used by deprecated Google Pay helpers.
   * Will be removed when deprecated methods are removed.
   */
  @Deprecated
  @Override
  public void onActivityResult(Activity activity, int requestCode, int resultCode, @Nullable Intent data) {
    if (requestCode == MFConstants.GooglePayRequestCODE) {
      if (mfGooglePayHelper != null)
        mfGooglePayHelper.onActivityResult(requestCode, resultCode, data);

      else if (mfGooglePayTokenHelper != null)
        mfGooglePayTokenHelper.onActivityResult(requestCode, resultCode, data);
    }
  }

  @Override
  public void onNewIntent(Intent intent) {
  }
  //#endregion

  //#region EventEmitter Methods
  private void OnInvoiceCreated(String invoiceId) {
    getReactApplicationContext()
      .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
      .emit(MFConstants.InvoiceCreatedEventName, invoiceId);
  }

  private void OnCardBinChanged(String bin) {
    getReactApplicationContext()
      .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
      .emit(MFConstants.CardBinChangedEventName, bin);
  }

  private void OnGPaySessionUpdated(String sessionId) {
    getReactApplicationContext()
      .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
      .emit(MFGPayConstants.GPaySessionUpdatedEventName, sessionId);
  }

  private void OnGPayExecutePaymentSuccess(String invoiceId, MFGetPaymentStatusResponse getPaymentStatusResponse) {
    Gson gson = new Gson();
    String json = gson.toJson(getPaymentStatusResponse);

    getReactApplicationContext()
      .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
      .emit(MFGPayConstants.GPayExecutePaymentSuccessEventName, json);
  }

  private void OnGPayError(MFError error) {
    Gson gson = new Gson();
    String json = gson.toJson(error);


    getReactApplicationContext()
      .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
      .emit(MFGPayConstants.GPayErrorEventName, json);
  }

  @Override
  @ReactMethod
  public void addListener(String eventName) {
  }

  @Override
  @ReactMethod
  public void removeListeners(Integer count) {
  }
  //#endregion

  //#region Helpers Methods
  private MFCountry getEnumCountry(String country) {
    if (country.equals(MFCountry.KUWAIT.getCode()))
      return MFCountry.KUWAIT;
    if (country.equals(MFCountry.SAUDI_ARABIA.getCode()))
      return MFCountry.SAUDI_ARABIA;
    if (country.equals(MFCountry.BAHRAIN.getCode()))
      return MFCountry.BAHRAIN;
    if (country.equals(MFCountry.UNITED_ARAB_EMIRATES_UAE.getCode()))
      return MFCountry.UNITED_ARAB_EMIRATES_UAE;
    if (country.equals(MFCountry.QATAR.getCode()))
      return MFCountry.QATAR;
    if (country.equals(MFCountry.OMAN.getCode()))
      return MFCountry.OMAN;
    if (country.equals(MFCountry.JORDAN.getCode()))
      return MFCountry.JORDAN;
    if (country.equals(MFCountry.EGYPT.getCode()))
      return MFCountry.EGYPT;
    return MFCountry.KUWAIT;
  }

  private MFEnvironment getEnumEnvironment(String country) {
    if (country.equals(MFEnvironment.TEST.toString()))
      return MFEnvironment.TEST;
    if (country.equals(MFEnvironment.LIVE.toString()))
      return MFEnvironment.LIVE;
    return MFEnvironment.TEST;
  }

  private GooglePayRequest getGooglePayRequest(ReadableMap googlePayRequest) {
    MFGooglePayRequest mfRequest = HandleReadableMap(googlePayRequest, MFGooglePayRequest.class);

    GooglePayRequest request = new GooglePayRequest(
      mfRequest.TotalPrice,
      mfRequest.MerchantId,
      mfRequest.MerchantName,
      mfRequest.CountryCode,
      mfRequest.CurrencyIso
    );

    return request;
  }

  private <T> T HandleReadableMap(ReadableMap requestMap, Class<T> classOfT) {
    return MFExtentionsKt.handleReadableMap(requestMap, classOfT);
  }

  private void OnSuccess(Promise promise, Object object) {
    Gson gson = new Gson();
    String originalJsonString = gson.toJson(object);
//    String lowercaseJsonString = MFExtentionsKt.convertJsonStringToLowercase(originalJsonString);
    String uppercaseJsonString = MFExtentionsKt.convertJsonStringToUppercase(originalJsonString);
    promise.resolve(uppercaseJsonString);
  }

  private void OnError(Promise promise, MFError error) {
    promise.reject(error.getCode(), error.getMessage());
  }
  //#endregion
}
