// Browser API polyfill for cross-browser compatibility
(function() {
    'use strict';
    
    // Define browser polyfill in the global scope (works in both service workers and content scripts)
    if (typeof browser === 'undefined' && typeof chrome !== 'undefined') {
        // Use self (service worker) or window (content script) or global fallback
        const globalScope = (function() {
            if (typeof self !== 'undefined') return self;
            if (typeof window !== 'undefined') return window;
            if (typeof global !== 'undefined') return global;
            return this;
        })();
        
        globalScope.browser = chrome;
    }
})();

(function(browser) {
    'use strict';
    
    // Detect browser type
    const getBrowserType = () => {
        const userAgent = navigator.userAgent;
        if (userAgent.includes('Safari') && !userAgent.includes('Chrome') && !userAgent.includes('Chromium')) {
            return 'Safari';
        } else if (userAgent.includes('Firefox')) {
            return 'Firefox';
        } else if (userAgent.includes('Chrome') || userAgent.includes('Chromium')) {
            return 'Chrome';
        }
        return 'Unknown';
    };

    const browserType = getBrowserType();
    const isSafari = browserType === 'Safari';
    const isChrome = browserType === 'Chrome';
    const isFirefox = browserType === 'Firefox';
    
    // Check if native messaging is available
    const hasNativeMessaging = typeof browser !== 'undefined' && 
                               browser.runtime && 
                               typeof browser.runtime.sendNativeMessage === 'function';
    
    console.log(`OpenIn: Initializing for ${browserType} (Native messaging: ${hasNativeMessaging})`);

    // Function to get current tab info for context
    const getTabInfo = function(tab) {
        return {
            url: tab.url,
            title: tab.title,
            id: tab.id,
            windowId: tab.windowId,
            active: tab.active,
            incognito: tab.incognito
        };
    };

    // Function to open URL in OpenIn app - Native messaging version
    const openInAppNative = function(url, tabInfo = null, source = "unknown") {
        const message = {
            action: "openInApp",
            url: url,
            tabInfo: tabInfo,
            source: source,
            browser: browserType
        };
        
        console.log(`OpenIn: Sending to ${browserType} native host:`, message);
        
        // Determine native application name based on browser
        let nativeAppName;
        if (isSafari) {
            // Safari uses built-in extension host
            nativeAppName = null;
        } else if (isChrome || isFirefox) {
            // Chrome and Firefox use external native messaging host
            nativeAppName = "app.loshadki.openin";
        }
        
        const sendNativeMessage = nativeAppName ? 
            browser.runtime.sendNativeMessage(nativeAppName, message) :
            browser.runtime.sendNativeMessage(message);
            
        sendNativeMessage.then((response) => {
            console.log(`OpenIn: ${browserType} native host response:`, response);
        }).catch((error) => {
            console.error(`OpenIn: ${browserType} native messaging failed, falling back to URL scheme:`, error);
            // Fallback to URL scheme if native messaging fails
            openInAppFallback(url, source, tabInfo ? tabInfo.id : null);
        });
    };

    // Function to open URL in OpenIn app - Other browsers fallback
    const openInAppFallback = function(url, source = "unknown", tabId = null) {
        const openInUrl = `openin://open?url=${encodeURIComponent(url)}&source=${encodeURIComponent("browserExtension:" + source)}`;
        
        console.log("OpenIn: Using URL scheme fallback:", openInUrl);
        
        // Try to update current tab first (cleaner approach)
        if (tabId) {
            const updateTab = browser.tabs.update(tabId, { url: openInUrl });
            
            // Handle both promise-based (Firefox/Safari) and callback-based (Chrome) APIs
            if (updateTab && typeof updateTab.then === 'function') {
                // Promise-based API
                updateTab.then(() => {
                    console.log("OpenIn: Updated current tab with openin:// URL");
                }).catch((error) => {
                    console.log("OpenIn: Failed to update tab (possibly in saved group), creating new tab:", error);
                    createNewTabFallback(openInUrl);
                });
            } else {
                // Callback-based API (Chrome)
                browser.tabs.update(tabId, { url: openInUrl }, () => {
                    if (browser.runtime.lastError) {
                        console.log("OpenIn: Failed to update tab (possibly in saved group), creating new tab:", browser.runtime.lastError);
                        createNewTabFallback(openInUrl);
                    } else {
                        console.log("OpenIn: Updated current tab with openin:// URL");
                    }
                });
            }
        } else {
            // No tab ID provided, create new tab
            createNewTabFallback(openInUrl);
        }
    };
    
    // Helper function to create and close temporary tab
    const createNewTabFallback = function(openInUrl) {
        const createTab = browser.tabs.create({ url: openInUrl });
        
        // Handle both promise-based (Firefox/Safari) and callback-based (Chrome) APIs
        if (createTab && typeof createTab.then === 'function') {
            // Promise-based API
            createTab.then((tab) => {
                console.log("OpenIn: Created new tab with openin:// URL");
                // Close the tab after a short delay since the URL scheme should have opened the app
                setTimeout(() => {
                    browser.tabs.remove(tab.id).catch(() => {
                        // Ignore errors if tab was already closed
                    });
                }, 1000);
            }).catch((error) => {
                console.error("OpenIn: Failed to create tab:", error);
            });
        } else {
            // Callback-based API (Chrome)
            browser.tabs.create({ url: openInUrl }, (tab) => {
                if (browser.runtime.lastError) {
                    console.error("OpenIn: Failed to create tab:", browser.runtime.lastError);
                    return;
                }
                console.log("OpenIn: Created new tab with openin:// URL");
                // Close the tab after a short delay
                setTimeout(() => {
                    browser.tabs.remove(tab.id, () => {
                        // Ignore errors if tab was already closed
                    });
                }, 1000);
            });
        }
    };

    // Main function to open URL in OpenIn app
    const openInApp = function(url, tabInfo = null, source = "unknown") {
        console.log(`OpenIn: Opening URL in app (${browserType}):`, url);
        
        // Use native messaging if available, otherwise fallback to URL scheme
        if (hasNativeMessaging) {
            openInAppNative(url, tabInfo, source);
        } else {
            const tabId = tabInfo ? tabInfo.id : null;
            openInAppFallback(url, source, tabId);
        }
    };

    // Handle toolbar icon click - compatible with both Manifest V2 and V3
    const actionAPI = browser.action || browser.browserAction;
    if (actionAPI && actionAPI.onClicked) {
        actionAPI.onClicked.addListener((tab) => {
            console.log("OpenIn: Toolbar icon clicked");
            openInApp(tab.url, getTabInfo(tab), "toolbar");
        });
    } else {
        console.error("OpenIn: No action API available");
    }

    // Create context menu item
    browser.runtime.onInstalled.addListener(() => {
        console.log("OpenIn: Extension installed/updated, creating context menu");
        
        const createMenu = browser.contextMenus.create({
            id: "openInOpenIn",
            title: "Open in OpenIn",
            contexts: ["link"]
        });
        
        // Handle both promise-based and callback-based APIs
        if (createMenu && typeof createMenu.then === 'function') {
            createMenu.then(() => {
                console.log("OpenIn: Context menu created successfully");
            }).catch((error) => {
                console.error("OpenIn: Failed to create context menu:", error);
            });
        } else if (browser.runtime.lastError) {
            console.error("OpenIn: Failed to create context menu:", browser.runtime.lastError);
        } else {
            console.log("OpenIn: Context menu created successfully");
        }
    });

    // Handle context menu clicks
    browser.contextMenus.onClicked.addListener((info, tab) => {
        console.log("OpenIn: Context menu clicked");
        
        if (info.menuItemId === "openInOpenIn" && info.linkUrl) {
            openInApp(info.linkUrl, getTabInfo(tab), "contextmenu");
        }
    });

    // Listen for messages from content script
    browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
        if (message.action === "openInApp" && message.url) {
            console.log("OpenIn: Received openInApp message from content script");
            
            // For content script messages, try to get current active tab if sender info is incomplete
            if (message.fromContentScript && (!sender.tab || !sender.tab.id)) {
                // Query for current active tab
                const queryTabs = browser.tabs.query({ active: true, currentWindow: true });
                
                if (queryTabs && typeof queryTabs.then === 'function') {
                    // Promise-based API
                    queryTabs.then((tabs) => {
                        const currentTab = tabs[0];
                        const tabInfo = currentTab ? getTabInfo(currentTab) : null;
                        const source = message.source || "link";
                        openInApp(message.url, tabInfo, source);
                        sendResponse({ success: true });
                    }).catch((error) => {
                        console.log("OpenIn: Failed to query current tab:", error);
                        const source = message.source || "link";
                        openInApp(message.url, null, source);
                        sendResponse({ success: true });
                    });
                } else {
                    // Callback-based API
                    browser.tabs.query({ active: true, currentWindow: true }, (tabs) => {
                        if (browser.runtime.lastError) {
                            console.log("OpenIn: Failed to query current tab:", browser.runtime.lastError);
                            const source = message.source || "link";
                            openInApp(message.url, null, source);
                        } else {
                            const currentTab = tabs[0];
                            const tabInfo = currentTab ? getTabInfo(currentTab) : null;
                            const source = message.source || "link";
                            openInApp(message.url, tabInfo, source);
                        }
                        sendResponse({ success: true });
                    });
                }
                return true; // Keep message channel open for async response
            } else {
                // Regular handling for toolbar/context menu or when sender tab is available
                const tabInfo = sender.tab ? getTabInfo(sender.tab) : null;
                const source = message.source || "link";
                openInApp(message.url, tabInfo, source);
                sendResponse({ success: true });
            }
            
        } else if (message.action === "getSettings") {
            console.log("OpenIn: Received getSettings message");
            
            // Get all settings
            const settingsKeys = ['linkBehavior', 'domainMatching', 'modifierKeys', 'respectTargetBlank'];
            
            const getSettings = browser.storage.sync.get(settingsKeys);
            
            // Handle both promise-based and callback-based APIs
            if (getSettings && typeof getSettings.then === 'function') {
                // Promise-based API
                getSettings.then((result) => {
                    const settings = {
                        linkBehavior: result.linkBehavior || 'disabled',
                        domainMatching: result.domainMatching || 'base',
                        modifierKeys: result.modifierKeys || {
                            cmd: false,
                            shift: false,
                            alt: false,
                            ctrl: false
                        },
                        respectTargetBlank: result.respectTargetBlank !== undefined ? result.respectTargetBlank : true,
                        browser: browserType,
                        hasNativeMessaging: hasNativeMessaging
                    };
                    
                    sendResponse(settings);
                }).catch((error) => {
                    console.error("OpenIn: Failed to get settings:", error);
                    sendResponse({ 
                        linkBehavior: 'disabled',
                        domainMatching: 'base',
                        modifierKeys: { cmd: false, shift: false, alt: false, ctrl: false },
                        respectTargetBlank: true,
                        browser: browserType,
                        hasNativeMessaging: hasNativeMessaging,
                        error: error.message 
                    });
                });
            } else {
                // Callback-based API
                browser.storage.sync.get(settingsKeys, (result) => {
                    if (browser.runtime.lastError) {
                        console.error("OpenIn: Failed to get settings:", browser.runtime.lastError);
                        sendResponse({ 
                            linkBehavior: 'disabled',
                            domainMatching: 'base',
                            modifierKeys: { cmd: false, shift: false, alt: false, ctrl: false },
                            respectTargetBlank: true,
                            browser: browserType,
                            hasNativeMessaging: hasNativeMessaging,
                            error: browser.runtime.lastError.message 
                        });
                        return;
                    }
                    
                    const settings = {
                        linkBehavior: result.linkBehavior || 'disabled',
                        domainMatching: result.domainMatching || 'base',
                        modifierKeys: result.modifierKeys || {
                            cmd: false,
                            shift: false,
                            alt: false,
                            ctrl: false
                        },
                        respectTargetBlank: result.respectTargetBlank !== undefined ? result.respectTargetBlank : true,
                        browser: browserType,
                        hasNativeMessaging: hasNativeMessaging
                    };
                    
                    sendResponse(settings);
                });
            }
            
            return true; // Keep message channel open for async response
            
        } else if (message.action === "getBrowserInfo") {
            // Allow content script to query browser type and capabilities
            sendResponse({
                browser: browserType,
                isSafari: isSafari,
                isChrome: isChrome,
                isFirefox: isFirefox,
                hasNativeMessaging: hasNativeMessaging,
                extensionInfo: {
                    name: "OpenIn",
                    version: "4.3"
                }
            });
        }
    });

    // Browser-specific initialization logging
    if (hasNativeMessaging) {
        if (isSafari) {
            console.log("OpenIn: Safari Web Extension - using built-in native messaging");
        } else {
            console.log(`OpenIn: ${browserType} extension - using external native messaging host`);
        }
    } else {
        console.log(`OpenIn: ${browserType} extension - native messaging not available, using URL scheme fallback`);
    }

})(typeof browser !== 'undefined' ? browser : chrome);
