package com.phonepe.payment.capacitor;

import static com.phonepe.payment.capacitor.DataUtil.convertResultToString;
import static com.phonepe.payment.capacitor.DataUtil.handleException;
import static com.phonepe.payment.capacitor.GlobalConstants.Argument.REQUEST;
import static com.phonepe.payment.capacitor.GlobalConstants.Argument.ENABLE_LOGS;
import static com.phonepe.payment.capacitor.GlobalConstants.Argument.ENVIRONMENT;
import static com.phonepe.payment.capacitor.GlobalConstants.Argument.FLOW_ID;
import static com.phonepe.payment.capacitor.GlobalConstants.Argument.MERCHANT_ID;
import static com.phonepe.payment.capacitor.GlobalConstants.Argument.SHOW_LOADER_FLAG;
import static com.phonepe.payment.capacitor.GlobalConstants.PHONEPE_PAYMENT_SDK;
import static com.phonepe.payment.capacitor.GlobalConstants.Response.APPLICATION_NAME;
import static com.phonepe.payment.capacitor.GlobalConstants.Response.ERROR;
import static com.phonepe.payment.capacitor.GlobalConstants.Response.FAILURE;
import static com.phonepe.payment.capacitor.GlobalConstants.Response.PACKAGE_NAME;
import static com.phonepe.payment.capacitor.GlobalConstants.Response.SUCCESS;
import static com.phonepe.payment.capacitor.GlobalConstants.Response.VERSION;
import static com.phonepe.payment.capacitor.LogUtil.logInfo;
import static com.phonepe.payment.capacitor.GlobalConstants.Response.STATUS;
import static com.phonepe.payment.capacitor.LogUtil.enableLogs;

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

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;

import com.getcapacitor.JSObject;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.annotation.CapacitorPlugin;
import com.phonepe.intent.sdk.api.PhonePeKt;
import com.phonepe.intent.sdk.api.UPIApplicationInfo;
import com.phonepe.intent.sdk.api.models.PhonePeEnvironment;
import com.phonepe.intent.sdk.api.models.SDKType;
import com.phonepe.intent.sdk.api.models.transaction.primitive.TransactionRequest;

import org.json.JSONArray;
import org.json.JSONException;
import java.util.Objects;


@CapacitorPlugin(name = PHONEPE_PAYMENT_SDK)
public class PhonePePaymentSDKPlugin extends Plugin {

    ActivityResultLauncher<Intent> activityResultLauncher = null;

    public PhonePePaymentSDKPlugin() {
        PhonePeKt.setAdditionalInfo(SDKType.IONIC);
    }

    @Override
    protected void handleOnStart() {
        super.handleOnStart();
        activityResultLauncher = getActivity().registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), (result) -> {
            try {
                String intentData = convertResultToString(result.getData());
                logInfo("handleResultOnActivityResultLauncher: requestCode:" + result.getResultCode() + " resultCode:" + result.getResultCode() + "data:" + intentData);
                if (getSavedCall() != null) {
                    JSObject jsonResult = new JSObject();
                    if (result.getResultCode() != Activity.RESULT_CANCELED) {
                        jsonResult.put(STATUS, SUCCESS);
                    } else {
                        jsonResult.put(STATUS, FAILURE);
                        jsonResult.put(ERROR, intentData);
                    }
                    getSavedCall().resolve(jsonResult);
                }
            } catch (Exception ex) {
                handleException(ex, getSavedCall());
            }

        });

    }


    @PluginMethod
    public void init(PluginCall call) {
        logInfo("started init");
        try {
            enableLogs = call.getData().getBoolean(ENABLE_LOGS);
            String environment = call.getData().getString(ENVIRONMENT);
            String merchantId = call.getData().getString(MERCHANT_ID);
            String flowId = call.getData().getString(FLOW_ID);
            if (environment == null || environment.isEmpty()
                || merchantId == null || merchantId.isEmpty()
                    || flowId == null || flowId.isEmpty())
                throw new IllegalArgumentException("Invalid environment or merchantId or flowId!");

            PhonePeEnvironment ppEnvironment;
            if (Objects.equals(environment, PhonePeEnvironment.SANDBOX.name()))
                ppEnvironment = PhonePeEnvironment.SANDBOX;
            else ppEnvironment = PhonePeEnvironment.RELEASE;

            JSObject result = new JSObject();
            result.put(STATUS, PhonePeKt.init(getContext(), merchantId, flowId, ppEnvironment, enableLogs));

            call.resolve(result);
        } catch (Exception ex) {
            handleException(ex, call);
        }
    }

    @PluginMethod
    public void getUpiAppsForAndroid(PluginCall call) {
        logInfo("started getUpiAppsForAndroid");
        try {
            JSONArray jsonArray = new JSONArray();
            for (UPIApplicationInfo app : PhonePeKt.getUpiApps()) {
                JSObject appJson = new JSObject();
                appJson.put(PACKAGE_NAME, app.getPackageName());
                appJson.put(APPLICATION_NAME, app.getApplicationName());
                appJson.put(VERSION, String.valueOf(app.getVersion()));
                jsonArray.put(appJson);
            }
            JSObject result = new JSObject();
            result.put(STATUS, jsonArray.toString());
            call.resolve(result);
        } catch (Exception ex) {
            handleException(ex, call);
        }
    }

    @PluginMethod
    public void startTransaction(PluginCall call) {
        try {
            logInfo("startTransaction initialized");
            saveCall(call);
            String body = call.getData().getString(REQUEST);
            boolean showLoaderFlag = call.getData().getBoolean(SHOW_LOADER_FLAG);

            if (body == null || body.isEmpty()) {
                throw new IllegalArgumentException("Invalid body!");
            }

            TransactionRequest transactionRequest = getTransactionRequest(body);
            PhonePeKt.startTransaction(getContext(), transactionRequest, activityResultLauncher, showLoaderFlag);

        } catch (Exception ex) {
            handleException(ex, call);
        }
    }

    private static TransactionRequest getTransactionRequest(String body) throws JSONException {

        JSObject requestBody = new JSObject(body);
        String orderId = requestBody.optString("orderId");
        if (orderId.isEmpty())
            throw new JSONException("Invalid orderId!");

        String token = requestBody.optString("token");
        if (token.isEmpty())
            throw new  JSONException("Invalid token!");

        String paymentMode = requestBody.optString("paymentMode");
        if (paymentMode.isEmpty())
            throw new  JSONException("Invalid paymentMode!");

        String targetAppPackageName = requestBody.optString("targetAppPackageName");

        return new TransactionRequest(orderId, token, requestBody.toString(), targetAppPackageName);
    }
}
