package com.bhikadia.receive_intent;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.Result;
import org.json.JSONObject;

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

public class ReceiveIntentPlugin implements FlutterPlugin, MethodChannel.MethodCallHandler, EventChannel.StreamHandler, ActivityAware {
    private MethodChannel methodChannel;
    private EventChannel eventChannel;
    private EventChannel.EventSink eventSink;

    private Context context;
    private Activity activity;

    private Map<String, Object> initialIntentMap;
    private Map<String, Object> latestIntentMap;
    private boolean initialIntent = true;

    private void handleIntent(Intent intent, String fromPackageName) {
        Map<String, Object> intentMap = new HashMap<>();
        intentMap.put("fromPackageName", fromPackageName);
        intentMap.put("fromSignatures", fromPackageName != null ? getApplicationSignature(context, fromPackageName) : null);
        intentMap.put("action", intent.getAction());
        intentMap.put("data", intent.getDataString());
        intentMap.put("categories", intent.getCategories() != null ? intent.getCategories() : null);
        intentMap.put("extra", intent.getExtras() != null ? bundleToJSON(intent.getExtras()).toString() : null);

        if (initialIntent) {
            initialIntentMap = intentMap;
            initialIntent = false;
        }
        latestIntentMap = intentMap;
        eventSink.success(latestIntentMap);
    }

    private void setResult(Result result, Integer resultCode, String data, Boolean shouldFinish) {
        if (resultCode != null) {
            if (data == null) {
                activity.setResult(resultCode);
            } else {
                JSONObject json = new JSONObject(data);
                activity.setResult(resultCode, jsonToIntent(json));
            }
            if (shouldFinish != null && shouldFinish) {
                activity.finish();
            }
            result.success(null);
        } else {
            result.error("InvalidArg", "resultCode cannot be null", null);
        }
    }

    @Override
    public void onAttachedToEngine(@NonNull FlutterPlugin.FlutterPluginBinding flutterPluginBinding) {
        context = flutterPluginBinding.getApplicationContext();
        methodChannel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "receive_intent");
        methodChannel.setMethodCallHandler(this);

        eventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), "receive_intent/event");
        eventChannel.setStreamHandler(this);
    }

    @Override
    public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
        switch (call.method) {
            case "getInitialIntent":
                result.success(initialIntentMap);
                break;
            case "setResult":
                setResult(result, call.argument("resultCode"), call.argument("data"), call.argument("shouldFinish"));
                break;
            default:
                result.notImplemented();
                break;
        }
    }

    @Override
    public void onListen(Object arguments, EventChannel.EventSink events) {
        eventSink = events;
    }

    @Override
    public void onCancel(Object arguments) {
        eventSink = null;
    }

    @Override
    public void onDetachedFromEngine(@NonNull FlutterPlugin.FlutterPluginBinding binding) {
        methodChannel.setMethodCallHandler(null);
        eventChannel.setStreamHandler(null);
    }

    @Override
    public void onAttachedToActivity(ActivityPluginBinding binding) {
        activity = binding.getActivity();
        binding.addOnNewIntentListener(intent -> {
            handleIntent(intent, binding.getActivity().getCallingActivity().getPackageName());
            return false;
        });
        handleIntent(activity.getIntent(), activity.getCallingActivity() != null ? activity.getCallingActivity().getPackageName() : null);
    }

    @Override
    public void onDetachedFromActivityForConfigChanges() {
        activity = null;
    }

    @Override
    public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) {
        activity = binding.getActivity();
        binding.addOnNewIntentListener(intent -> {
            handleIntent(intent, binding.getActivity().getCallingActivity().getPackageName());
            return false;
        });
        handleIntent(activity.getIntent(), activity.getCallingActivity() != null ? activity.getCallingActivity().getPackageName() : null);
    }

    @Override
    public void onDetachedFromActivity() {
        activity = null;
    }

    // Implement other methods like getApplicationSignature and bundleToJSON here
}
