package com.dejankaravla.plugins.swipebackcontrol;

import android.os.Build;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.WebView;

import com.getcapacitor.JSObject;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.annotation.CapacitorPlugin;

import java.util.HashSet;
import java.util.Set;

@CapacitorPlugin(name = "SwipeBackControl")
public class SwipeBackControlPlugin extends Plugin {
    private static final String TAG = "SwipeBackControl";
    private Set<String> disabledPages = new HashSet<>();

    @Override
    public void load() {
        try {
            Log.i(TAG, "SwipeBackControl plugin loading...");
            disabledPages.clear(); // Reset on load
            
            // Listen for back button events from JavaScript (Web)
            getBridge().getWebView().setOnKeyListener(new View.OnKeyListener() {
                @Override
                public boolean onKey(View v, int keyCode, android.view.KeyEvent event) {
                    if (keyCode == android.view.KeyEvent.KEYCODE_BACK && event.getAction() == android.view.KeyEvent.ACTION_UP) {
                        try {
                            String currentPage = getCurrentPath();
                            boolean shouldBlockBack = disabledPages.contains(currentPage);
                            
                            if (shouldBlockBack) {
                                Log.d(TAG, "Back button blocked for page: " + currentPage);
                                return true; // Block back button
                            }
                        } catch (Exception e) {
                            Log.e(TAG, "Error in back button handler", e);
                        }
                    }
                    return false; // Let the system handle the back button
                }
            });
            
            Log.i(TAG, "SwipeBackControl plugin loaded successfully");
        } catch (Exception e) {
            Log.e(TAG, "Error during SwipeBackControl plugin loading", e);
        }
    }

    @PluginMethod
    public void enableSwipeBack(PluginCall call) {
        try {
            if (call == null) {
                Log.e(TAG, "enableSwipeBack called with null PluginCall");
                return;
            }

            Log.d(TAG, "enableSwipeBack called");
            Boolean enabled = call.getBoolean("enabled", true);
            String currentPage = call.getString("currentPage", "");

            // Safety check
            if (currentPage == null) {
                currentPage = "";
                Log.w(TAG, "Current page is null, using empty string");
            }

            // Normalize the path
            try {
                currentPage = SwipeBackControl.normalizePath(currentPage);
            } catch (Exception e) {
                Log.e(TAG, "Error normalizing path: " + currentPage, e);
                // Use a safe default
                currentPage = "/";
            }
            
            Log.d(TAG, "Configuring swipe back for page: " + currentPage + ", enabled: " + enabled);

            if (enabled) {
                disabledPages.remove(currentPage);
                Log.d(TAG, "Swipe back enabled for path: " + currentPage);
            } else {
                disabledPages.add(currentPage);
                Log.d(TAG, "Swipe back disabled for path: " + currentPage);
            }

            try {
                updateBackGestureState(currentPage);
            } catch (Exception e) {
                Log.e(TAG, "Error updating back gesture state", e);
                // Continue and resolve call anyway
            }
            
            call.resolve();
        } catch (Exception e) {
            Log.e(TAG, "Failed to enable/disable swipe back", e);
            if (call != null) {
                call.reject("Failed to enable/disable swipe back: " + e.getMessage(), e);
            }
        }
    }

    @PluginMethod
    public void disableSwipeBack(PluginCall call) {
        try {
            if (call == null) {
                Log.e(TAG, "disableSwipeBack called with null PluginCall");
                return;
            }

            Log.d(TAG, "disableSwipeBack called");
            String currentPage = getCurrentPath();
            if (currentPage == null) {
                Log.w(TAG, "Cannot determine current path, using default /");
                currentPage = "/";
            }

            Log.d(TAG, "Disabling swipe back for path: " + currentPage);
            disabledPages.add(currentPage);
            
            try {
                updateBackGestureState(currentPage);
            } catch (Exception e) {
                Log.e(TAG, "Error updating back gesture state", e);
                // Continue and resolve call anyway
            }
            
            call.resolve();
        } catch (Exception e) {
            Log.e(TAG, "Failed to disable swipe back", e);
            if (call != null) {
                call.reject("Failed to disable swipe back: " + e.getMessage(), e);
            }
        }
    }

    @PluginMethod
    public void shouldBlockBackButton(PluginCall call) {
        try {
            String currentPage = getCurrentPath();
            boolean shouldBlockBack = disabledPages.contains(currentPage);
            
            JSObject ret = new JSObject();
            ret.put("shouldBlock", shouldBlockBack);
            ret.put("currentPage", currentPage);
            
            Log.d(TAG, "Back button check for page: " + currentPage + ", shouldBlock: " + shouldBlockBack);
            call.resolve(ret);
        } catch (Exception e) {
            Log.e(TAG, "Error checking if back button should be blocked", e);
            call.reject("Error checking if back button should be blocked", e);
        }
    }

    private String getCurrentPath() {
        try {
            if (getBridge() == null) {
                Log.e(TAG, "Bridge is null");
                return "/";
            }
            
            WebView webView = getBridge().getWebView();
            if (webView == null) {
                Log.e(TAG, "WebView is null");
                return "/";
            }
            
            String url = webView.getUrl();
            if (url == null || url.isEmpty()) {
                Log.e(TAG, "WebView URL is null or empty");
                return "/";
            }
            
            return SwipeBackControl.getPathFromUrl(url);
        } catch (Exception e) {
            Log.e(TAG, "Error getting current path", e);
            return "/";
        }
    }

    private void updateBackGestureState(String currentPage) {
        if (getActivity() == null) {
            Log.e(TAG, "Activity is null, cannot update back gesture state");
            return;
        }
        
        boolean isEnabled = !disabledPages.contains(currentPage);
        Log.d(TAG, "Updating back gesture state, enabled: " + isEnabled);
        
        // For Android 10+ (API level 29+), handle system gesture navigation
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            try {
                // Run UI operations on the main thread to prevent CalledFromWrongThreadException
                getActivity().runOnUiThread(() -> {
                    try {
                        Window window = getActivity().getWindow();
                        if (window == null) {
                            Log.e(TAG, "Window is null");
                            return;
                        }
                        
                        // We don't actually disable the system gestures as that's not possible without special permissions
                        // Instead, we just indicate to the user visually that back gestures are disabled
                        if (!isEnabled) {
                            // Visual indicator that swipe back is disabled
                            window.setNavigationBarColor(0xFF444444); // Dark gray
                        } else {
                            // Reset navigation bar color
                            window.setNavigationBarColor(0x00000000); // Transparent
                        }
                    } catch (Exception e) {
                        Log.e(TAG, "Error updating navigation bar color", e);
                    }
                });
            } catch (Exception e) {
                Log.e(TAG, "Error updating navigation bar color", e);
            }
        }
    }
}
