package com.payuupiboltui;

import android.os.Handler;
import android.os.Looper;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.facebook.react.bridge.*;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.payu.commonmodelssdk.listeners.PayUHashGeneratedListener;
import com.payu.commonmodelssdk.model.response.PayUUPIBoltResponse;
import com.payu.upiboltui.PayUUPIBoltUI;
import com.payu.upiboltui.listeners.PayUUPIBoltUICallback;
import com.payu.upiboltui.model.ManagementScreenType;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;


public class PayUUPIBoltUISdkModule extends ReactContextBaseJavaModule {

    private  ReactContext reactContext;
    private static PayUHashGeneratedListener payUHashGeneratedListener;
    PayUUPIBoltUI boltUI = null;

    public PayUUPIBoltUISdkModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    }

    @Override
    public String getName() {
        return PayUUPIBoltUISdkConstants.PAYU_UPI_BOLT_SDK;
    }

    @ReactMethod
    public void initSDK(ReadableMap payUUPIBoltUIConfig) {
        new Handler(Looper.getMainLooper()).post(() -> {

            boltUI = PayUUPIBoltUI.getInstance((AppCompatActivity) reactContext.getCurrentActivity(),
                    payUUPIBoltUIConfig.toHashMap(), (hashMap, payUHashGeneratedListener) -> {
                        try {
                            PayUUPIBoltUISdkModule.payUHashGeneratedListener = payUHashGeneratedListener;
                            WritableMap map = new WritableNativeMap();
                            for (Map.Entry<String, String> entry : hashMap.entrySet()) {
                                map.putString(entry.getKey(), entry.getValue());
                            }
                            sendResultBack(PayUUPIBoltUISdkConstants.GENERATE_HASH, map);
                        } catch (Exception e) {
                            WritableMap map = new WritableNativeMap();
                            map.putString(PayUUPIBoltUISdkConstants.ERROR_MSG, PayUUPIBoltUISdkConstants.GENERIC_MESSAGE);
                            sendResultBack(PayUUPIBoltUISdkConstants.ON_PAYU_FAILURE, map);
                        }
                    });
        });
    }

    @ReactMethod
    public void isUPIBoltSDKAvailable(Callback onCallback) {
        if (boltUI != null) {
            new Handler(Looper.getMainLooper()).post(() -> {
                        boltUI.isUpiBoltEnabled(payUUPIBoltResponse -> {

                            WritableMap map = new WritableNativeMap();
                            String isEnabled;
                            if (payUUPIBoltResponse.getCode() == 0)
                                isEnabled = "true";
                            else
                                isEnabled = "false";
                            map.putString(PayUUPIBoltUISdkConstants.IS_SDK_AVAILABLE, isEnabled);
                            onCallback.invoke(map);

                            return null;
                        });
                    }
            );
        } else {
            initiateFailureResponse();
        }
    }

    @ReactMethod
    public void payURegisterAndPay(ReadableMap payUPaymentParams) {

        new Handler(Looper.getMainLooper()).post(() -> {
                    if (boltUI != null) {
                        boltUI.registerAndPay(payUPaymentParams.toHashMap(), new PayUUPIBoltUICallback() {
                            @Override
                            public void onPayUCancel(boolean isTxnInitiated) {
                                WritableMap map = new WritableNativeMap();
                                map.putString(PayUUPIBoltUISdkConstants.RESULT_MSG, "onPayUCancel isTxnInitiated" + isTxnInitiated);
                                map.putInt(PayUUPIBoltUISdkConstants.RESULT_CODE, -1);
                                sendResultBack(PayUUPIBoltUISdkConstants.ON_PAYU_CANCEL, map);
                            }

                            @Override
                            public void onPayUSuccess(@NonNull PayUUPIBoltResponse response) {
                                WritableMap map = new WritableNativeMap();
                                String result = String.valueOf(response.getResult());
                                map.putString(PayUUPIBoltUISdkConstants.RESULT_MSG, response.getMessage());
                                map.putInt(PayUUPIBoltUISdkConstants.RESULT_CODE, response.getCode());
                                map.putString(PayUUPIBoltUISdkConstants.RESULT, result);
                                sendResultBack(PayUUPIBoltUISdkConstants.ON_PAYU_SUCCESS, map);
                            }

                            @Override
                            public void onPayUFailure(@NonNull PayUUPIBoltResponse response) {
                                WritableMap map = new WritableNativeMap();
                                map.putString(PayUUPIBoltUISdkConstants.RESULT_MSG, response.getMessage());
                                map.putInt(PayUUPIBoltUISdkConstants.RESULT_CODE, response.getCode());
                                map.putString(PayUUPIBoltUISdkConstants.RESULT, String.valueOf(response.getResult()));
                                sendResultBack(PayUUPIBoltUISdkConstants.ON_PAYU_FAILURE, map);
                            }
                        });
                    } else {
                        initiateFailureResponse();

                    }
                }
        );
    }

    @ReactMethod
    public void payUUPIBoltUserSettings(String screenType){
        new Handler(Looper.getMainLooper()).post(() -> {
            if (boltUI != null) {
                boltUI.openUPIManagement(ManagementScreenType.valueOf(screenType), new PayUUPIBoltUICallback() {
                    @Override
                    public void onPayUCancel(boolean isTxnInitiated) {
                        WritableMap map = new WritableNativeMap();
                        map.putString(PayUUPIBoltUISdkConstants.RESULT_MSG, "onPayUCancel isTxnInitiated" + isTxnInitiated);
                        map.putInt(PayUUPIBoltUISdkConstants.RESULT_CODE, -1);
                        sendResultBack(PayUUPIBoltUISdkConstants.ON_PAYU_CANCEL, map);
                    }

                    @Override
                    public void onPayUSuccess(@NonNull PayUUPIBoltResponse response) {
                        WritableMap map = new WritableNativeMap();
                        map.putString(PayUUPIBoltUISdkConstants.RESULT_MSG, response.getMessage());
                        map.putInt(PayUUPIBoltUISdkConstants.RESULT_CODE, response.getCode());
                        map.putString(PayUUPIBoltUISdkConstants.RESULT, String.valueOf(response.getResult()));
                    }

                    @Override
                    public void onPayUFailure(@NonNull PayUUPIBoltResponse response) {
                        WritableMap map = new WritableNativeMap();
                        map.putString(PayUUPIBoltUISdkConstants.RESULT_MSG, response.getMessage());
                        map.putInt(PayUUPIBoltUISdkConstants.RESULT_CODE, response.getCode());
                        map.putString(PayUUPIBoltUISdkConstants.RESULT, String.valueOf(response.getResult()));
                        sendResultBack(PayUUPIBoltUISdkConstants.ON_PAYU_FAILURE, map);
                    }
                });
            } else {
                initiateFailureResponse();
            }
        });
    }


    @ReactMethod
    public void hashGenerated(final ReadableMap map) {
        UiThreadUtil.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                HashMap<String, String> valueMap = new HashMap<>();
                ReadableMapKeySetIterator iterator = map.keySetIterator();
                while (iterator.hasNextKey()) {
                    String key = iterator.nextKey();
                    valueMap.put(key, map.getString(key));
                }
                PayUUPIBoltUISdkModule.payUHashGeneratedListener.onHashGenerated(valueMap);
            }
        });
    }

    @ReactMethod
    public void reset(){
        Handler handler = new Handler(reactContext.getMainLooper());
        handler.post(new Runnable() {

            @Override
            public void run() {
                PayUUPIBoltUI.reset(reactContext);
            }
        });
    }


 @ReactMethod
    public void isRegistered(String pg, Callback onCallback){
        if (boltUI != null) {
            new Handler(Looper.getMainLooper()).post(() -> {
                        boltUI.isRegistered(pg, registered -> {

                            WritableMap map = new WritableNativeMap();
                            String isRegistered;
                            if (registered)
                                isRegistered = "true";
                            else
                                isRegistered = "false";
                            map.putString(PayUUPIBoltUISdkConstants.IS_REGISTERED, isRegistered);
                            onCallback.invoke(map);
                            return null;
                        });
                    }
            );
        } else {
            initiateFailureResponse();
        }
    }


  @ReactMethod
    public void clearCache(String pg){
        if (boltUI != null) {
            new Handler(Looper.getMainLooper()).post(() -> {
                        boltUI.clearData(pg);
                    }
            );
        } else {
            initiateFailureResponse();
        }
    }

    private void sendResultBack(String eventName, WritableMap params) {
        Handler handler = new Handler(reactContext.getMainLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                PayUUPIBoltUISdkModule.this.reactContext
                        .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                        .emit(eventName, params);
            }
        });
    }

    private void initiateFailureResponse() {
        WritableMap map = new WritableNativeMap();
        map.putString(PayUUPIBoltUISdkConstants.RESULT_MSG, "Please initiate the UPI bolt sdk before calling this service");
        map.putInt(PayUUPIBoltUISdkConstants.RESULT_CODE, -2);
        sendResultBack(PayUUPIBoltUISdkConstants.ON_PAYU_FAILURE, map);
    }
}
