package be.harmonics.saas;

import android.Manifest;
import android.os.Build;
import android.util.Log;

import com.getcapacitor.JSObject;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.PermissionState;
import com.getcapacitor.annotation.CapacitorPlugin;
import com.getcapacitor.annotation.Permission;
import com.getcapacitor.annotation.PermissionCallback;
import com.pusher.pushnotifications.BeamsCallback;
import com.pusher.pushnotifications.PushNotifications;
import com.pusher.pushnotifications.PusherCallbackError;
import com.pusher.pushnotifications.auth.AuthData;
import com.pusher.pushnotifications.auth.AuthDataGetter;
import com.pusher.pushnotifications.auth.BeamsTokenProvider;

import java.util.HashMap;

@CapacitorPlugin(
    name = "PusherBeams",
    permissions = {
        @Permission(
            alias = "notifications",
            strings = { Manifest.permission.POST_NOTIFICATIONS }
        )
    }
)
public class PusherBeamsPlugin extends Plugin {
    private static final String TAG = "HarmonicSaaS";
    private boolean isStarted = false;
    private PluginCall savedStartCall = null;

    @PluginMethod
    public void start(PluginCall call) {
        String instanceId = call.getString("instanceId");
        if (instanceId == null || instanceId.isEmpty()) {
            call.reject("Instance ID is required");
            return;
        }

        // Request notification permission on Android 13+ (API 33+)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            if (getPermissionState("notifications") != PermissionState.GRANTED) {
                savedStartCall = call;
                requestPermissionForAlias("notifications", call, "handleNotificationPermission");
                return;
            }
        }

        doStart(call, instanceId);
    }

    @PermissionCallback
    private void handleNotificationPermission(PluginCall call) {
        if (call == null) {
            call = savedStartCall;
        }
        if (call == null) {
            Log.e(TAG, "No saved call for permission callback");
            return;
        }

        String instanceId = call.getString("instanceId");
        if (instanceId == null || instanceId.isEmpty()) {
            call.reject("Instance ID is required");
            return;
        }

        // Continue with start regardless of permission result
        // User can still receive notifications if they grant permission later
        doStart(call, instanceId);
        savedStartCall = null;
    }

    private void doStart(PluginCall call, String instanceId) {
        try {
            PushNotifications.start(getContext(), instanceId);
            isStarted = true;
            Log.d(TAG, "Pusher Beams started with instance: " + instanceId);
            call.resolve();
        } catch (Exception e) {
            Log.e(TAG, "Failed to start Pusher Beams", e);
            call.reject("Failed to start Pusher Beams: " + e.getMessage());
        }
    }

    @PluginMethod
    public void setUserId(PluginCall call) {
        if (!isStarted) {
            call.reject("Pusher Beams not started. Call start() first.");
            return;
        }

        String userId = call.getString("userId");
        String tokenProviderUrl = call.getString("tokenProviderUrl");
        String sessionCookie = call.getString("sessionCookie");

        if (userId == null || userId.isEmpty()) {
            call.reject("User ID is required");
            return;
        }

        if (tokenProviderUrl == null || tokenProviderUrl.isEmpty()) {
            call.reject("Token provider URL is required");
            return;
        }

        try {
            BeamsTokenProvider tokenProvider = new BeamsTokenProvider(
                tokenProviderUrl,
                new AuthDataGetter() {
                    @Override
                    public AuthData getAuthData() {
                        // Return auth headers with session cookie
                        HashMap<String, String> headers = new HashMap<>();
                        HashMap<String, String> queryParams = new HashMap<>();

                        // Pass session cookie for authentication
                        if (sessionCookie != null && !sessionCookie.isEmpty()) {
                            headers.put("Cookie", sessionCookie);
                        }

                        return new AuthData(headers, queryParams);
                    }
                }
            );

            PushNotifications.setUserId(userId, tokenProvider, new BeamsCallback<Void, PusherCallbackError>() {
                @Override
                public void onSuccess(Void... values) {
                    Log.d(TAG, "User ID set successfully: " + userId);
                    getActivity().runOnUiThread(() -> {
                        call.resolve();
                    });
                }

                @Override
                public void onFailure(PusherCallbackError error) {
                    Log.e(TAG, "Failed to set user ID: " + error.getMessage());
                    getActivity().runOnUiThread(() -> {
                        call.reject("Failed to authenticate with Beams: " + error.getMessage());
                    });
                }
            });
        } catch (Exception e) {
            Log.e(TAG, "Failed to set user ID", e);
            call.reject("Failed to set user ID: " + e.getMessage());
        }
    }

    @PluginMethod
    public void clearAllState(PluginCall call) {
        try {
            PushNotifications.clearAllState();
            isStarted = false;
            Log.d(TAG, "Pusher Beams state cleared");
            call.resolve();
        } catch (Exception e) {
            Log.e(TAG, "Failed to clear Beams state", e);
            call.reject("Failed to clear state: " + e.getMessage());
        }
    }

    @PluginMethod
    public void getDeviceId(PluginCall call) {
        // Note: Pusher Beams SDK does not expose a getDeviceId method
        // Return the Android ID as an alternative device identifier
        if (!isStarted) {
            call.reject("Pusher Beams not started. Call start() first.");
            return;
        }

        try {
            String deviceId = android.provider.Settings.Secure.getString(
                getContext().getContentResolver(),
                android.provider.Settings.Secure.ANDROID_ID
            );
            JSObject result = new JSObject();
            result.put("deviceId", deviceId != null ? deviceId : "unknown");
            call.resolve(result);
        } catch (Exception e) {
            Log.e(TAG, "Failed to get device ID", e);
            call.reject("Failed to get device ID: " + e.getMessage());
        }
    }

    @PluginMethod
    public void addDeviceInterest(PluginCall call) {
        if (!isStarted) {
            call.reject("Pusher Beams not started. Call start() first.");
            return;
        }

        String interest = call.getString("interest");
        if (interest == null || interest.isEmpty()) {
            call.reject("Interest is required");
            return;
        }

        try {
            PushNotifications.addDeviceInterest(interest);
            Log.d(TAG, "Added device interest: " + interest);
            call.resolve();
        } catch (Exception e) {
            Log.e(TAG, "Failed to add device interest", e);
            call.reject("Failed to add interest: " + e.getMessage());
        }
    }

    @PluginMethod
    public void removeDeviceInterest(PluginCall call) {
        if (!isStarted) {
            call.reject("Pusher Beams not started. Call start() first.");
            return;
        }

        String interest = call.getString("interest");
        if (interest == null || interest.isEmpty()) {
            call.reject("Interest is required");
            return;
        }

        try {
            PushNotifications.removeDeviceInterest(interest);
            Log.d(TAG, "Removed device interest: " + interest);
            call.resolve();
        } catch (Exception e) {
            Log.e(TAG, "Failed to remove device interest", e);
            call.reject("Failed to remove interest: " + e.getMessage());
        }
    }
}
