/**
 * Note: URLValidator is available globally via /static/js/security/url-validator.js
 * Research Component
 * Manages the research form and handles submissions
 */
(function() {
    // Form validator instance
    let researchValidator = null;

    // DOM Elements
    let form = null;
    let queryInput = null;
    let modeOptions = null;
    let notificationToggle = null;
    let startBtn = null;
    let modelProviderSelect = null;
    let customEndpointInput = null;
    let endpointContainer = null;
    let anthropicEndpointUrlInput = null;
    let anthropicEndpointContainer = null;
    let ollamaUrlInput = null;
    let ollamaUrlContainer = null;
    let lmstudioUrlInput = null;
    let lmstudioUrlContainer = null;
    let contextWindowInput = null;
    let contextWindowContainer = null;
    // API Key inputs and containers
    let openaiApiKeyInput = null;
    let openaiApiKeyContainer = null;
    let anthropicApiKeyInput = null;
    let anthropicApiKeyContainer = null;
    let googleApiKeyInput = null;
    let googleApiKeyContainer = null;
    let openrouterApiKeyInput = null;
    let openrouterApiKeyContainer = null;
    let xaiApiKeyInput = null;
    let xaiApiKeyContainer = null;
    let ionosApiKeyInput = null;
    let ionosApiKeyContainer = null;
    let openaiEndpointApiKeyInput = null;
    let openaiEndpointApiKeyContainer = null;
    let anthropicEndpointApiKeyInput = null;
    let anthropicEndpointApiKeyContainer = null;
    let ollamaApiKeyInput = null;
    let ollamaApiKeyContainer = null;
    let lmstudioApiKeyInput = null;
    let lmstudioApiKeyContainer = null;
    let modelInput = null;
    let modelDropdown = null;
    let modelDropdownList = null;
    let modelRefreshBtn = null;
    let searchEngineInput = null;
    let searchEngineDropdown = null;
    let searchEngineDropdownList = null;
    let searchEngineRefreshBtn = null;
    let advancedToggle = null;
    let advancedPanel = null;

    // Cache keys for in-memory cache (5-minute expiration, clears on page reload)
    const CACHE_KEYS = {
        MODELS: 'deepResearch.availableModels',
        SEARCH_ENGINES: 'deepResearch.searchEngines'
    };

    // Cache expiration time (24 hours in milliseconds)
    const CACHE_EXPIRATION = 24 * 60 * 60 * 1000;

    // State variables for dropdowns
    let modelOptions = [];
    let selectedModelValue = '';
    const modelSelectedIndex = -1;
    let searchEngineOptions = [];
    let selectedSearchEngineValue = '';
    const searchEngineSelectedIndex = -1;

    // Track initialization to prevent unwanted saves during initial setup
    let isInitializing = true;

    // Store pending rerun config to apply after initialization completes
    let pendingRerunConfig = null;

    /**
     * Select a research mode (both visual and radio button)
     * @param {HTMLElement} modeElement - The mode option element that was selected
     */
    function selectMode(modeElement) {
        // Update visual appearance
        modeOptions.forEach(m => {
            m.classList.remove('active');
            m.setAttribute('tabindex', '-1');
        });

        modeElement.classList.add('active');
        modeElement.setAttribute('tabindex', '0');

        // Update the corresponding radio button
        const modeValue = modeElement.getAttribute('data-mode');
        const radioButton = document.getElementById(`mode-${modeValue}`);
        if (radioButton) {
            radioButton.checked = true;
        }
    }

    // Model provider options - will be populated dynamically from API
    let MODEL_PROVIDERS = [];

    // Store available models by provider - will be populated dynamically from API
    let availableModels = {};

    /**
     * Check if a provider is a local provider (not cloud-based)
     * Uses the is_cloud attribute from provider metadata
     * @param {string} providerKey - The provider key (e.g., 'OLLAMA', 'LMSTUDIO')
     * @returns {boolean} - True if the provider is local (is_cloud === false)
     */
    function isLocalProvider(providerKey) {
        if (!providerKey) return false;
        const provider = MODEL_PROVIDERS.find(
            p => p.value && p.value.toUpperCase() === providerKey.toUpperCase()
        );
        // Use is_cloud from provider metadata; return false if provider not found yet
        return provider ? provider.is_cloud === false : false;
    }

    /**
     * Get saved advanced menu state from localStorage.
     * @returns {boolean} true if panel should be open (defaults to true for first visit)
     */
    function getAdvancedMenuState() {
        const saved = localStorage.getItem('advancedMenuOpen');
        // Default to open for new users so they discover the available options
        return saved === null ? true : saved === 'true';
    }

    /**
     * Apply advanced options panel state to the DOM.
     * Syncs toggle button classes, ARIA attributes, icon, and panel visibility.
     * @param {boolean} isOpen - Whether the panel should be open
     */
    function applyAdvancedOptionsState(isOpen) {
        if (!advancedToggle || !advancedPanel) return;

        advancedToggle.classList.toggle('ldr-open', isOpen);
        advancedPanel.classList.toggle('ldr-expanded', isOpen);
        advancedToggle.setAttribute('aria-expanded', String(isOpen));

        const srText = advancedToggle.querySelector('.sr-only');
        if (srText) {
            srText.textContent = isOpen
                ? 'Click to collapse advanced options'
                : 'Click to expand advanced options';
        }

        const icon = advancedToggle.querySelector('i');
        if (icon) {
            icon.className = isOpen ? 'fas fa-chevron-up' : 'fas fa-chevron-down';
        }
    }

    /**
     * Check for rerun configuration from sessionStorage.
     * Stores it for later application after initialization completes.
     */
    function checkAndApplyRerunConfig() {
        let rerunConfigStr;
        try {
            rerunConfigStr = sessionStorage.getItem('rerunConfig');
        } catch (e) {
            SafeLogger.warn('Could not read rerun config from sessionStorage:', e);
            return;
        }
        if (!rerunConfigStr) return;

        try {
            pendingRerunConfig = JSON.parse(rerunConfigStr);
            sessionStorage.removeItem('rerunConfig'); // Clear immediately
            SafeLogger.log('Stored pending rerun config:', pendingRerunConfig);
        } catch (e) {
            SafeLogger.error('Error parsing rerun config:', e);
            sessionStorage.removeItem('rerunConfig');
            pendingRerunConfig = null;
        }
    }

    /**
     * Apply pending rerun configuration after initialization is complete.
     * Only pre-fills query and mode; all other settings come from the
     * settings manager / database (the current user defaults).
     */
    function applyPendingRerunConfig() {
        if (!pendingRerunConfig) return;

        const config = pendingRerunConfig;
        pendingRerunConfig = null; // Clear to prevent re-application
        SafeLogger.log('Applying rerun config:', config);

        // Set query
        const queryEl = document.getElementById('query');
        if (queryEl && config.query) {
            queryEl.value = config.query;
        }

        // Set mode via the visible label element so both the radio and
        // the visual highlight update correctly
        if (config.mode) {
            const modeOption = document.querySelector(`.ldr-mode-option[data-mode="${CSS.escape(config.mode)}"]`);
            if (modeOption) {
                selectMode(modeOption);
            }
        }

        // Show notification
        showRerunNotification();
    }

    /**
     * Called when initialization completes. Applies any pending rerun config.
     */
    function onInitializationComplete() {
        SafeLogger.log('Initialization complete, checking for pending rerun config');
        applyPendingRerunConfig();
    }

    /**
     * Show notification that form has been pre-filled for re-run
     */
    function showRerunNotification() {
        const alertContainer = document.getElementById('research-alert');
        if (alertContainer) {
            alertContainer.style.display = 'block';
            alertContainer.innerHTML = `
                <div class="alert alert-info alert-dismissible fade show" role="alert">
                    <i class="fas fa-redo me-2"></i>
                    Re-running previous research. Review settings and click "Start Research" when ready.
                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
                </div>
            `;
        }
    }

    /**
     * Initialize the research component
     */
    function initializeResearch() {
        // Set initializing flag
        isInitializing = true;
        SafeLogger.log('=== Starting research page initialization. isInitializing:', isInitializing);

        // Check for rerun config from history page
        checkAndApplyRerunConfig();

        // Get DOM elements
        form = document.getElementById('research-form');
        queryInput = document.getElementById('query');
        modeOptions = document.querySelectorAll('.ldr-mode-option');
        notificationToggle = document.getElementById('notification-toggle');
        startBtn = document.getElementById('start-research-btn');
        modelProviderSelect = document.getElementById('model_provider');
        customEndpointInput = document.getElementById('custom_endpoint');
        endpointContainer = document.getElementById('endpoint_container');
        anthropicEndpointUrlInput = document.getElementById('anthropic_endpoint_url');
        anthropicEndpointContainer = document.getElementById('anthropic_endpoint_container');
        ollamaUrlInput = document.getElementById('ollama_url');
        ollamaUrlContainer = document.getElementById('ollama_url_container');
        lmstudioUrlInput = document.getElementById('lmstudio_url');
        lmstudioUrlContainer = document.getElementById('lmstudio_url_container');
        contextWindowInput = document.getElementById('context_window');
        contextWindowContainer = document.getElementById('context_window_container');

        // API Key elements
        openaiApiKeyInput = document.getElementById('openai_api_key');
        openaiApiKeyContainer = document.getElementById('openai_api_key_container');
        anthropicApiKeyInput = document.getElementById('anthropic_api_key');
        anthropicApiKeyContainer = document.getElementById('anthropic_api_key_container');
        googleApiKeyInput = document.getElementById('google_api_key');
        googleApiKeyContainer = document.getElementById('google_api_key_container');
        openrouterApiKeyInput = document.getElementById('openrouter_api_key');
        openrouterApiKeyContainer = document.getElementById('openrouter_api_key_container');
        xaiApiKeyInput = document.getElementById('xai_api_key');
        xaiApiKeyContainer = document.getElementById('xai_api_key_container');
        ionosApiKeyInput = document.getElementById('ionos_api_key');
        ionosApiKeyContainer = document.getElementById('ionos_api_key_container');
        openaiEndpointApiKeyInput = document.getElementById('openai_endpoint_api_key');
        openaiEndpointApiKeyContainer = document.getElementById('openai_endpoint_api_key_container');
        anthropicEndpointApiKeyInput = document.getElementById('anthropic_endpoint_api_key');
        anthropicEndpointApiKeyContainer = document.getElementById('anthropic_endpoint_api_key_container');
        ollamaApiKeyInput = document.getElementById('ollama_api_key');
        ollamaApiKeyContainer = document.getElementById('ollama_api_key_container');
        lmstudioApiKeyInput = document.getElementById('lmstudio_api_key');
        lmstudioApiKeyContainer = document.getElementById('lmstudio_api_key_container');

        // Custom dropdown elements
        modelInput = document.getElementById('model');
        modelDropdown = document.getElementById('model-dropdown');
        modelDropdownList = document.getElementById('model-dropdown-list');
        modelRefreshBtn = document.getElementById('model-refresh');

        searchEngineInput = document.getElementById('search_engine');
        searchEngineDropdown = document.getElementById('search-engine-dropdown');
        searchEngineDropdownList = document.getElementById('search-engine-dropdown-list');
        searchEngineRefreshBtn = document.getElementById('search_engine-refresh');

        // Other form elements
        advancedToggle = document.querySelector('.ldr-advanced-options-toggle');
        advancedPanel = document.querySelector('.ldr-advanced-options-panel');

        // Note: Settings are now loaded from the database via the template
        // The form values are already set by the server-side rendering
        // We just need to initialize the UI components

        // Initialize the UI first (immediate operations)
        setupEventListeners();
        // Don't populate providers yet - wait for API data
        initializeDropdowns();

        // Don't set initial values yet - wait for model options to load first
        // setInitialFormValues() will be called after loadSettings() completes

        // Auto-focus the query input
        if (queryInput) {
            queryInput.focus();
            // Move cursor to end if there's existing text
            if (queryInput.value) {
                queryInput.setSelectionRange(queryInput.value.length, queryInput.value.length);
            }
        }

        // Then load data asynchronously (don't block UI)
        Promise.all([
            loadModelOptions(false),
            loadSearchEngineOptions(false)
        ]).then(([_modelData, searchEngineData]) => {
            // After loading model data, update the UI with the loaded data
            const currentProvider = modelProviderSelect ? modelProviderSelect.value : 'OLLAMA';
            updateModelOptionsForProvider(currentProvider, false);

            // Update search engine options
            if (searchEngineData && Array.isArray(searchEngineData)) {
                searchEngineOptions = searchEngineData;

                // Force search engine dropdown to update with new data
                if (searchEngineDropdownList && window.setupCustomDropdown) {
                    // Recreate the dropdown with the new data
                    const searchDropdownInstance = window.setupCustomDropdown(
                        searchEngineInput,
                        searchEngineDropdownList,
                        () => (searchEngineOptions.length > 0 ? searchEngineOptions : [{ value: '', label: 'No search engines available' }]),
                        (value, item) => {
                            selectedSearchEngineValue = value;

                            // Update the input field
                            if (item) {
                                searchEngineInput.value = item.label;
                            } else {
                                searchEngineInput.value = value;
                            }

                            // Only save if not initializing
                            if (!isInitializing) {
                                saveSearchEngineSettings(value);
                            }
                        },
                        false,
                        'No search engines available.',
                        handleSearchEngineFavoriteToggle
                    );

                    // If we have a last selected search engine, try to select it
                    const lastSearchEngine = searchEngineInput?.getAttribute('data-initial-value') ||
                                           localStorage.getItem('selected_search_engine');
                    if (lastSearchEngine) {
                        // Find the matching engine
                        const matchingEngine = searchEngineOptions.find(engine =>
                            engine.value === lastSearchEngine || engine.id === lastSearchEngine);

                        if (matchingEngine) {
                            searchEngineInput.value = matchingEngine.label;
                            selectedSearchEngineValue = matchingEngine.value;

                            // Update hidden input if exists
                            const hiddenInput = document.getElementById('search_engine_hidden');
                            if (hiddenInput) {
                                hiddenInput.value = matchingEngine.value;
                            }
                        }
                    }
                }
            }

            // Set initial form values from data attributes
            setInitialFormValues();

            // Finally, load settings after data is available
            loadSettings();
        }).catch(error => {
            SafeLogger.error('Failed to load options:', error);

            // Set initial form values even if data loading fails
            setInitialFormValues();

            // Still load settings even if data loading fails
            loadSettings();

            if (window.ui && window.ui.showAlert) {
                window.ui.showAlert('Some options could not be loaded. Using defaults instead.', 'warning');
            }
        });
    }

    /**
     * Initialize custom dropdowns for model and search engine
     */
    function initializeDropdowns() {
        // Check if the custom dropdown script is loaded
        if (typeof window.setupCustomDropdown !== 'function') {
            SafeLogger.error('Custom dropdown script is not loaded');
            // Display an error message
            if (window.ui && window.ui.showAlert) {
                window.ui.showAlert('Failed to initialize dropdowns. Please reload the page.', 'error');
            }
            return;
        }

        SafeLogger.log('Initializing dropdowns with setupCustomDropdown');

        // Set up model dropdown
        if (modelInput && modelDropdownList) {
            // Clear any existing dropdown setup
            modelDropdownList.innerHTML = '';
            const modelDropdownInstance = window.setupCustomDropdown(
                modelInput,
                modelDropdownList,
                () => {
                    SafeLogger.log('Getting model options from dropdown:', modelOptions);
                    return modelOptions.length > 0 ? modelOptions : [{ value: '', label: 'No models available' }];
                },
                (value, item) => {
                    SafeLogger.log('Model selected:', value, item);
                    SafeLogger.log('isInitializing flag:', isInitializing);
                    selectedModelValue = value;

                    // Update the input field with the selected model's label or value
                    if (item) {
                        modelInput.value = item.label;
                    } else {
                        modelInput.value = value;
                    }

                    const isCustomValue = !item;
                    showCustomModelWarning(isCustomValue);

                    // Save selected model to settings - only if not initializing
                    if (!isInitializing) {
                        SafeLogger.log('Saving model to database:', value);
                        saveModelSettings(value);
                    } else {
                        SafeLogger.log('Skipping save - still initializing');
                    }
                },
                true, // Allow custom values
                'No models available. Type to enter a custom model name.'
            );

            // Initialize model refresh button
            if (modelRefreshBtn) {
                modelRefreshBtn.addEventListener('click', function() {
                    const icon = modelRefreshBtn.querySelector('i');

                    // Add loading class to button
                    modelRefreshBtn.classList.add('ldr-loading');

                    // Force refresh of model options
                    loadModelOptions(true).then(() => {
                        // Remove loading class
                        modelRefreshBtn.classList.remove('ldr-loading');

                        // Ensure the current provider's models are loaded
                        const currentProvider = modelProviderSelect ? modelProviderSelect.value : 'OLLAMA';
                        updateModelOptionsForProvider(currentProvider, false);

                        // Force dropdown update
                        const event = new Event('click', { bubbles: true });
                        modelInput.dispatchEvent(event);
                    }).catch(error => {
                        SafeLogger.error('Error refreshing models:', error);

                        // Remove loading class
                        modelRefreshBtn.classList.remove('ldr-loading');

                        if (window.ui && window.ui.showAlert) {
                            window.ui.showAlert('Failed to refresh models: ' + error.message, 'error');
                        }
                    });
                });
            }
        }

        // Set up search engine dropdown
        if (searchEngineInput && searchEngineDropdownList) {
            // Clear any existing dropdown setup
            searchEngineDropdownList.innerHTML = '';

            // Add loading state to search engine input
            if (searchEngineInput.parentNode) {
                searchEngineInput.parentNode.classList.add('ldr-loading');
            }
            const searchDropdownInstance = window.setupCustomDropdown(
                searchEngineInput,
                searchEngineDropdownList,
                () => {
                    // Log available search engines for debugging
                    SafeLogger.log('Getting search engine options:', searchEngineOptions);
                    return searchEngineOptions.length > 0 ? searchEngineOptions : [{ value: '', label: 'No search engines available' }];
                },
                (value, item) => {
                    SafeLogger.log('Search engine selected:', value, item);
                    selectedSearchEngineValue = value;

                    // Update the input field with the selected search engine's label or value
                    if (item) {
                        searchEngineInput.value = item.label;
                    } else {
                        searchEngineInput.value = value;
                    }

                    // Keep the hidden input in sync so the STRICT-scope
                    // availability check (and form submit) see the new value.
                    const seHidden = document.getElementById('search_engine_hidden');
                    if (seHidden) {
                        seHidden.value = value;
                    }

                    // Save search engine selection to settings - only if not initializing
                    if (!isInitializing) {
                        saveSearchEngineSettings(value);
                    }
                },
                false, // Don't allow custom values
                'No search engines available.',
                handleSearchEngineFavoriteToggle
            );

            // Initialize search engine refresh button
            if (searchEngineRefreshBtn) {
                searchEngineRefreshBtn.addEventListener('click', function() {
                    const icon = searchEngineRefreshBtn.querySelector('i');

                    // Add loading class to button
                    searchEngineRefreshBtn.classList.add('ldr-loading');

                    // Force refresh of search engine options
                    loadSearchEngineOptions(true).then(() => {
                        // Remove loading class
                        searchEngineRefreshBtn.classList.remove('ldr-loading');

                        // Force dropdown update
                        const event = new Event('click', { bubbles: true });
                        searchEngineInput.dispatchEvent(event);
                    }).catch(error => {
                        SafeLogger.error('Error refreshing search engines:', error);

                        // Remove loading class
                        searchEngineRefreshBtn.classList.remove('ldr-loading');

                        if (window.ui && window.ui.showAlert) {
                            window.ui.showAlert('Failed to refresh search engines: ' + error.message, 'error');
                        }
                    });
                });
            }
        }
    }

    /**
     * Set initial form values from data attributes
     */
    function setInitialFormValues() {
        SafeLogger.log('Setting initial form values...');

        // Set initial model value if available
        if (modelInput) {
            const initialModel = modelInput.getAttribute('data-initial-value');
            SafeLogger.log('Initial model value from data attribute:', initialModel);
            if (initialModel) {
                // Find the matching model in the options
                const matchingModel = modelOptions.find(m =>
                    m.value === initialModel || m.id === initialModel
                );

                if (matchingModel) {
                    modelInput.value = matchingModel.label;
                    selectedModelValue = matchingModel.value;
                } else {
                    // If not found in options, set it as custom value
                    modelInput.value = initialModel;
                    selectedModelValue = initialModel;
                }

                // Update hidden input
                const hiddenInput = document.getElementById('model_hidden');
                if (hiddenInput) {
                    hiddenInput.value = selectedModelValue;
                }
            }
        }

        // Set initial search engine value if available
        if (searchEngineInput) {
            const initialSearchEngine = searchEngineInput.getAttribute('data-initial-value');
            if (initialSearchEngine) {
                // Find the matching search engine in the options
                const matchingEngine = searchEngineOptions.find(e =>
                    e.value === initialSearchEngine || e.id === initialSearchEngine
                );

                if (matchingEngine) {
                    searchEngineInput.value = matchingEngine.label;
                    selectedSearchEngineValue = matchingEngine.value;
                } else {
                    searchEngineInput.value = initialSearchEngine;
                    selectedSearchEngineValue = initialSearchEngine;
                }

                // Update hidden input
                const hiddenInput = document.getElementById('search_engine_hidden');
                if (hiddenInput) {
                    hiddenInput.value = selectedSearchEngineValue;
                }
            }
        }
    }

    /**
     * Setup event listeners
     */
    function setupEventListeners() {
        if (!form || !startBtn) return;

        // Setup inline form validation for query field
        if (window.FormValidator && queryInput) {
            researchValidator = new window.FormValidator();
            researchValidator.addValidation(
                queryInput,
                window.formValidators.required('Please enter a research query.'),
                { validateOnBlur: false, validateOnInput: false }
            );
        }

        // INITIALIZE ADVANCED OPTIONS FIRST - before any async operations
        // Advanced options toggle - make immediately responsive
        if (advancedToggle && advancedPanel) {
            // Set initial state based on localStorage (default to open)
            applyAdvancedOptionsState(getAdvancedMenuState());

            // Add the click listener
            advancedToggle.addEventListener('click', function() {
                const isOpen = !advancedToggle.classList.contains('ldr-open');
                applyAdvancedOptionsState(isOpen);
                localStorage.setItem('advancedMenuOpen', isOpen.toString());
            });

            // Add keyboard support for the advanced options toggle
            advancedToggle.addEventListener('keydown', function(event) {
                if (event.key === 'Enter' || event.key === ' ') {
                    event.preventDefault();
                    this.click(); // Trigger the click handler
                }
            });
        }

        // Global keyboard shortcuts for this page
        document.addEventListener('keydown', function(event) {
            // Escape key: return focus to search field (override global Esc behavior when on search page)
            if (event.key === 'Escape') {
                if (queryInput && document.activeElement !== queryInput) {
                    event.preventDefault();
                    event.stopPropagation(); // Prevent global keyboard service from handling this
                    queryInput.focus();
                    queryInput.select(); // Select all text for easy replacement
                }
            }

            // Ctrl/Cmd + Enter: submit form from anywhere on the page
            if ((event.ctrlKey || event.metaKey) && event.key === 'Enter') {
                if (form) {
                    event.preventDefault();
                    handleResearchSubmit(new Event('submit'));
                }
            }
        });

        // Form submission
        form.addEventListener('submit', handleResearchSubmit);

        // Mode selection - updated for accessibility
        modeOptions.forEach(mode => {
            mode.addEventListener('click', function() {
                selectMode(this);
            });

            mode.addEventListener('keydown', function(event) {
                if (event.key === 'Enter' || event.key === ' ') {
                    event.preventDefault();
                    selectMode(this);
                } else if (event.key === 'ArrowLeft' || event.key === 'ArrowUp') {
                    event.preventDefault();
                    // Find the previous mode option, skipping hidden inputs
                    const allModeOptions = Array.from(document.querySelectorAll('.ldr-mode-option'));
                    const currentIndex = allModeOptions.indexOf(this);
                    const previousMode = allModeOptions[currentIndex - 1];
                    if (previousMode) {
                        selectMode(previousMode);
                        previousMode.focus();
                    }
                } else if (event.key === 'ArrowRight' || event.key === 'ArrowDown') {
                    event.preventDefault();
                    // Find the next mode option, skipping hidden inputs
                    const allModeOptions = Array.from(document.querySelectorAll('.ldr-mode-option'));
                    const currentIndex = allModeOptions.indexOf(this);
                    const nextMode = allModeOptions[currentIndex + 1];
                    if (nextMode) {
                        selectMode(nextMode);
                        nextMode.focus();
                    }
                }
            });
        });

        // Add keyboard shortcuts for textarea
        if (queryInput) {
            queryInput.addEventListener('keydown', function(event) {
                if (event.key === 'Enter') {
                    if (event.shiftKey) {
                        // Allow default behavior (new line) — fall through
                    } else if (event.ctrlKey || event.metaKey) {
                        // Ctrl+Enter or Cmd+Enter = Submit form (common pattern)
                        event.preventDefault();
                        handleResearchSubmit(new Event('submit'));
                    } else {
                        // Just Enter = Submit form (keeping existing behavior)
                        event.preventDefault();
                        handleResearchSubmit(new Event('submit'));
                    }
                }
            });
        }

        // Model provider change
        if (modelProviderSelect) {
            modelProviderSelect.addEventListener('change', function() {
                const provider = this.value;
                SafeLogger.log('Model provider changed to:', provider);

                // Show custom endpoint input if OpenAI endpoint is selected
                if (endpointContainer) {
                    endpointContainer.style.display = provider === 'OPENAI_ENDPOINT' ? 'block' : 'none';
                }

                // Show Anthropic endpoint input if Anthropic endpoint is selected
                if (anthropicEndpointContainer) {
                    anthropicEndpointContainer.style.display = provider === 'ANTHROPIC_ENDPOINT' ? 'block' : 'none';
                }

                // Show Ollama URL input if Ollama is selected
                if (ollamaUrlContainer) {
                    ollamaUrlContainer.style.display = provider === 'OLLAMA' ? 'block' : 'none';
                }

                // Show LM Studio URL input if LMSTUDIO is selected
                if (lmstudioUrlContainer) {
                    lmstudioUrlContainer.style.display = provider === 'LMSTUDIO' ? 'block' : 'none';
                }

                // Show context window for local providers
                if (contextWindowContainer) {
                    contextWindowContainer.style.display = isLocalProvider(provider) ? 'block' : 'none';
                }

                // Show API key input for cloud providers
                if (openaiApiKeyContainer) {
                    openaiApiKeyContainer.style.display = provider === 'OPENAI' ? 'block' : 'none';
                }
                if (anthropicApiKeyContainer) {
                    anthropicApiKeyContainer.style.display = provider === 'ANTHROPIC' ? 'block' : 'none';
                }
                if (googleApiKeyContainer) {
                    googleApiKeyContainer.style.display = provider === 'GOOGLE' ? 'block' : 'none';
                }
                if (openrouterApiKeyContainer) {
                    openrouterApiKeyContainer.style.display = provider === 'OPENROUTER' ? 'block' : 'none';
                }
                if (xaiApiKeyContainer) {
                    xaiApiKeyContainer.style.display = provider === 'XAI' ? 'block' : 'none';
                }
                if (ionosApiKeyContainer) {
                    ionosApiKeyContainer.style.display = provider === 'IONOS' ? 'block' : 'none';
                }
                if (openaiEndpointApiKeyContainer) {
                    openaiEndpointApiKeyContainer.style.display = provider === 'OPENAI_ENDPOINT' ? 'block' : 'none';
                }
                if (anthropicEndpointApiKeyContainer) {
                    anthropicEndpointApiKeyContainer.style.display = provider === 'ANTHROPIC_ENDPOINT' ? 'block' : 'none';
                }
                if (ollamaApiKeyContainer) {
                    ollamaApiKeyContainer.style.display = provider === 'OLLAMA' ? 'block' : 'none';
                }
                if (lmstudioApiKeyContainer) {
                    lmstudioApiKeyContainer.style.display = provider === 'LMSTUDIO' ? 'block' : 'none';
                }

                // Update model options based on provider
                // Don't reset model selection - preserve it if valid for new provider
                updateModelOptionsForProvider(provider, false);

                // Save provider change to database
                saveProviderSetting(provider);

                // Also update any settings form with the same provider
                const settingsProviderInputs = document.querySelectorAll('input[data-key="llm.provider"]');
                settingsProviderInputs.forEach(input => {
                    if (input !== modelProviderSelect) {
                        input.value = provider;
                        const hiddenInput = document.getElementById('llm.provider_hidden');
                        if (hiddenInput) {
                            hiddenInput.value = provider;
                            // Trigger change event
                            const event = new Event('change', { bubbles: true });
                            hiddenInput.dispatchEvent(event);
                        }
                    }
                });
            });
        }

        // Search engine change - save to settings manager
        // Note: Listen to the hidden input to get the value (config key) not the label
        const searchEngineHiddenInput = document.getElementById('search_engine_hidden');
        if (searchEngineHiddenInput) {
            searchEngineHiddenInput.addEventListener('change', function() {
                const searchEngine = this.value;
                SafeLogger.log('Search engine changed to:', searchEngine);
                saveSearchSetting('search.tool', searchEngine);
            });
        }

        // Iterations change - save to settings manager
        const iterationsInput = document.getElementById('iterations');
        if (iterationsInput) {
            iterationsInput.addEventListener('change', function() {
                const iterations = parseInt(this.value, 10);
                SafeLogger.log('Iterations changed to:', iterations);
                saveSearchSetting('search.iterations', iterations);
            });
        }

        // Questions per iteration change - save to settings manager
        const questionsInput = document.getElementById('questions_per_iteration');
        if (questionsInput) {
            questionsInput.addEventListener('change', function() {
                const questions = parseInt(this.value, 10);
                SafeLogger.log('Questions per iteration changed to:', questions);
                saveSearchSetting('search.questions_per_iteration', questions);
            });
        }

        // Privacy & Egress controls — persist to settings DB on change so
        // the picked scope/local-inference toggles survive the next page load
        // and the egress-policy warning banner refreshes immediately.
        const policyScopeSelect = document.getElementById('policy_egress_scope');
        if (policyScopeSelect) {
            policyScopeSelect.addEventListener('change', function() {
                saveSearchSetting('policy.egress_scope', this.value);
                applyPrivacyPanelScope(this.value);
            });
            // Apply the initial cue on page load (the data-scope attribute is
            // already set server-side from settings; this just keeps the icon
            // in sync without requiring a roundtrip).
            applyPrivacyPanelScope(policyScopeSelect.value);
        }
        const llmRequireLocalInput = document.getElementById('llm_require_local_endpoint');
        if (llmRequireLocalInput) {
            llmRequireLocalInput.addEventListener('change', function() {
                saveSearchSetting('llm.require_local_endpoint', this.checked);
            });
        }
        const embRequireLocalInput = document.getElementById('embeddings_require_local');
        if (embRequireLocalInput) {
            embRequireLocalInput.addEventListener('change', function() {
                saveSearchSetting('embeddings.require_local', this.checked);
            });
        }

        // LM Studio URL change - save to settings manager
        if (lmstudioUrlInput) {
            lmstudioUrlInput.addEventListener('change', function() {
                const url = this.value;
                saveSearchSetting('llm.lmstudio.url', url);
            });
        }

        // Context window size change - save to settings manager
        if (contextWindowInput) {
            contextWindowInput.addEventListener('change', function() {
                const size = parseInt(this.value, 10);
                saveSearchSetting('llm.local_context_window_size', size);
            });
        }

        // Ollama URL change - save to settings manager
        if (ollamaUrlInput) {
            ollamaUrlInput.addEventListener('change', function() {
                const url = this.value;
                SafeLogger.log('Ollama URL changed to:', url);
                saveSearchSetting('llm.ollama.url', url);
            });
        }

        // API Key change handlers - save to settings manager
        if (openaiApiKeyInput) {
            openaiApiKeyInput.addEventListener('change', function() {
                saveSearchSetting('llm.openai.api_key', this.value);
            });
        }
        if (anthropicApiKeyInput) {
            anthropicApiKeyInput.addEventListener('change', function() {
                saveSearchSetting('llm.anthropic.api_key', this.value);
            });
        }
        if (googleApiKeyInput) {
            googleApiKeyInput.addEventListener('change', function() {
                saveSearchSetting('llm.google.api_key', this.value);
            });
        }
        if (openrouterApiKeyInput) {
            openrouterApiKeyInput.addEventListener('change', function() {
                saveSearchSetting('llm.openrouter.api_key', this.value);
            });
        }
        if (xaiApiKeyInput) {
            xaiApiKeyInput.addEventListener('change', function() {
                saveSearchSetting('llm.xai.api_key', this.value);
            });
        }
        if (ionosApiKeyInput) {
            ionosApiKeyInput.addEventListener('change', function() {
                saveSearchSetting('llm.ionos.api_key', this.value);
            });
        }
        if (openaiEndpointApiKeyInput) {
            openaiEndpointApiKeyInput.addEventListener('change', function() {
                saveSearchSetting('llm.openai_endpoint.api_key', this.value);
            });
        }
        if (anthropicEndpointUrlInput) {
            anthropicEndpointUrlInput.addEventListener('change', function() {
                const url = this.value;
                SafeLogger.log('Anthropic endpoint URL changed to:', url);
                saveSearchSetting('llm.anthropic_endpoint.url', url);
            });
        }
        if (anthropicEndpointApiKeyInput) {
            anthropicEndpointApiKeyInput.addEventListener('change', function() {
                saveSearchSetting('llm.anthropic_endpoint.api_key', this.value);
            });
        }
        if (ollamaApiKeyInput) {
            ollamaApiKeyInput.addEventListener('change', function() {
                saveSearchSetting('llm.ollama.api_key', this.value);
            });
        }
        if (lmstudioApiKeyInput) {
            lmstudioApiKeyInput.addEventListener('change', function() {
                saveSearchSetting('llm.lmstudio.api_key', this.value);
            });
        }

        // Load options data from APIs
        Promise.all([
            loadModelOptions(false),
            loadSearchEngineOptions(false)
        ]).then(() => {
            // After loading data, initialize dropdowns
            const currentProvider = modelProviderSelect ? modelProviderSelect.value : 'OLLAMA';
            updateModelOptionsForProvider(currentProvider, false);
        }).catch(error => {
            SafeLogger.error('Failed to load options:', error);
            if (window.ui && window.ui.showAlert) {
                window.ui.showAlert('Failed to load model options. Please check your connection and try again.', 'error');
            }
        });
    }

    /**
     * Show or hide warning about custom model entries
     * @param {boolean} show - Whether to show the warning
     */
    function showCustomModelWarning(show) {
        let warningEl = document.getElementById('custom-model-warning');

        if (!warningEl && show) {
            warningEl = document.createElement('div');
            warningEl.id = 'custom-model-warning';
            warningEl.className = 'ldr-model-warning';
            warningEl.textContent = 'Custom model name entered. Make sure it exists in your provider.';
            const parent = modelDropdown.closest('.form-group');
            if (parent) {
                parent.appendChild(warningEl);
            }
        }

        if (warningEl) {
            warningEl.style.display = show ? 'block' : 'none';
        }
    }

    /**
     * Populate model provider dropdown
     */
    function populateModelProviders() {
        if (!modelProviderSelect) return;

        // Don't populate if we don't have providers yet
        if (MODEL_PROVIDERS.length === 0) {
            SafeLogger.log('No providers loaded yet, skipping populate');
            return;
        }

        // Store current value before clearing
        const currentValue = modelProviderSelect.value;

        // Clear existing options
        modelProviderSelect.innerHTML = '';

        // Add options
        MODEL_PROVIDERS.forEach(provider => {
            const option = document.createElement('option');
            option.value = provider.value;
            option.textContent = provider.label;
            modelProviderSelect.appendChild(option);
        });

        // Restore previous value if it exists in new options, otherwise use initial value
        const initialProvider = modelProviderSelect.getAttribute('data-initial-value') || 'OLLAMA';
        if (currentValue && Array.from(modelProviderSelect.options).some(opt => opt.value === currentValue)) {
            modelProviderSelect.value = currentValue;
        } else {
            SafeLogger.log('Initial provider from data attribute:', initialProvider);
            modelProviderSelect.value = initialProvider.toUpperCase();
        }

        // Show custom endpoint input if OpenAI endpoint is selected
        if (endpointContainer) {
            const selectedProvider = modelProviderSelect.value || initialProvider.toUpperCase();
            SafeLogger.log('Setting endpoint container display for provider:', selectedProvider);
            endpointContainer.style.display = selectedProvider === 'OPENAI_ENDPOINT' ? 'block' : 'none';
        } else {
            SafeLogger.warn('Endpoint container not found');
        }

        // Show Anthropic endpoint input if Anthropic endpoint is selected
        if (anthropicEndpointContainer) {
            const selectedProvider = modelProviderSelect.value || initialProvider.toUpperCase();
            anthropicEndpointContainer.style.display = selectedProvider === 'ANTHROPIC_ENDPOINT' ? 'block' : 'none';
        }

        // Show Ollama URL input if Ollama is selected
        if (ollamaUrlContainer) {
            const selectedProvider = modelProviderSelect.value || initialProvider.toUpperCase();
            ollamaUrlContainer.style.display = selectedProvider === 'OLLAMA' ? 'block' : 'none';
        }

        // Show LM Studio URL input if LMSTUDIO is selected
        if (lmstudioUrlContainer) {
            const selectedProvider = modelProviderSelect.value || initialProvider.toUpperCase();
            lmstudioUrlContainer.style.display = selectedProvider === 'LMSTUDIO' ? 'block' : 'none';
        }

        // Show context window for local providers
        if (contextWindowContainer) {
            const selectedProvider = modelProviderSelect.value || initialProvider.toUpperCase();
            contextWindowContainer.style.display = isLocalProvider(selectedProvider) ? 'block' : 'none';
        }

        // Show API key containers based on initial provider
        const selectedProvider = modelProviderSelect.value || initialProvider.toUpperCase();
        if (openaiApiKeyContainer) {
            openaiApiKeyContainer.style.display = selectedProvider === 'OPENAI' ? 'block' : 'none';
        }
        if (anthropicApiKeyContainer) {
            anthropicApiKeyContainer.style.display = selectedProvider === 'ANTHROPIC' ? 'block' : 'none';
        }
        if (googleApiKeyContainer) {
            googleApiKeyContainer.style.display = selectedProvider === 'GOOGLE' ? 'block' : 'none';
        }
        if (openrouterApiKeyContainer) {
            openrouterApiKeyContainer.style.display = selectedProvider === 'OPENROUTER' ? 'block' : 'none';
        }
        if (xaiApiKeyContainer) {
            xaiApiKeyContainer.style.display = selectedProvider === 'XAI' ? 'block' : 'none';
        }
        if (ionosApiKeyContainer) {
            ionosApiKeyContainer.style.display = selectedProvider === 'IONOS' ? 'block' : 'none';
        }
        if (openaiEndpointApiKeyContainer) {
            openaiEndpointApiKeyContainer.style.display = selectedProvider === 'OPENAI_ENDPOINT' ? 'block' : 'none';
        }
        if (anthropicEndpointApiKeyContainer) {
            anthropicEndpointApiKeyContainer.style.display = selectedProvider === 'ANTHROPIC_ENDPOINT' ? 'block' : 'none';
        }
        if (ollamaApiKeyContainer) {
            ollamaApiKeyContainer.style.display = selectedProvider === 'OLLAMA' ? 'block' : 'none';
        }
        if (lmstudioApiKeyContainer) {
            lmstudioApiKeyContainer.style.display = selectedProvider === 'LMSTUDIO' ? 'block' : 'none';
        }

        // Initial update of model options
        const providerToUpdate = modelProviderSelect.value || initialProvider.toUpperCase();
        updateModelOptionsForProvider(providerToUpdate);
    }

    /**
     * Update model options based on selected provider
     * @param {string} provider - The selected provider
     * @param {boolean} resetSelectedModel - Whether to reset the selected model
     * @returns {Promise} - A promise that resolves when the model options are updated
     */
    function updateModelOptionsForProvider(provider, resetSelectedModel = false) {
        return new Promise((resolve) => {
            // Convert provider to uppercase for consistent comparison
            const providerUpper = provider.toUpperCase();
            SafeLogger.log('Filtering models for provider:', providerUpper, 'resetSelectedModel:', resetSelectedModel);

        // If models aren't loaded yet, return early - they'll be loaded when available
        const allModels = getCachedData(CACHE_KEYS.MODELS);
        if (!allModels || !Array.isArray(allModels)) {
            SafeLogger.log('No model data loaded yet, will populate when available');
            // Load models then try again
            loadModelOptions(false).then(() => {
                    updateModelOptionsForProvider(provider, resetSelectedModel)
                        .then(resolve)
                        .catch(() => resolve([]));
                }).catch(() => resolve([]));
            return;
        }

            SafeLogger.log('Filtering models for provider:', providerUpper, 'from', allModels.length, 'models');

            // Filter models based on provider
            // Simple filtering: only show models from the selected provider
            const models = allModels.filter(model => {
                if (!model || typeof model !== 'object') return false;
                // Skip provider options (they have value but no id)
                if (model.value && !model.id && !model.name) return false;
                const modelProvider = (model.provider || '').toUpperCase();
                return modelProvider === providerUpper;
            });

            SafeLogger.log('Filtered models for provider', provider, ':', models.length, 'models');

        // Format models for dropdown
        modelOptions = models.map(model => {
                const label = model.name || model.label || model.id || model.value || 'Unknown model';
                const value = model.id || model.value || '';
            return { value, label, provider: model.provider };
        });

            SafeLogger.log(`Updated model options for provider ${provider}: ${modelOptions.length} models`);

        // Check for stored last model before deciding what to select
            let lastSelectedModel = null; // Don't use localStorage

            // Also check the database setting
            fetch(URLS.SETTINGS_API.LLM_MODEL, {
                method: 'GET',
                headers: {
                    'Content-Type': 'application/json'
                }
            })
            .then(response => response.json())
            .then(data => {
                if (data && data.setting && data.setting.value) {
                    const dbModelValue = data.setting.value;
                    SafeLogger.log('Found model in database:', dbModelValue);

                    // Use the database value if it exists and matches the current provider
                    const dbModelMatch = modelOptions.find(model => model.value === dbModelValue);

                    if (dbModelMatch) {
                        SafeLogger.log('Found matching model in filtered options:', dbModelMatch);
                        lastSelectedModel = dbModelValue;
                    }
                }

                // Continue with model selection
                selectModelBasedOnProvider(resetSelectedModel, lastSelectedModel);
                resolve(modelOptions);
            })
            .catch(error => {
                SafeLogger.error('Error fetching model from database:', error.message || error);
                // Continue with model selection using localStorage
                selectModelBasedOnProvider(resetSelectedModel, lastSelectedModel);
                resolve(modelOptions);
            });
        });
    }

    /**
     * Select a model based on the current provider and saved preferences
     * @param {boolean} resetSelectedModel - Whether to reset the selected model
     * @param {string} lastSelectedModel - The last selected model from localStorage or database
     */
    function selectModelBasedOnProvider(resetSelectedModel, lastSelectedModel) {
        if (modelInput && modelInput.disabled) {
            // Don't change the model automatically if we've disabled model
            // selection. Then the user won't be able to change it back.
            return;
        }

        if (resetSelectedModel) {
            if (modelInput) {
                // Try to select last used model first if it's available
                if (lastSelectedModel) {
                    const matchingModel = modelOptions.find(model => model.value === lastSelectedModel);
                    if (matchingModel) {
                        modelInput.value = matchingModel.label;
                        selectedModelValue = matchingModel.value;
                        SafeLogger.log('Selected previously used model:', selectedModelValue);

                        // Update any hidden input if it exists
                        const hiddenInput = document.getElementById('model_hidden');
                        if (hiddenInput) {
                            hiddenInput.value = selectedModelValue;
                        }

                        // Only save to settings if we're not initializing
                        if (!isInitializing) {
                            saveModelSettings(selectedModelValue);
                        }
                        return;
                    }
                }

                // If no matching model, clear and select first available
                modelInput.value = '';
                selectedModelValue = '';
            }
        }

        // Select model from database if available
        if ((!selectedModelValue || selectedModelValue === '') && modelOptions.length > 0 && modelInput) {
            // Try to find last used model from database
            if (lastSelectedModel) {
                const matchingModel = modelOptions.find(model => model.value === lastSelectedModel);
                if (matchingModel) {
                    modelInput.value = matchingModel.label;
                    selectedModelValue = matchingModel.value;
                    SafeLogger.log('Selected previously used model:', selectedModelValue);

                    // Update any hidden input if it exists
                    const hiddenInput = document.getElementById('model_hidden');
                    if (hiddenInput) {
                        hiddenInput.value = selectedModelValue;
                    }

                    // Only save to settings if we're not initializing
                    if (!isInitializing) {
                        saveModelSettings(selectedModelValue);
                    }
                    return;
                }
            }

            // Don't auto-select first model - wait for database settings to load
            // or let user manually select a model
            SafeLogger.log('No saved model found, waiting for user selection');
        }
    }

    /**
     * Check if Ollama is running and available
     * @returns {Promise<boolean>} True if Ollama is running
     */
    async function isOllamaRunning() {
        try {
            // Use the API endpoint with proper timeout handling
            const controller = new AbortController();
            const timeoutId = setTimeout(() => controller.abort(), 5000); // 5 second timeout

            const response = await fetch(URLS.SETTINGS_API.OLLAMA_STATUS, {
                signal: controller.signal
            });

            clearTimeout(timeoutId);

            if (response.ok) {
                const data = await response.json();
                return data.running === true;
            }
            return false;
            } catch (error) {
            SafeLogger.error('Ollama check failed:', error.name === 'AbortError' ? 'Request timed out' : error);
            return false;
        }
    }

    /**
     * Get the currently selected model value
     * @returns {string} The selected model value
     */
    function getSelectedModel() {
        SafeLogger.log('Getting selected model...');
        SafeLogger.log('- selectedModelValue:', selectedModelValue);
        SafeLogger.log('- modelInput value:', modelInput ? modelInput.value : 'modelInput not found');
        SafeLogger.log('- modelInput exists:', !!modelInput);

        // First try the stored selected value from dropdown
        if (selectedModelValue) {
            SafeLogger.log('Using selectedModelValue:', selectedModelValue);
            return selectedModelValue;
        }

        // Then try the input field value
        if (modelInput && modelInput.value.trim()) {
            SafeLogger.log('Using modelInput value:', modelInput.value.trim());
            return modelInput.value.trim();
        }

        // Finally, check if there's a hidden input with the model value
        const hiddenModelInput = document.getElementById('model_hidden');
        if (hiddenModelInput && hiddenModelInput.value) {
            SafeLogger.log('Using hidden input value:', hiddenModelInput.value);
            return hiddenModelInput.value;
        }

        SafeLogger.log('No model value found, returning empty string');
        return "";
    }

    /**
     * Check if Ollama is running and the selected model is available
     * @returns {Promise<{success: boolean, error: string, solution: string}>} Result of the check
     */
    async function checkOllamaModel() {
        const isRunning = await isOllamaRunning();

        if (!isRunning) {
            return {
                success: false,
                error: "Ollama service is not running.",
                solution: "Please start Ollama and try again. If you've recently updated, you may need to run database migration with 'python -m src.local_deep_research.migrate_db'."
            };
        }

        // Get the currently selected model
        const model = getSelectedModel();

        if (!model) {
            return {
                success: false,
                error: "No model selected.",
                solution: "Please select or enter a valid model name."
            };
        }

        // Check if the model is available in Ollama
        try {
            const controller = new AbortController();
            const timeoutId = setTimeout(() => controller.abort(), 5000);

            const response = await fetch(`/api/check/ollama_model?model=${encodeURIComponent(model)}`, {
                signal: controller.signal
            });

            clearTimeout(timeoutId);

            if (!response.ok) {
                return {
                    success: false,
                    error: "Error checking model availability.",
                    solution: "Please check your Ollama installation and try again."
                };
            }

            const data = await response.json();

            if (data.available) {
                return {
                    success: true
                };
            }
            return {
                    success: false,
                    error: data.message || "The selected model is not available in Ollama.",
                    solution: "Please pull the model first using 'ollama pull " + model + "' or select a different model."
                };

        } catch (error) {
            SafeLogger.error("Error checking Ollama model:", error);
            return {
                success: false,
                error: "Error checking model availability: " + error.message,
                solution: "Please check your Ollama installation and try again."
            };
        }
    }

    // Load settings from the database
    function loadSettings() {
        SafeLogger.log('Loading settings from database...');
        let numApiCallsPending = 1;

        // Increase the API calls counter to include strategy loading
        numApiCallsPending = 3;

        // Fetch the current settings from the settings API
        fetch(URLS.SETTINGS_API.BASE, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json'
            }
        })
        .then(response => {
            if (!response.ok) {
                throw new Error(`API error: ${response.status}`);
            }
            return response.json();
        })
        .then(data => {
            SafeLogger.log('Loaded settings from database:', data);

            // If we have a settings object in the response
            if (data && data.settings) {
                // Find the provider and model settings
                const providerSetting = data.settings["llm.provider"];
                const modelSetting = data.settings["llm.model"];
                const customEndpointUrlSetting = data.settings["llm.openai_endpoint.url"];
                const anthropicEndpointUrlSetting = data.settings["llm.anthropic_endpoint.url"];

                // Update provider dropdown if we have a valid provider
                if (providerSetting && modelProviderSelect) {
                    const providerValue = providerSetting.value.toUpperCase();
                    SafeLogger.log('Setting provider to:', providerValue);

                    // Find the matching option in the dropdown
                    const matchingOption = Array.from(modelProviderSelect.options).find(
                        option => option.value.toUpperCase() === providerValue
                    );

                    if (matchingOption) {
                        SafeLogger.log('Found matching provider option:', matchingOption.value);
                        modelProviderSelect.value = matchingOption.value;
                        // Also save to localStorage
                        // Provider saved to DB: matchingOption.value);
                    } else {
                        // If no match, try to find case-insensitive or partial match
                        const caseInsensitiveMatch = Array.from(modelProviderSelect.options).find(
                            option => option.value.toUpperCase().includes(providerValue) ||
                                      providerValue.includes(option.value.toUpperCase())
                        );

                        if (caseInsensitiveMatch) {
                            SafeLogger.log('Found case-insensitive provider match:', caseInsensitiveMatch.value);
                            modelProviderSelect.value = caseInsensitiveMatch.value;
                            // Also save to localStorage
                            // Provider saved to DB: caseInsensitiveMatch.value);
                        } else {
                            SafeLogger.warn(`No matching provider option found for '${providerValue}'`);
                        }
                    }
                    modelProviderSelect.disabled = !providerSetting.editable;

                    // Display endpoint container if using custom endpoint
                    if (endpointContainer) {
                        endpointContainer.style.display =
                            providerValue === 'OPENAI_ENDPOINT' ? 'block' : 'none';
                    }

                    // Display Anthropic endpoint container if using Anthropic endpoint
                    if (anthropicEndpointContainer) {
                        anthropicEndpointContainer.style.display =
                            providerValue === 'ANTHROPIC_ENDPOINT' ? 'block' : 'none';
                    }

                    // Display Ollama URL container if using Ollama
                    if (ollamaUrlContainer) {
                        ollamaUrlContainer.style.display =
                            providerValue === 'OLLAMA' ? 'block' : 'none';
                    }

                    // Display LM Studio URL container if using LMSTUDIO
                    if (lmstudioUrlContainer) {
                        lmstudioUrlContainer.style.display =
                            providerValue === 'LMSTUDIO' ? 'block' : 'none';
                    }

                    // Display context window container for local providers
                    if (contextWindowContainer) {
                        contextWindowContainer.style.display = isLocalProvider(providerValue) ? 'block' : 'none';
                    }

                    // Display API key containers based on provider
                    if (openaiApiKeyContainer) {
                        openaiApiKeyContainer.style.display = providerValue === 'OPENAI' ? 'block' : 'none';
                    }
                    if (anthropicApiKeyContainer) {
                        anthropicApiKeyContainer.style.display = providerValue === 'ANTHROPIC' ? 'block' : 'none';
                    }
                    if (googleApiKeyContainer) {
                        googleApiKeyContainer.style.display = providerValue === 'GOOGLE' ? 'block' : 'none';
                    }
                    if (openrouterApiKeyContainer) {
                        openrouterApiKeyContainer.style.display = providerValue === 'OPENROUTER' ? 'block' : 'none';
                    }
                    if (xaiApiKeyContainer) {
                        xaiApiKeyContainer.style.display = providerValue === 'XAI' ? 'block' : 'none';
                    }
                    if (ionosApiKeyContainer) {
                        ionosApiKeyContainer.style.display = providerValue === 'IONOS' ? 'block' : 'none';
                    }
                    if (openaiEndpointApiKeyContainer) {
                        openaiEndpointApiKeyContainer.style.display = providerValue === 'OPENAI_ENDPOINT' ? 'block' : 'none';
                    }
                    if (anthropicEndpointApiKeyContainer) {
                        anthropicEndpointApiKeyContainer.style.display = providerValue === 'ANTHROPIC_ENDPOINT' ? 'block' : 'none';
                    }
                    if (ollamaApiKeyContainer) {
                        ollamaApiKeyContainer.style.display = providerValue === 'OLLAMA' ? 'block' : 'none';
                    }
                    if (lmstudioApiKeyContainer) {
                        lmstudioApiKeyContainer.style.display = providerValue === 'LMSTUDIO' ? 'block' : 'none';
                    }
                }

                // Update the custom endpoint URl if we have one.
                if (customEndpointUrlSetting && customEndpointInput) {
                    const customEndpointUrlValue = customEndpointUrlSetting.value;
                    SafeLogger.log('Current endpoint URL:', customEndpointUrlValue);
                    customEndpointInput.value = customEndpointUrlValue;
                    customEndpointInput.disabled = !customEndpointUrlSetting.editable;
                }

                // Update the Anthropic endpoint URL if we have one.
                if (anthropicEndpointUrlSetting && anthropicEndpointUrlInput) {
                    const anthropicEndpointUrlValue = anthropicEndpointUrlSetting.value;
                    SafeLogger.log('Current Anthropic endpoint URL:', anthropicEndpointUrlValue);
                    anthropicEndpointUrlInput.value = anthropicEndpointUrlValue;
                    anthropicEndpointUrlInput.disabled = !anthropicEndpointUrlSetting.editable;
                }

                // Update the Ollama URL if we have one
                const ollamaUrlSetting = data.settings['llm.ollama.url'];
                if (ollamaUrlSetting && ollamaUrlInput) {
                    const ollamaUrlValue = ollamaUrlSetting.value;
                    SafeLogger.log('Current Ollama URL:', ollamaUrlValue);
                    ollamaUrlInput.value = ollamaUrlValue;
                    ollamaUrlInput.disabled = !ollamaUrlSetting.editable;
                }

                // Update the LM Studio URL if we have one
                const lmstudioUrlSetting = data.settings['llm.lmstudio.url'];
                if (lmstudioUrlSetting && lmstudioUrlInput) {
                    const lmstudioUrlValue = lmstudioUrlSetting.value;
                    lmstudioUrlInput.value = lmstudioUrlValue;
                    lmstudioUrlInput.disabled = !lmstudioUrlSetting.editable;
                }

                // Update the context window size if we have one
                const contextWindowSetting = data.settings['llm.local_context_window_size'];
                if (contextWindowSetting && contextWindowInput) {
                    const contextWindowValue = contextWindowSetting.value;
                    contextWindowInput.value = contextWindowValue;
                    contextWindowInput.disabled = !contextWindowSetting.editable;
                }

                // Update API key inputs from settings
                const openaiApiKeySetting = data.settings['llm.openai.api_key'];
                if (openaiApiKeySetting && openaiApiKeyInput) {
                    openaiApiKeyInput.value = openaiApiKeySetting.value || '';
                    openaiApiKeyInput.disabled = !openaiApiKeySetting.editable;
                }

                const anthropicApiKeySetting = data.settings['llm.anthropic.api_key'];
                if (anthropicApiKeySetting && anthropicApiKeyInput) {
                    anthropicApiKeyInput.value = anthropicApiKeySetting.value || '';
                    anthropicApiKeyInput.disabled = !anthropicApiKeySetting.editable;
                }

                const googleApiKeySetting = data.settings['llm.google.api_key'];
                if (googleApiKeySetting && googleApiKeyInput) {
                    googleApiKeyInput.value = googleApiKeySetting.value || '';
                    googleApiKeyInput.disabled = !googleApiKeySetting.editable;
                }

                const openrouterApiKeySetting = data.settings['llm.openrouter.api_key'];
                if (openrouterApiKeySetting && openrouterApiKeyInput) {
                    openrouterApiKeyInput.value = openrouterApiKeySetting.value || '';
                    openrouterApiKeyInput.disabled = !openrouterApiKeySetting.editable;
                }

                const xaiApiKeySetting = data.settings['llm.xai.api_key'];
                if (xaiApiKeySetting && xaiApiKeyInput) {
                    xaiApiKeyInput.value = xaiApiKeySetting.value || '';
                    xaiApiKeyInput.disabled = !xaiApiKeySetting.editable;
                }

                const ionosApiKeySetting = data.settings['llm.ionos.api_key'];
                if (ionosApiKeySetting && ionosApiKeyInput) {
                    ionosApiKeyInput.value = ionosApiKeySetting.value || '';
                    ionosApiKeyInput.disabled = !ionosApiKeySetting.editable;
                }

                const openaiEndpointApiKeySetting = data.settings['llm.openai_endpoint.api_key'];
                if (openaiEndpointApiKeySetting && openaiEndpointApiKeyInput) {
                    openaiEndpointApiKeyInput.value = openaiEndpointApiKeySetting.value || '';
                    openaiEndpointApiKeyInput.disabled = !openaiEndpointApiKeySetting.editable;
                }

                const anthropicEndpointApiKeySetting = data.settings['llm.anthropic_endpoint.api_key'];
                if (anthropicEndpointApiKeySetting && anthropicEndpointApiKeyInput) {
                    anthropicEndpointApiKeyInput.value = anthropicEndpointApiKeySetting.value || '';
                    anthropicEndpointApiKeyInput.disabled = !anthropicEndpointApiKeySetting.editable;
                }

                const ollamaApiKeySetting = data.settings['llm.ollama.api_key'];
                if (ollamaApiKeySetting && ollamaApiKeyInput) {
                    ollamaApiKeyInput.value = ollamaApiKeySetting.value || '';
                    ollamaApiKeyInput.disabled = !ollamaApiKeySetting.editable;
                }

                const lmstudioApiKeySetting = data.settings['llm.lmstudio.api_key'];
                if (lmstudioApiKeySetting && lmstudioApiKeyInput) {
                    lmstudioApiKeyInput.value = lmstudioApiKeySetting.value || '';
                    lmstudioApiKeyInput.disabled = !lmstudioApiKeySetting.editable;
                }

                // Load model options based on the current provider
                const currentProvider = modelProviderSelect ? modelProviderSelect.value : 'OLLAMA';
                updateModelOptionsForProvider(currentProvider, false).then(() => {
                    // Update model selection if we have a valid model
                    if (modelSetting && modelInput) {
                        const modelValue = modelSetting.value;
                        SafeLogger.log('Setting model to:', modelValue);

                        // Save to localStorage
                        // Model saved to DB

                        // Find the model in our loaded options
                        const matchingModel = modelOptions.find(m =>
                            m.value === modelValue || m.id === modelValue
                        );

                        if (matchingModel) {
                            SafeLogger.log('Found matching model in options:', matchingModel);

                            // Set the input field value
                            modelInput.value = matchingModel.label || modelValue;
                            selectedModelValue = modelValue;

                            // Also update hidden input if it exists
                            const hiddenInput = document.getElementById('model_hidden');
                            if (hiddenInput) {
                                hiddenInput.value = modelValue;
                            }
                        } else {
                            // If no matching model found, just set the raw value
                            SafeLogger.warn(`No matching model found for '${modelValue}'`);
                            modelInput.value = modelValue;
                            selectedModelValue = modelValue;

                            // Also update hidden input if it exists
                            const hiddenInput = document.getElementById('model_hidden');
                            if (hiddenInput) {
                                hiddenInput.value = modelValue;
                            }
                        }
                        modelInput.disabled = !modelSetting.editable;
                    }
                });

                // Update search engine if we have a valid value
                const searchEngineSetting = data.settings["search.tool"];
                if (searchEngineSetting && searchEngineSetting.value && searchEngineInput) {
                    const engineValue = searchEngineSetting.value;
                    SafeLogger.log('Setting search engine to:', engineValue);

                    // Save to localStorage
                    // Search engine saved to DB

                    // Find the engine in our loaded options
                    const matchingEngine = searchEngineOptions.find(e =>
                        e.value === engineValue || e.id === engineValue
                    );

                    if (matchingEngine) {
                        SafeLogger.log('Found matching search engine in options:', matchingEngine);

                        // Set the input field value
                        searchEngineInput.value = matchingEngine.label || engineValue;
                        selectedSearchEngineValue = engineValue;

                        // Also update hidden input if it exists
                        const hiddenInput = document.getElementById('search_engine_hidden');
                        if (hiddenInput) {
                            hiddenInput.value = engineValue;
                        }
                    } else {
                        // If no matching engine found, just set the raw value
                        SafeLogger.warn(`No matching search engine found for '${engineValue}'`);
                        searchEngineInput.value = engineValue;
                        selectedSearchEngineValue = engineValue;

                        // Also update hidden input if it exists
                        const hiddenInput = document.getElementById('search_engine_hidden');
                        if (hiddenInput) {
                            hiddenInput.value = engineValue;
                        }
                    }

                    searchEngineInput.disabled = !searchEngineSetting.editable;
                }


            }

            // If all the calls to the settings API are finished, we're no
            // longer initializing.
            numApiCallsPending--;
            isInitializing = (numApiCallsPending === 0);
            SafeLogger.log('Settings loaded. isInitializing now:', isInitializing, 'pending calls:', numApiCallsPending);
            if (!isInitializing) onInitializationComplete();
        })
        .catch(error => {
            SafeLogger.error('Error loading settings:', error);

            // Fallback to localStorage if database fetch fails
            fallbackToLocalStorageSettings();

            // Even if there's an error, we're done initializing
            numApiCallsPending--;
            isInitializing = (numApiCallsPending === 0);
            SafeLogger.log('Settings load error. isInitializing now:', isInitializing, 'pending calls:', numApiCallsPending);
            if (!isInitializing) onInitializationComplete();
        });

        // Load search strategy setting
        fetch(URLS.SETTINGS_API.SEARCH_STRATEGY, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json'
            }
        })
            .then(response => {
                if (!response.ok) {
                    throw new Error(`API error: ${response.status}`);
                }
                return response.json();
            })
            .then(data => {
                SafeLogger.log('Loaded strategy from database:', data);

                const strategySelect = document.getElementById('strategy');
                if (data && data.setting && data.setting.value && strategySelect) {
                    const strategyValue = data.setting.value;
                    SafeLogger.log('Setting strategy to:', strategyValue);

                    // Update the select element
                    strategySelect.value = strategyValue;

                    // Save to localStorage
                    // Strategy saved to DB
                }

                numApiCallsPending--;
                isInitializing = (numApiCallsPending === 0);
                SafeLogger.log('Strategy loaded. isInitializing now:', isInitializing, 'pending calls:', numApiCallsPending);
                if (!isInitializing) onInitializationComplete();
            })
            .catch(error => {
                SafeLogger.error('Error loading strategy:', error.message || error);

                // Fallback to localStorage
                const lastStrategy = null; // Strategy loaded from DB
                const strategySelect = document.getElementById('strategy');
                if (lastStrategy && strategySelect) {
                    strategySelect.value = lastStrategy;
                }

                numApiCallsPending--;
                isInitializing = (numApiCallsPending === 0);
                SafeLogger.log('Strategy load error. isInitializing now:', isInitializing, 'pending calls:', numApiCallsPending);
                if (!isInitializing) onInitializationComplete();
            });
    }

    // Add a fallback function to use localStorage settings
    function fallbackToLocalStorageSettings() {
        // Settings are loaded from database, not localStorage
        const provider = null;
        const model = null;
        const searchEngine = null;

        SafeLogger.log('Falling back to localStorage settings:', { provider, model, searchEngine });

        if (provider && modelProviderSelect) {
            modelProviderSelect.value = provider;
            // Show/hide custom endpoint input if needed
            if (endpointContainer) {
                endpointContainer.style.display =
                    provider === 'OPENAI_ENDPOINT' ? 'block' : 'none';
            }
            // Show/hide Anthropic endpoint input if needed
            if (anthropicEndpointContainer) {
                anthropicEndpointContainer.style.display =
                    provider === 'ANTHROPIC_ENDPOINT' ? 'block' : 'none';
            }
            // Show/hide Ollama URL input if needed
            if (ollamaUrlContainer) {
                ollamaUrlContainer.style.display =
                    provider === 'OLLAMA' ? 'block' : 'none';
            }
            // Show/hide LM Studio URL input if needed
            if (lmstudioUrlContainer) {
                lmstudioUrlContainer.style.display =
                    provider === 'LMSTUDIO' ? 'block' : 'none';
            }
            // Show/hide context window for local providers
            if (contextWindowContainer) {
                contextWindowContainer.style.display = isLocalProvider(provider) ? 'block' : 'none';
            }
            // Show/hide API key containers based on provider
            if (openaiApiKeyContainer) {
                openaiApiKeyContainer.style.display = provider === 'OPENAI' ? 'block' : 'none';
            }
            if (anthropicApiKeyContainer) {
                anthropicApiKeyContainer.style.display = provider === 'ANTHROPIC' ? 'block' : 'none';
            }
            if (googleApiKeyContainer) {
                googleApiKeyContainer.style.display = provider === 'GOOGLE' ? 'block' : 'none';
            }
            if (openrouterApiKeyContainer) {
                openrouterApiKeyContainer.style.display = provider === 'OPENROUTER' ? 'block' : 'none';
            }
            if (xaiApiKeyContainer) {
                xaiApiKeyContainer.style.display = provider === 'XAI' ? 'block' : 'none';
            }
            if (ionosApiKeyContainer) {
                ionosApiKeyContainer.style.display = provider === 'IONOS' ? 'block' : 'none';
            }
            if (openaiEndpointApiKeyContainer) {
                openaiEndpointApiKeyContainer.style.display = provider === 'OPENAI_ENDPOINT' ? 'block' : 'none';
            }
            if (anthropicEndpointApiKeyContainer) {
                anthropicEndpointApiKeyContainer.style.display = provider === 'ANTHROPIC_ENDPOINT' ? 'block' : 'none';
            }
            if (ollamaApiKeyContainer) {
                ollamaApiKeyContainer.style.display = provider === 'OLLAMA' ? 'block' : 'none';
            }
        }

        const currentProvider = modelProviderSelect ? modelProviderSelect.value : 'OLLAMA';
        updateModelOptionsForProvider(currentProvider, !model);

        if (model && modelInput) {
            const matchingModel = modelOptions.find(m => m.value === model);
            if (matchingModel) {
                modelInput.value = matchingModel.label;
            } else {
                modelInput.value = model;
            }
            selectedModelValue = model;

            // Update hidden input if it exists
            const hiddenInput = document.getElementById('model_hidden');
            if (hiddenInput) {
                hiddenInput.value = model;
            }
        }

        if (searchEngine && searchEngineInput) {
            const matchingEngine = searchEngineOptions.find(e => e.value === searchEngine);
            if (matchingEngine) {
                searchEngineInput.value = matchingEngine.label;
            } else {
                searchEngineInput.value = searchEngine;
            }
            selectedSearchEngineValue = searchEngine;

            // Update hidden input if it exists
            const hiddenInput = document.getElementById('search_engine_hidden');
            if (hiddenInput) {
                hiddenInput.value = searchEngine;
            }
        }
    }

    /**
     * Load model options from API or cache
     */
    function loadModelOptions(forceRefresh = false) {
        return new Promise((resolve) => {
            // Check in-memory cache first if not forcing refresh (5-minute expiration)
            if (!forceRefresh) {
                const cachedData = getCachedData(CACHE_KEYS.MODELS);
                if (cachedData) {
                    SafeLogger.log('Using cached model data');
                    resolve(cachedData);
                    return;
                }
            }

            // Add loading class to parent
            if (modelInput && modelInput.parentNode) {
                modelInput.parentNode.classList.add('ldr-loading');
            }

            // Fetch from API if cache is invalid or refresh is forced
            const url = forceRefresh
                ? `${URLS.SETTINGS_API.AVAILABLE_MODELS}?force_refresh=true`
                : URLS.SETTINGS_API.AVAILABLE_MODELS;

            fetch(url)
                .then(response => {
                    if (!response.ok) {
                        throw new Error(`API error: ${response.status}`);
                    }
                    return response.json();
                })
                .then(data => {
                    // Remove loading class
                    if (modelInput && modelInput.parentNode) {
                        modelInput.parentNode.classList.remove('ldr-loading');
                    }

                    if (data && data.providers) {
                        SafeLogger.log('Got model data from API:', data);

                        // Update MODEL_PROVIDERS from API if available
                        if (data.provider_options) {
                            MODEL_PROVIDERS = data.provider_options;
                            SafeLogger.log('Updated MODEL_PROVIDERS from API:', MODEL_PROVIDERS);
                            // Re-populate the provider dropdown with new options
                            populateModelProviders();
                        }

                        // Format the data for our dropdown
                        const formattedModels = formatModelsFromAPI(data);

                        // Cache in memory (5-minute expiration to reduce database calls)
                        cacheData(CACHE_KEYS.MODELS, formattedModels);

                        resolve(formattedModels);
                    } else {
                        throw new Error('Invalid model data format');
                    }
                })
                .catch(error => {
                    SafeLogger.error('Error loading models:', error.message || error);

                    // Remove loading class on error
                    if (modelInput && modelInput.parentNode) {
                        modelInput.parentNode.classList.remove('ldr-loading');
                    }

                    // Use cached data if available, even if expired
                    const cachedData = getCachedData(CACHE_KEYS.MODELS);
                    if (cachedData) {
                        SafeLogger.log('Using expired cached model data due to API error');
                        resolve(cachedData);
                    } else {
                        // No cache and API failed - return empty array
                        SafeLogger.log('API failed and no cache available - returning empty model list');
                        resolve([]);
                    }
                });
        });
    }

    // Format models from API response
    function formatModelsFromAPI(data) {
        const formatted = [];

        // Process provider options
        if (data.provider_options) {
            data.provider_options.forEach(provider => {
                formatted.push({
                    ...provider,
                    isProvider: true // Flag to identify provider options
                });
            });
        }

        // Process all provider models dynamically
        if (data.providers) {
            // Create a new object to avoid race conditions
            const newAvailableModels = {};

            // Iterate through all providers in the response
            Object.keys(data.providers).forEach(providerKey => {
                // Extract provider name from key (e.g., 'ollama_models' -> 'OLLAMA')
                const providerName = providerKey.replace('_models', '').toUpperCase();

                // Initialize array for this provider
                if (!newAvailableModels[providerName]) {
                    newAvailableModels[providerName] = [];
                }

                // Process each model for this provider
                const models = data.providers[providerKey];
                if (Array.isArray(models)) {
                    models.forEach(model => {
                        const formattedModel = {
                            ...model,
                            id: model.value,
                            provider: model.provider || providerName
                        };
                        formatted.push(formattedModel);
                        newAvailableModels[providerName].push(formattedModel);
                    });
                }
            });

            // Atomically update the global variable
            availableModels = newAvailableModels;
            SafeLogger.log('Dynamically populated availableModels:', availableModels);
        }

        return formatted;
    }

    // In-memory cache to avoid excessive API calls within a session
    const memoryCache = {};
    const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes

    function cacheData(key, data) {
        memoryCache[key] = {
            data,
            timestamp: Date.now()
        };
    }

    function getCachedData(key) {
        const cached = memoryCache[key];
        if (cached && (Date.now() - cached.timestamp < CACHE_DURATION)) {
            return cached.data;
        }
        return null;
    }

    function invalidateCacheKey(key) {
        if (memoryCache[key]) {
            delete memoryCache[key];
            SafeLogger.log(`Cache invalidated for key: ${key}`);
        }
    }

    // Load search engine options
    function loadSearchEngineOptions(forceRefresh = false) {
        return new Promise((resolve) => {
            // Check in-memory cache first if not forcing refresh (5-minute expiration)
            if (!forceRefresh) {
                const cachedData = getCachedData(CACHE_KEYS.SEARCH_ENGINES);
                if (cachedData) {
                    SafeLogger.log('Using cached search engine data');
                    searchEngineOptions = cachedData; // Ensure the global variable is updated
                    resolve(cachedData);
                    return;
                }
            }

            // Add loading class to parent
            if (searchEngineInput && searchEngineInput.parentNode) {
                searchEngineInput.parentNode.classList.add('ldr-loading');
            }

            SafeLogger.log('Fetching search engines from API...');

            // Fetch from API
            fetch(URLS.SETTINGS_API.AVAILABLE_SEARCH_ENGINES)
                .then(response => {
                    if (!response.ok) {
                        throw new Error(`API error: ${response.status}`);
                    }
                    return response.json();
                })
                .then(data => {
                    // Remove loading class
                    if (searchEngineInput && searchEngineInput.parentNode) {
                        searchEngineInput.parentNode.classList.remove('ldr-loading');
                    }

                    // Log the entire response to debug
                    SafeLogger.log('Search engine API response:', data);

                    // Extract engines from the data based on the actual response format
                    let formattedEngines = [];

                    // Handle the case where API returns {engine_options, engines}
                    if (data && data.engine_options) {
                        SafeLogger.log('Processing engine_options:', data.engine_options.length + ' options');

                        // Map the engine options to our dropdown format. The
                        // group_* fields drive the band headers/ordering; the
                        // base_group_* fields let a favorite toggle move an
                        // engine back to its category band without re-fetching.
                        formattedEngines = data.engine_options.map(engine => ({
                            value: engine.value || engine.id || '',
                            label: engine.label || engine.name || engine.value || '',
                            type: engine.type || 'search',
                            is_favorite: engine.is_favorite || false,
                            group_label: engine.group_label,
                            group_order: engine.group_order,
                            base_group_label: engine.base_group_label,
                            base_group_order: engine.base_group_order
                        }));
                    }
                    // Also try adding engines from engines object if it exists
                    if (data && data.engines) {
                        SafeLogger.log('Processing engines object:', Object.keys(data.engines).length + ' engine types');

                        // Handle each type of engine in the engines object
                        Object.keys(data.engines).forEach(engineType => {
                            const enginesOfType = data.engines[engineType];
                            if (Array.isArray(enginesOfType)) {
                                SafeLogger.log(`Processing ${engineType} engines:`, enginesOfType.length + ' engines');

                                // Map each engine to our dropdown format
                                const typeEngines = enginesOfType.map(engine => ({
                                    value: engine.value || engine.id || '',
                                    label: engine.label || engine.name || engine.value || '',
                                    type: engineType
                                }));

                                // Add to our formatted engines array
                                formattedEngines = [...formattedEngines, ...typeEngines];
                            }
                        });
                    }
                    // Handle classic format with search_engines array
                    else if (data && data.search_engines) {
                        SafeLogger.log('Processing search_engines array:', data.search_engines.length + ' engines');
                        formattedEngines = data.search_engines.map(engine => ({
                            value: engine.id || engine.value || '',
                            label: engine.name || engine.label || '',
                            type: engine.type || 'search'
                        }));
                    }
                    // Handle direct array format
                    else if (data && Array.isArray(data)) {
                        SafeLogger.log('Processing direct array:', data.length + ' engines');
                        formattedEngines = data.map(engine => ({
                            value: engine.id || engine.value || '',
                            label: engine.name || engine.label || '',
                            type: engine.type || 'search'
                        }));
                    }

                    SafeLogger.log('Final formatted search engines:', formattedEngines);

                    if (formattedEngines.length > 0) {
                        // Cache the data
                        cacheData(CACHE_KEYS.SEARCH_ENGINES, formattedEngines);

                        // Update global searchEngineOptions
                        searchEngineOptions = formattedEngines;

                        resolve(formattedEngines);
                    } else {
                        throw new Error('No valid search engines found in API response');
                    }
                })
                .catch(error => {
                    SafeLogger.error('Error loading search engines:', error.message || error);

                    // Remove loading class on error
                    if (searchEngineInput && searchEngineInput.parentNode) {
                        searchEngineInput.parentNode.classList.remove('ldr-loading');
                    }

                    // Use cached data if available, even if expired
                    const cachedData = getCachedData(CACHE_KEYS.SEARCH_ENGINES);
                    if (cachedData) {
                        SafeLogger.log('Using expired cached search engine data due to API error');
                        searchEngineOptions = cachedData;
                        resolve(cachedData);
                    } else {
                        // No cache and API failed - return empty array
                        SafeLogger.log('API failed and no cache available - returning empty search engine list');
                        resolve([]);
                    }
                });
        });
    }

    // Save model settings to database
    function saveModelSettings(modelValue) {
        // Only save to database, not localStorage

        // Update any hidden input with the same settings key that might exist in other forms
        const hiddenInputs = document.querySelectorAll('input[id$="_hidden"][name="llm.model"]');
        hiddenInputs.forEach(input => {
            input.value = modelValue;
        });

        // Save to the database using the settings API
        fetch(URLBuilder.updateSetting('llm.model'), {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': window.api ? window.api.getCsrfToken() : ''
            },
            body: JSON.stringify({ value: modelValue })
        })
        .then(response => response.json())
        .then(data => {
            SafeLogger.log('Model setting saved to database:', data);

            // Optionally show a notification if there's UI notification support
            if (window.ui && window.ui.showMessage) {
                window.ui.showMessage(`Model updated to: ${modelValue}`, 'success', 2000);
            }
        })
        .catch(error => {
            SafeLogger.error('Error saving model setting to database:', error);

            // Show error notification if available
            if (window.ui && window.ui.showMessage) {
                window.ui.showMessage(`Error updating model: ${error.message}`, 'error', 3000);
            }
        });
    }

    // Save search engine settings to database
    function saveSearchEngineSettings(engineValue) {
        // Only save to database, not localStorage

        // Update any hidden input with the same settings key that might exist in other forms
        const hiddenInputs = document.querySelectorAll('input[id$="_hidden"][name="search.tool"]');
        hiddenInputs.forEach(input => {
            input.value = engineValue;
        });

        // Save to the database using the settings API
        fetch(URLS.SETTINGS_API.SEARCH_TOOL, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': window.api ? window.api.getCsrfToken() : ''
            },
            body: JSON.stringify({ value: engineValue })
        })
        .then(response => response.json())
        .then(data => {
            SafeLogger.log('Search engine setting saved to database:', data);

            // Optionally show a notification
            if (window.ui && window.ui.showMessage) {
                window.ui.showMessage(`Search engine updated to: ${engineValue}`, 'success', 2000);
            }
        })
        .catch(error => {
            SafeLogger.error('Error saving search engine setting to database:', error);

            // Show error notification if available
            if (window.ui && window.ui.showMessage) {
                window.ui.showMessage(`Error updating search engine: ${error.message}`, 'error', 3000);
            }
        });
    }

    // Handle toggling a search engine as favorite
    function handleSearchEngineFavoriteToggle(engineId, item, isFavorite) {
        SafeLogger.log(`Toggling favorite for ${engineId}: ${isFavorite}`);

        // Make API call to toggle favorite
        fetch(URLS.SETTINGS_API.SEARCH_FAVORITES_TOGGLE, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': window.api ? window.api.getCsrfToken() : ''
            },
            body: JSON.stringify({ engine_id: engineId })
        })
        .then(response => response.json())
        .then(data => {
            SafeLogger.log('Favorite toggled:', data);

            if (data.error) {
                SafeLogger.error('Error toggling favorite:', data.error);
                if (window.ui && window.ui.showMessage) {
                    window.ui.showMessage(`Error: ${data.error}`, 'error', 3000);
                }
                return;
            }

            // Update the local options with new favorite status. A starred
            // engine moves to the Favorites band; un-starring returns it to its
            // category band (base_group_*). Favorites is the top band, mirroring
            // engine_groups.SEARCH_ENGINE_GROUPS[0] on the server.
            const updatedFavorites = data.favorites || [];
            const FAVORITES_BAND = { label: 'Favorites', order: 0 };
            searchEngineOptions = searchEngineOptions.map(engine => {
                const isFav = updatedFavorites.includes(engine.value);
                return {
                    ...engine,
                    is_favorite: isFav,
                    group_label: isFav ? FAVORITES_BAND.label : engine.base_group_label,
                    group_order: isFav ? FAVORITES_BAND.order : engine.base_group_order
                };
            });

            // Re-sort by band order (favorites first), then alphabetically
            // within each band. group_order can be 0, so don't treat it as falsy.
            const bandOrder = (engine) => {
                return typeof engine.group_order === 'number' ? engine.group_order : 999;
            };
            searchEngineOptions.sort((a, b) =>
                (bandOrder(a) - bandOrder(b)) ||
                (a.label || '').localeCompare(b.label || '')
            );

            // Invalidate cache so next dropdown open gets fresh data
            invalidateCacheKey(CACHE_KEYS.SEARCH_ENGINES);

            // Show success message
            const action = data.is_favorite ? 'added to' : 'removed from';
            if (window.ui && window.ui.showMessage) {
                window.ui.showMessage(`Search engine ${action} favorites`, 'success', 2000);
            }
        })
        .catch(error => {
            SafeLogger.error('Error toggling search engine favorite:', error);
            if (window.ui && window.ui.showMessage) {
                window.ui.showMessage(`Error updating favorites: ${error.message}`, 'error', 3000);
            }
        });
    }

    // Save provider setting to database
    function saveProviderSetting(providerValue) {
        // Only save to database, not localStorage

        // Update any hidden input with the same settings key that might exist in other forms
        const hiddenInputs = document.querySelectorAll('input[id$="_hidden"][name="llm.provider"]');
        hiddenInputs.forEach(input => {
            input.value = providerValue;
        });

        // Save to the database using the settings API
        fetch(URLS.SETTINGS_API.LLM_PROVIDER, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': window.api ? window.api.getCsrfToken() : ''
            },
            body: JSON.stringify({ value: providerValue.toLowerCase() })
        })
        .then(response => response.json())
        .then(data => {
            SafeLogger.log('Provider setting saved to database:', data);

            // If the response includes warnings, display them directly
            if (data.warnings && typeof window.displayWarnings === 'function') {
                window.displayWarnings(data.warnings);
            } else if (typeof window.refetchSettingsAndUpdateWarnings === 'function') {
                // Fallback: trigger warning system update
                window.refetchSettingsAndUpdateWarnings();
            }

            // Optionally show a notification
            if (window.ui && window.ui.showMessage) {
                window.ui.showMessage(`Provider updated to: ${providerValue}`, 'success', 2000);
            }
        })
        .catch(error => {
            SafeLogger.error('Error saving provider setting to database:', error);

            // Show error notification if available
            if (window.ui && window.ui.showMessage) {
                window.ui.showMessage(`Error updating provider: ${error.message}`, 'error', 3000);
            }
        });
    }

    // Save search setting to database
    /**
     * Reflect the chosen egress scope visually: swap the panel's data-scope
     * (CSS handles the border/background/header color) and the header icon.
     * Icon mapping mirrors the dropdown semantics — globe = "anywhere",
     * cloud = "data going out", house = "stays home", target = "one tool only".
     */
    function applyPrivacyPanelScope(scope) {
        const normalized = scope || 'adaptive';
        const panel = document.querySelector('.ldr-privacy-panel');
        if (panel) panel.setAttribute('data-scope', normalized);
        // Also stamp the body so CSS can escalate the cue to the research card
        // and query textarea (see <style> block in research.html).
        if (document.body) document.body.dataset.scope = normalized;

        // Auto-check + lock the local-inference toggles under "Private only",
        // so the form matches what the backend actually enforces
        // (context_from_snapshot forces require_local_llm/embeddings under
        // PRIVATE_ONLY) and matches docs/egress-modes.md. Visual only — the
        // saved scope is what the backend couples; we restore the user's stored
        // preference when they leave Private only. (Mirrors applyEgressScopeLock
        // on the settings page.)
        const LOCK_TITLE = 'Forced on by the Private-only egress scope — local inference is required so data stays on this machine.';
        const scopeLocked = normalized === 'private_only';
        ['llm_require_local_endpoint', 'embeddings_require_local'].forEach((id) => {
            const cb = document.getElementById(id);
            if (!cb) return;
            if (scopeLocked) {
                // Remember the user's choice once, so we can restore it later.
                if (!cb.dataset.userCheckedSaved) {
                    cb.dataset.userChecked = cb.checked ? '1' : '0';
                    cb.dataset.userCheckedSaved = '1';
                }
                cb.checked = true;
                cb.disabled = true;
                cb.title = LOCK_TITLE;
            } else {
                if (cb.dataset.userCheckedSaved) {
                    cb.checked = cb.dataset.userChecked === '1';
                    delete cb.dataset.userChecked;
                    delete cb.dataset.userCheckedSaved;
                }
                cb.disabled = false;
                cb.title = '';
            }
        });

        const icon = document.getElementById('ldr-privacy-panel-icon');
        if (!icon) return;
        const iconClassByScope = {
            adaptive: 'fas fa-shield-alt',
            both: 'fas fa-shield-alt',
            public_only: 'fas fa-cloud',
            private_only: 'fas fa-home',
            strict: 'fas fa-bullseye',
        };
        icon.className = iconClassByScope[normalized] || iconClassByScope.adaptive;
    }

    function saveSearchSetting(settingKey, value) {
        // Save to the database using the settings API
        fetch(`/settings/api/${settingKey}`, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': window.api ? window.api.getCsrfToken() : ''
            },
            body: JSON.stringify({ value })
        })
        .then(response => response.json())
        .then(data => {
            SafeLogger.log(`Search setting ${settingKey} saved to database:`, data);

            // If the response includes warnings, display them directly
            if (data.warnings && typeof window.displayWarnings === 'function') {
                window.displayWarnings(data.warnings);
            }

            // Optionally show a notification
            if (window.ui && window.ui.showMessage) {
                window.ui.showMessage(`${settingKey.split('.').pop()} updated to: ${value}`, 'success', 2000);
            }
        })
        .catch(error => {
            SafeLogger.error(`Error saving search setting ${settingKey} to database:`, error);

            // Show error notification if available
            if (window.ui && window.ui.showMessage) {
                window.ui.showMessage(`Error updating ${settingKey}: ${error.message}`, 'error', 3000);
            }
        });
    }

    // Research form submission handler
    function handleResearchSubmit(event) {
        event.preventDefault();
        SafeLogger.log('Research form submitted');

        // Validate the query BEFORE any UI changes
        const query = queryInput.value.trim();
        if (!query) {
            if (researchValidator) {
                researchValidator.validateAll();
                queryInput.focus();
            } else {
                showAlert('Please enter a research query.', 'error');
            }
            return;
        }

        // Clear any previous validation errors
        if (researchValidator) {
            researchValidator.clearErrors();
        }

        // Disable the submit button to prevent multiple submissions
        startBtn.disabled = true;

      // Use centralized security utilities for button update
        window.safeUpdateButton(startBtn, 'fa-spinner', ' Starting...', true);

        // Show loading overlay for better feedback using centralized utility
        const loadingOverlay = window.createSafeLoadingOverlay({
            title: 'Preparing your research...',
            description: 'Securing settings and initializing search engines'
        });
        loadingOverlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.85);
            display: flex;
            align-items: center;
            justify-content: center;
            z-index: 9999;
            color: white;
        `;
        document.body.appendChild(loadingOverlay);

        // Get the selected research mode from radio button (more reliable)
        const selectedModeRadio = document.querySelector('input[name="research_mode"]:checked');
        const mode = selectedModeRadio ? selectedModeRadio.value : 'quick';

        // Handle Chat Mode - create session and redirect
        if (mode === 'chat') {
            if (!query) {
                showAlert('Please enter a research query.', 'error');
                startBtn.disabled = false;
                window.safeUpdateButton(startBtn, 'fa-rocket', ' Start Research');
                const overlay = document.querySelector('.ldr-loading-overlay');
                if (overlay) overlay.remove();
                return;
            }

            const csrfToken = window.api ? window.api.getCsrfToken() : '';
            fetch('/api/chat/sessions', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRFToken': csrfToken
                },
                body: JSON.stringify({ initial_query: query })
            })
            .then(response => {
                if (!response.ok) {
                    throw new Error('Failed to create chat session');
                }
                return response.json();
            })
            .then(data => {
                if (data.success && data.session_id) {
                    window.location.href = `/chat/${data.session_id}?q=${encodeURIComponent(query)}`;
                } else {
                    throw new Error(data.error || 'Failed to create chat session');
                }
            })
            .catch(error => {
                SafeLogger.error('Error creating chat session:', error);
                showAlert('Failed to start chat: ' + error.message, 'error');
                startBtn.disabled = false;
                window.safeUpdateButton(startBtn, 'fa-rocket', ' Start Research');
                const overlay = document.querySelector('.ldr-loading-overlay');
                if (overlay) overlay.remove();
            });
            return;
        }

        // Get values from form fields (query already read above)
        const modelProvider = modelProviderSelect ? modelProviderSelect.value : '';

        // Get values from hidden inputs for custom dropdowns
        const model = document.querySelector('#model_hidden') ?
                     document.querySelector('#model_hidden').value : '';
        const searchEngine = document.querySelector('#search_engine_hidden') ?
                           document.querySelector('#search_engine_hidden').value : '';

        // Get other form values
        const customEndpoint = customEndpointInput ? customEndpointInput.value : '';
        const ollamaUrl = ollamaUrlInput ? ollamaUrlInput.value : '';
        const enableNotifications = notificationToggle ? notificationToggle.checked : true;

        // Get strategy value
        const strategySelect = document.getElementById('strategy');
        const strategy = strategySelect ? strategySelect.value : 'source-based';

        // Get iterations and questions per iteration
        const iterationsInput = document.getElementById('iterations');
        const iterations = iterationsInput ? parseInt(iterationsInput.value, 10) : 2;
        const questionsInput = document.getElementById('questions_per_iteration');
        const questionsPerIteration = questionsInput ? parseInt(questionsInput.value, 10) : 3;

        // Egress policy form fields (per-research override, not saved
        // to settings). Mirror the model/search_engine pattern: the
        // server falls back to saved settings when these are unset.
        const policyScopeEl = document.getElementById('policy_egress_scope');
        const llmLocalEl = document.getElementById('llm_require_local_endpoint');
        const embLocalEl = document.getElementById('embeddings_require_local');
        const policyEgressScope = policyScopeEl ? policyScopeEl.value : null;
        const llmRequireLocalEndpoint = llmLocalEl ? !!llmLocalEl.checked : null;
        const embeddingsRequireLocal = embLocalEl ? !!embLocalEl.checked : null;

        // Prepare the data for submission
        const formData = {
            query,
            mode,
            model_provider: modelProvider,
            model,
            custom_endpoint: customEndpoint,
            ollama_url: ollamaUrl,
            search_engine: searchEngine,
            strategy,
            iterations,
            questions_per_iteration: questionsPerIteration
        };
        if (policyEgressScope !== null && policyEgressScope !== '') {
            formData.policy_egress_scope = policyEgressScope;
        }
        if (llmRequireLocalEndpoint !== null) {
            formData.llm_require_local_endpoint = llmRequireLocalEndpoint;
        }
        if (embeddingsRequireLocal !== null) {
            formData.embeddings_require_local = embeddingsRequireLocal;
        }

        SafeLogger.log('Submitting research with data:', formData);

        // Get CSRF token
        const csrfToken = window.api ? window.api.getCsrfToken() : '';

        // Submit the form data to the backend
        fetch(URLS.API.START_RESEARCH, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': csrfToken
            },
            body: JSON.stringify(formData)
        })
        .then(response => response.json())
        .then(data => {
            if (data.status === 'success' || data.status === window.RESEARCH_STATUS.QUEUED) {
                SafeLogger.log('Research started:', data);

                if (data.status === window.RESEARCH_STATUS.QUEUED) {
                    showAlert(data.message || 'Your research has been queued.', 'info');
                }

                // Store research preferences in localStorage
                // Settings are saved to database via the API, not localStorage

                // Redirect to the progress page
                // URLBuilder produces /progress/{uuid}
                // bearer:disable javascript_lang_open_redirect
                window.location.href = URLBuilder.progressPage(data.research_id);
            } else {
                // Show error message
                showAlert(data.message || 'Failed to start research.', 'error');

                // Re-enable the button
                startBtn.disabled = false;
                // Use centralized security utilities for button reset
                window.safeUpdateButton(startBtn, 'fa-rocket', ' Start Research');

                // Remove loading overlay
                const overlay = document.querySelector('.ldr-loading-overlay');
                if (overlay) overlay.remove();
            }
        })
        .catch(error => {
            SafeLogger.error('Error starting research:', error);

            // Show error message
            showAlert('An error occurred while starting research. Please try again.', 'error');

            // Re-enable the button
            startBtn.disabled = false;
            // Use centralized security utilities for button reset
                window.safeUpdateButton(startBtn, 'fa-rocket', ' Start Research');

            // Remove loading overlay
            const overlay = document.querySelector('.ldr-loading-overlay');
            if (overlay) overlay.remove();
        });
    }

    /**
     * Show an alert message
     * @param {string} message - The message to show
     * @param {string} type - The alert type (success, error, warning, info)
     */
    function showAlert(message, type = 'info') {
  // Use centralized security utility for alerts with auto-hide functionality
        window.showSafeAlert('research-alert', message, type);

        // Add auto-hide functionality after 5 seconds (preserving dev branch behavior)
        const alertContainer = document.getElementById('research-alert');
        if (alertContainer && alertContainer.firstChild) {
            const alert = alertContainer.firstChild;
            setTimeout(() => {
                if (alertContainer.contains(alert)) {
                    alert.remove();
                    if (alertContainer.children.length === 0) {
                        alertContainer.style.display = 'none';
                    }
                }
            }, 5000);
        }
    }

    // Initialize research component when DOM is loaded
    document.addEventListener('DOMContentLoaded', initializeResearch);
})();
