/**
 * Research Component
 * Manages the research form and handles submissions
 */
(function() {
    // 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 modelInput = null;
    let modelDropdown = null;
    let modelDropdownList = null;
    let modelRefreshBtn = null;
    let searchEngineInput = null;
    let searchEngineDropdown = null;
    let searchEngineDropdownList = null;
    let searchEngineRefreshBtn = null;
    let iterationsInput = null;
    let questionsPerIterationInput = null;
    let advancedToggle = null;
    let advancedPanel = null;

    // Cache keys
    const CACHE_KEYS = {
        MODELS: 'deepResearch.availableModels',
        SEARCH_ENGINES: 'deepResearch.searchEngines',
        CACHE_TIMESTAMP: 'deepResearch.cacheTimestamp'
    };

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

    // Flag to track if we're using fallback data
    let usingFallbackModels = false;
    let usingFallbackSearchEngines = false;

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

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

    /**
     * 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('aria-checked', 'false');
            m.setAttribute('tabindex', '-1');
        });

        modeElement.classList.add('active');
        modeElement.setAttribute('aria-checked', 'true');
        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 from README
    const MODEL_PROVIDERS = [
        { value: 'OLLAMA', label: 'Ollama (Local)' },
        { value: 'OPENAI', label: 'OpenAI (Cloud)' },
        { value: 'ANTHROPIC', label: 'Anthropic (Cloud)' },
        { value: 'OPENAI_ENDPOINT', label: 'Custom OpenAI Endpoint' },
        { value: 'VLLM', label: 'vLLM (Local)' },
        { value: 'LMSTUDIO', label: 'LM Studio (Local)' },
        { value: 'LLAMACPP', label: 'Llama.cpp (Local)' }
    ];

    // Store available models by provider
    let availableModels = {
        OLLAMA: [],
        OPENAI: [
            { value: 'gpt-4o', label: 'GPT-4o' },
            { value: 'gpt-4', label: 'GPT-4' },
            { value: 'gpt-3.5-turbo', label: 'GPT-3.5 Turbo' }
        ],
        ANTHROPIC: [
            { value: 'claude-3-5-sonnet-latest', label: 'Claude 3.5 Sonnet' },
            { value: 'claude-3-opus-20240229', label: 'Claude 3 Opus' },
            { value: 'claude-3-sonnet-20240229', label: 'Claude 3 Sonnet' },
            { value: 'claude-3-haiku-20240307', label: 'Claude 3 Haiku' }
        ],
        VLLM: [],
        LMSTUDIO: [],
        LLAMACPP: [],
        OPENAI_ENDPOINT: []
    };

    /**
     * Initialize the research component
     */
    function initializeResearch() {
        // Set initializing flag
        isInitializing = true;

        // Get DOM elements
        form = document.getElementById('research-form');
        queryInput = document.getElementById('query');
        modeOptions = document.querySelectorAll('.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');

        // 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
        iterationsInput = document.getElementById('iterations');
        questionsPerIterationInput = document.getElementById('questions_per_iteration');
        advancedToggle = document.querySelector('.advanced-options-toggle');
        advancedPanel = document.querySelector('.advanced-options-panel');

        // First, try to load settings from localStorage for immediate display
        const lastProvider = localStorage.getItem('lastUsedProvider');
        const lastModel = localStorage.getItem('lastUsedModel');
        const lastSearchEngine = localStorage.getItem('lastUsedSearchEngine');
        const lastStrategy = localStorage.getItem('lastUsedStrategy') || 'source-based';

        console.log('Local storage values:', { provider: lastProvider, model: lastModel, searchEngine: lastSearchEngine, strategy: lastStrategy });

        // Apply local storage values if available
        if (lastProvider && modelProviderSelect) {
            console.log('Setting provider from localStorage:', lastProvider);
            modelProviderSelect.value = lastProvider;
            // Show/hide endpoint container as needed
            if (endpointContainer) {
                endpointContainer.style.display = lastProvider === 'OPENAI_ENDPOINT' ? 'block' : 'none';
            }
        }

        // Apply saved strategy
        const strategySelect = document.getElementById('strategy');
        if (strategySelect && lastStrategy) {
            console.log('Setting strategy from localStorage:', lastStrategy);
            strategySelect.value = lastStrategy;
        }

        // Initialize the UI first (immediate operations)
        setupEventListeners();
        populateModelProviders();
        initializeDropdowns();

        // 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);
            }
        }

        // Set initial state of the advanced options panel based on localStorage
        const savedState = localStorage.getItem('advancedOptionsOpen') === 'true';
        if (savedState && advancedPanel) {
            advancedPanel.style.display = 'block';
            advancedPanel.classList.add('expanded');
            if (advancedToggle) {
                advancedToggle.classList.add('open');
                const icon = advancedToggle.querySelector('i');
                if (icon) icon.className = 'fas fa-chevron-up';
            }
        }

        // Then load data asynchronously (don't block UI)
        Promise.all([
            loadModelOptions(false),
            loadSearchEngineOptions(false)
        ]).then(([modelData, searchEngineData]) => {
            console.log('Data loaded successfully');

            // After loading model data, update the UI with the loaded data
            const currentProvider = modelProviderSelect ? modelProviderSelect.value : (lastProvider || 'OLLAMA');
            updateModelOptionsForProvider(currentProvider, false);

            // Update search engine options
            if (searchEngineData && Array.isArray(searchEngineData)) {
                searchEngineOptions = searchEngineData;
                console.log('Loaded search engines:', searchEngineData.length);

                // 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) => {
                            console.log('Search engine selected:', 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.'
                    );

                    // If we have a last selected search engine, try to select it
                    if (lastSearchEngine) {
                        console.log('Trying to select last search engine:', lastSearchEngine);
                        // Find the matching engine
                        const matchingEngine = searchEngineOptions.find(engine =>
                            engine.value === lastSearchEngine || engine.id === lastSearchEngine);

                        if (matchingEngine) {
                            console.log('Found matching search engine:', 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;
                            }
                        }
                    }
                }
            }

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

            // 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') {
            console.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;
        }

        console.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,
                () => {
                    console.log('Getting model options from dropdown:', modelOptions);
                    return modelOptions.length > 0 ? modelOptions : [{ value: '', label: 'No models available' }];
                },
                (value, item) => {
                    console.log('Model selected:', value, item);
                    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) {
                        saveModelSettings(value);
                    }
                },
                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('loading');

                    // Force refresh of model options
                    loadModelOptions(true).then(() => {
                        // Remove loading class
                        modelRefreshBtn.classList.remove('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 => {
                        console.error('Error refreshing models:', error);

                        // Remove loading class
                        modelRefreshBtn.classList.remove('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('loading');
            }

            const searchDropdownInstance = window.setupCustomDropdown(
                searchEngineInput,
                searchEngineDropdownList,
                () => {
                    // Log available search engines for debugging
                    console.log('Getting search engine options:', searchEngineOptions);
                    return searchEngineOptions.length > 0 ? searchEngineOptions : [{ value: '', label: 'No search engines available' }];
                },
                (value, item) => {
                    console.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;
                    }

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

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

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

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

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

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

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

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

        // INITIALIZE ADVANCED OPTIONS FIRST - before any async operations
        // Advanced options toggle - make immediately responsive
        if (advancedToggle && advancedPanel) {
            // Set initial state based on localStorage, relying only on CSS classes
            const savedState = localStorage.getItem('advancedOptionsOpen') === 'true';

            if (savedState) {
                advancedToggle.classList.add('open', 'expanded');
                advancedToggle.classList.toggle('expanded', true);

                // Update icon immediately
                const icon = advancedToggle.querySelector('i');
                if (icon) {
                    icon.className = 'fas fa-chevron-up';
                }
            } else {
                advancedToggle.classList.remove('open', 'expanded');
                advancedToggle.classList.toggle('expanded', false);
                // Ensure icon is correct
                const icon = advancedToggle.querySelector('i');
                if (icon) {
                    icon.className = 'fas fa-chevron-down';
                }
            }

            // Add the click listener
            advancedToggle.addEventListener('click', function() {
                // Toggle classes for both approaches
                const isOpen = advancedToggle.classList.toggle('open');
                advancedToggle.classList.toggle('expanded', isOpen);

                // Save state to localStorage
                localStorage.setItem('advancedOptionsOpen', isOpen);

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

                // Animate using CSS transitions based on the 'expanded' class
                // No need for direct style manipulation or timeouts here if CSS is set up correctly
                // Example: CSS might have transition on max-height and opacity
                // If explicit display toggle is needed for transition logic:
                if (isOpen) {
                    advancedPanel.style.display = 'block'; // Show before transition starts
                    // Force reflow to ensure display:block is applied before transition
                    advancedPanel.offsetHeight;
                    advancedPanel.classList.add('expanded'); // Add class to trigger transition
                } else {
                    advancedPanel.classList.remove('expanded'); // Remove class to trigger transition
                    // Optionally hide with display:none after transition ends (using event listener)
                    advancedPanel.addEventListener('transitionend', () => {
                        if (!advancedPanel.classList.contains('expanded')) {
                            advancedPanel.style.display = 'none';
                        }
                    }, { once: true });
                }
            });
        }

        // 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();
                    const previousMode = this.previousElementSibling;
                    if (previousMode && previousMode.classList.contains('mode-option')) {
                        selectMode(previousMode);
                        previousMode.focus();
                    }
                } else if (event.key === 'ArrowRight' || event.key === 'ArrowDown') {
                    event.preventDefault();
                    const nextMode = this.nextElementSibling;
                    if (nextMode && nextMode.classList.contains('mode-option')) {
                        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)
                        return;
                    } 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;
                console.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';
                }

                // Update model options based on provider
                updateModelOptionsForProvider(provider, true);

                // 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);
                        }
                    }
                });
            });
        }

        // 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 => {
            console.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 = '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;

        // 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);
        });

        // Default to Ollama
        modelProviderSelect.value = 'OLLAMA';

        // Initial update of model options
        updateModelOptionsForProvider('OLLAMA');
    }

    /**
     * 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();
            console.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)) {
            console.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;
        }

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

            // Filter models based on provider
            let models = [];

        // Special handling for OLLAMA provider - don't do strict filtering
        if (providerUpper === 'OLLAMA') {
            console.log('Searching for Ollama models...');

            // First attempt: get models with provider explicitly set to OLLAMA
            models = allModels.filter(model => {
                if (!model || typeof model !== 'object') return false;
                // Check if provider is set to OLLAMA
                const modelProvider = (model.provider || '').toUpperCase();
                return modelProvider === 'OLLAMA';
            });

            console.log(`Found ${models.length} models with provider="OLLAMA"`);

            // If we didn't find enough models, look for models with Ollama in the name or id
            if (models.length < 2) {
                console.log('Searching more broadly for Ollama models');
                models = allModels.filter(model => {
                    if (!model || typeof model !== 'object') return false;

                    // Skip provider options that are not actual models
                    if (model.value && !model.id && !model.name) return false;

                    // Check various properties that might indicate this is an Ollama model
                    const modelProvider = (model.provider || '').toUpperCase();
                        const modelName = (model.name || model.label || '').toLowerCase();
                        const modelId = (model.id || model.value || '').toLowerCase();

                        // Include if: provider is OLLAMA OR name contains "ollama" OR id is one of common Ollama models
                    return modelProvider === 'OLLAMA' ||
                           modelName.includes('ollama') ||
                           modelId.includes('llama') ||
                           modelId.includes('mistral') ||
                           modelId.includes('gemma');
                });

                console.log(`Broader search found ${models.length} possible Ollama models`);
            }

            // If we still don't have enough models, look for any that might be LLMs
            if (models.length < 2) {
                console.log('Still few models found, trying any model with likely LLM names');
                // Add models that look like they could be LLMs (if they're not already included)
                const moreModels = allModels.filter(model => {
                    if (!model || typeof model !== 'object') return false;
                        if (models.some(m => m.id === model.id || m.value === model.value)) return false; // Skip if already included

                        const modelId = (model.id || model.value || '').toLowerCase();
                        const modelName = (model.name || model.label || '').toLowerCase();

                    // Include common LLM name patterns
                    return modelId.includes('gpt') ||
                           modelId.includes('llama') ||
                           modelId.includes('mistral') ||
                           modelId.includes('gemma') ||
                           modelId.includes('claude') ||
                           modelName.includes('llm') ||
                           modelName.includes('model');
                });

                console.log(`Found ${moreModels.length} additional possible LLM models`);
                models = [...models, ...moreModels];
            }

            // If we STILL have few or no models, use our fallbacks
            if (models.length < 2) {
                console.log('No Ollama models found, using fallbacks');
                models = [
                    { id: 'llama3', name: 'Llama 3 (Ollama)', provider: 'OLLAMA' },
                    { id: 'mistral', name: 'Mistral (Ollama)', provider: 'OLLAMA' },
                    { id: 'gemma:latest', name: 'Gemma (Ollama)', provider: 'OLLAMA' }
                ];
                usingFallbackModels = true;
            }
            } else if (providerUpper === 'ANTHROPIC') {
                // Filter Anthropic models
            models = allModels.filter(model => {
                if (!model || typeof model !== 'object') return false;

                    // Skip provider options
                    if (model.value && !model.id && !model.name) return false;

                    // Check provider, name, or ID for Anthropic indicators
                    const modelProvider = (model.provider || '').toUpperCase();
                    const modelName = (model.name || model.label || '').toLowerCase();
                    const modelId = (model.id || model.value || '').toLowerCase();

                    return modelProvider === 'ANTHROPIC' ||
                           modelName.includes('claude') ||
                           modelId.includes('claude');
                });

                // Add fallbacks if necessary
                if (models.length === 0) {
                    console.log('No Anthropic models found, using fallbacks');
                    models = [
                        { id: 'claude-3-5-sonnet-latest', name: 'Claude 3.5 Sonnet (Anthropic)', provider: 'ANTHROPIC' },
                        { id: 'claude-3-opus-20240229', name: 'Claude 3 Opus (Anthropic)', provider: 'ANTHROPIC' },
                        { id: 'claude-3-sonnet-20240229', name: 'Claude 3 Sonnet (Anthropic)', provider: 'ANTHROPIC' }
                    ];
                    usingFallbackModels = true;
                }
            } else if (providerUpper === 'OPENAI') {
                // Filter OpenAI models
                models = allModels.filter(model => {
                    if (!model || typeof model !== 'object') return false;

                    // Skip provider options
                    if (model.value && !model.id && !model.name) return false;

                    // Check provider, name, or ID for OpenAI indicators
                    const modelProvider = (model.provider || '').toUpperCase();
                    const modelName = (model.name || model.label || '').toLowerCase();
                    const modelId = (model.id || model.value || '').toLowerCase();

                    return modelProvider === 'OPENAI' ||
                           modelName.includes('gpt') ||
                           modelId.includes('gpt');
                });

                // Add fallbacks if necessary
            if (models.length === 0) {
                    console.log('No OpenAI models found, using fallbacks');
                    models = [
                        { id: 'gpt-4o', name: 'GPT-4o (OpenAI)', provider: 'OPENAI' },
                        { id: 'gpt-4', name: 'GPT-4 (OpenAI)', provider: 'OPENAI' },
                        { id: 'gpt-3.5-turbo', name: 'GPT-3.5 Turbo (OpenAI)', provider: 'OPENAI' }
                    ];
                    usingFallbackModels = true;
                }
            } else if (providerUpper === 'OPENAI_ENDPOINT') {
                models = allModels.filter(model => {
                    if (!model || typeof model !== 'object') return false;

                    // Skip provider options
                    if (model.value && !model.id && !model.name) return false;

                    const modelProvider = (model.provider || '').toUpperCase();
                    return modelProvider === 'OPENAI_ENDPOINT';
                });

                console.log(`Found ${models.length} models with provider="OPENAI_ENDPOINT"`);

                if (models.length === 0) {
                    console.log('No OPENAI_ENDPOINT models found, checking for models with "Custom" in label');
                    models = allModels.filter(model => {
                        if (!model || typeof model !== 'object') return false;

                        // Skip provider options
                        if (model.value && !model.id && !model.name) return false;

                        const modelLabel = (model.label || '').toLowerCase();
                        return modelLabel.includes('custom');
                    });

                    console.log(`Found ${models.length} models with "Custom" in label`);
                }

                if (models.length === 0) {
                    console.log('No OPENAI_ENDPOINT or Custom models found, using OpenAI models as examples');
                    models = allModels.filter(model => {
                        if (!model || typeof model !== 'object') return false;

                        // Skip provider options
                        if (model.value && !model.id && !model.name) return false;

                        const modelProvider = (model.provider || '').toUpperCase();
                        const modelId = (model.id || model.value || '').toLowerCase();
                        return modelProvider === 'OPENAI' ||
                               modelId.includes('gpt');
                    });
                }

                // Add fallbacks if necessary
                if (models.length === 0) {
                    console.log('No models found for custom endpoint, using fallbacks');
                    models = [
                        { id: 'gpt-4o', name: 'GPT-4o (via Custom Endpoint)', provider: 'OPENAI_ENDPOINT' },
                        { id: 'claude-3-5-sonnet-latest', name: 'Claude 3.5 Sonnet (via Custom Endpoint)', provider: 'OPENAI_ENDPOINT' }
                    ];
                    usingFallbackModels = true;
                }
            } else {
                // Standard filtering for other providers
                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 ? model.provider.toUpperCase() : '';
                    return modelProvider === providerUpper;
                });

                // If we found no models for this provider, add fallbacks
                if (models.length === 0) {
                    console.log(`No models found for provider ${provider}, using generic fallbacks`);
                    models = [
                        { id: 'model1', name: `Model 1 (${providerUpper})`, provider: providerUpper },
                        { id: 'model2', name: `Model 2 (${providerUpper})`, provider: providerUpper }
                    ];
                usingFallbackModels = true;
            }
        }

            console.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 };
        });

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

        // Check for stored last model before deciding what to select
            let lastSelectedModel = localStorage.getItem('lastUsedModel');

            // Also check the database setting
            fetch('/research/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;
                    console.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) {
                        console.log('Found matching model in filtered options:', dbModelMatch);
                        lastSelectedModel = dbModelValue;
                    }
                }

                // Continue with model selection
                selectModelBasedOnProvider(resetSelectedModel, lastSelectedModel);
                resolve(modelOptions);
            })
            .catch(error => {
                console.error('Error fetching model from database:', 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 (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;
                        console.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 first available model if no selection and models are available
        if ((!selectedModelValue || selectedModelValue === '') && modelOptions.length > 0 && modelInput) {
            // Try to find last used model first
            if (lastSelectedModel) {
                const matchingModel = modelOptions.find(model => model.value === lastSelectedModel);
                if (matchingModel) {
                    modelInput.value = matchingModel.label;
                    selectedModelValue = matchingModel.value;
                    console.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 match found, select first available
            modelInput.value = modelOptions[0].label;
            selectedModelValue = modelOptions[0].value;
            console.log('Auto-selected first available 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);
            }
        }
    }

    /**
     * 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('/research/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) {
            console.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() {
        console.log('Getting selected model...');
        console.log('- selectedModelValue:', selectedModelValue);
        console.log('- modelInput value:', modelInput ? modelInput.value : 'modelInput not found');
        console.log('- modelInput exists:', !!modelInput);

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

        // Then try the input field value
        if (modelInput && modelInput.value.trim()) {
            console.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) {
            console.log('Using hidden input value:', hiddenModelInput.value);
            return hiddenModelInput.value;
        }

        console.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(`/research/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
                };
            } else {
                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) {
            console.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() {
        console.log('Loading settings from database...');
        let numApiCallsPending = 2;

        // Fetch the current settings from the settings API
        fetch('/research/settings/api/llm', {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json'
            }
        })
        .then(response => {
            if (!response.ok) {
                throw new Error(`API error: ${response.status}`);
            }
            return response.json();
        })
        .then(data => {
            console.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.value["provider"];
                const modelSetting = data.settings.value["model"];
                const customEndpointUrl = data.settings.value["openai_endpoint.url"];

                // Update provider dropdown if we have a valid provider
                if (providerSetting && modelProviderSelect) {
                    const providerValue = providerSetting.toUpperCase();
                    console.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) {
                        console.log('Found matching provider option:', matchingOption.value);
                        modelProviderSelect.value = matchingOption.value;
                        // Also save to localStorage
                        localStorage.setItem('lastUsedProvider', 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) {
                            console.log('Found case-insensitive provider match:', caseInsensitiveMatch.value);
                            modelProviderSelect.value = caseInsensitiveMatch.value;
                            // Also save to localStorage
                            localStorage.setItem('lastUsedProvider', caseInsensitiveMatch.value);
                        } else {
                            console.warn(`No matching provider option found for '${providerValue}'`);
                        }
                    }

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

                // Update the custom endpoint URl if we have one.
                if (customEndpointUrl && customEndpointInput) {
                    console.log('Setting endpoint URL to:', customEndpointUrl);
                    customEndpointInput.value = customEndpointUrl;
                }

                // 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;
                        console.log('Setting model to:', modelValue);

                        // Save to localStorage
                        localStorage.setItem('lastUsedModel', modelValue);

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

                        if (matchingModel) {
                            console.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
                            console.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;
                            }
                        }
                    }
                });


            }

            // If all the calls to the settings API are finished, we're no
            // longer initializing.
            numApiCallsPending--;
            isInitializing = (numApiCallsPending === 0);
        })
        .catch(error => {
            console.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);
        });

        fetch('/research/settings/api/search.tool', {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json'
            }
        })
            .then(response => {
                if (!response.ok) {
                    throw new Error(`API error: ${response.status}`);
                }
                return response.json();
            })
            .then(data => {
                console.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 searchEngineSetting = data.settings;

                    // Update search engine if we have a valid value
                    if (searchEngineSetting && searchEngineSetting.value && searchEngineInput) {
                        const engineValue = searchEngineSetting.value;
                        console.log('Setting search engine to:', engineValue);

                        // Save to localStorage
                        localStorage.setItem('lastUsedSearchEngine', engineValue);

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

                        if (matchingEngine) {
                            console.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
                            console.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;
                            }
                        }
                    }
                }

                // If all the calls to the settings API are finished, we're no
                // longer initializing.
                numApiCallsPending--;
                isInitializing = (numApiCallsPending === 0);

            })
            .catch(error => {
                console.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);
            });
    }

    // Add a fallback function to use localStorage settings
    function fallbackToLocalStorageSettings() {
        const provider = localStorage.getItem('lastUsedProvider');
        const model = localStorage.getItem('lastUsedModel');
        const searchEngine = localStorage.getItem('lastUsedSearchEngine');

        console.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';
            }
        }

        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, reject) => {
            // Check cache first if not forcing refresh
            if (!forceRefresh) {
                const cachedData = getCachedData(CACHE_KEYS.MODELS);
                const cacheTimestamp = getCachedData(CACHE_KEYS.CACHE_TIMESTAMP);

                // Use cache if it exists and isn't expired
                if (cachedData && cacheTimestamp && (Date.now() - cacheTimestamp < CACHE_EXPIRATION)) {
                    console.log('Using cached model data');
                    resolve(cachedData);
                    return;
                }
            }

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

            // Fetch from API if cache is invalid or refresh is forced
            fetch('/research/settings/api/available-models')
                .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('loading');
                    }

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

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

                        // Cache the data
                        cacheData(CACHE_KEYS.MODELS, formattedModels);
                        cacheData(CACHE_KEYS.CACHE_TIMESTAMP, Date.now());

                        // Also cache with the settings.js cache keys for cross-component sharing
                        cacheData('deepResearch.availableModels', formattedModels);
                        cacheData('deepResearch.cacheTimestamp', Date.now());

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

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

                    // Use cached data if available, even if expired
                    const cachedData = getCachedData(CACHE_KEYS.MODELS);
                    if (cachedData) {
                        console.log('Using expired cached model data due to API error');
                        resolve(cachedData);
                    } else {
                        // Use fallback data if no cache available
                        console.log('Using fallback model data');
                        const fallbackModels = getFallbackModels();
                        cacheData(CACHE_KEYS.MODELS, fallbackModels);
                        cacheData('deepResearch.availableModels', fallbackModels);
                        resolve(fallbackModels);
                    }
                });
        });
    }

    // 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 Ollama models
        if (data.providers && data.providers.ollama_models) {
            data.providers.ollama_models.forEach(model => {
                formatted.push({
                    ...model,
                    id: model.value,
                    provider: 'OLLAMA'
                });
            });
        }

        // Process OpenAI models
        if (data.providers && data.providers.openai_models) {
            data.providers.openai_models.forEach(model => {
                formatted.push({
                    ...model,
                    id: model.value,
                    provider: 'OPENAI'
                });
            });
        }

        // Process Anthropic models
        if (data.providers && data.providers.anthropic_models) {
            data.providers.anthropic_models.forEach(model => {
                formatted.push({
                    ...model,
                    id: model.value,
                    provider: 'ANTHROPIC'
                });
            });
        }

        // Process Custom OpenAI Endpoint models
        if (data.providers && data.providers.openai_endpoint_models) {
            data.providers.openai_endpoint_models.forEach(model => {
                formatted.push({
                    ...model,
                    id: model.value,
                    provider: 'OPENAI_ENDPOINT'
                });
            });
        }

        return formatted;
    }

    // Get fallback models if API fails
    function getFallbackModels() {
        return [
            // Ollama models
            { id: 'llama3', value: 'llama3', label: 'Llama 3 (Ollama)', provider: 'OLLAMA' },
            { id: 'mistral', value: 'mistral', label: 'Mistral (Ollama)', provider: 'OLLAMA' },
            { id: 'gemma:latest', value: 'gemma:latest', label: 'Gemma (Ollama)', provider: 'OLLAMA' },

            // OpenAI models
            { id: 'gpt-4o', value: 'gpt-4o', label: 'GPT-4o (OpenAI)', provider: 'OPENAI' },
            { id: 'gpt-4', value: 'gpt-4', label: 'GPT-4 (OpenAI)', provider: 'OPENAI' },
            { id: 'gpt-3.5-turbo', value: 'gpt-3.5-turbo', label: 'GPT-3.5 Turbo (OpenAI)', provider: 'OPENAI' },

            // Anthropic models
            { id: 'claude-3-5-sonnet-latest', value: 'claude-3-5-sonnet-latest', label: 'Claude 3.5 Sonnet (Anthropic)', provider: 'ANTHROPIC' },
            { id: 'claude-3-opus-20240229', value: 'claude-3-opus-20240229', label: 'Claude 3 Opus (Anthropic)', provider: 'ANTHROPIC' },
            { id: 'claude-3-sonnet-20240229', value: 'claude-3-sonnet-20240229', label: 'Claude 3 Sonnet (Anthropic)', provider: 'ANTHROPIC' }
        ];
    }

    // Cache and retrieve data in localStorage
    function cacheData(key, data) {
        try {
            localStorage.setItem(key, JSON.stringify(data));
        } catch (e) {
            console.error('Error caching data:', e);
        }
    }

    function getCachedData(key) {
        try {
            const item = localStorage.getItem(key);
            return item ? JSON.parse(item) : null;
        } catch (e) {
            console.error('Error retrieving cached data:', e);
            return null;
        }
    }

    // Load search engine options
    function loadSearchEngineOptions(forceRefresh = false) {
        return new Promise((resolve, reject) => {
            // Check cache first if not forcing refresh
            if (!forceRefresh) {
                const cachedData = getCachedData(CACHE_KEYS.SEARCH_ENGINES);
                const cacheTimestamp = getCachedData(CACHE_KEYS.CACHE_TIMESTAMP);

                // Use cache if it exists and isn't expired
                if (cachedData && cacheTimestamp && (Date.now() - cacheTimestamp < CACHE_EXPIRATION)) {
                    console.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('loading');
            }

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

            // Fetch from API
            fetch('/research/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('loading');
                    }

                    // Log the entire response to debug
                    console.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) {
                        console.log('Processing engine_options:', data.engine_options.length + ' options');

                        // Map the engine options to our dropdown format
                        formattedEngines = data.engine_options.map(engine => ({
                            value: engine.value || engine.id || '',
                            label: engine.label || engine.name || engine.value || '',
                            type: engine.type || 'search'
                        }));
                    }
                    // Also try adding engines from engines object if it exists
                    if (data && data.engines) {
                        console.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)) {
                                console.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) {
                        console.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)) {
                        console.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'
                        }));
                    }

                    console.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 => {
                    console.error('Error loading search engines:', error);

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

                    // Use cached data if available, even if expired
                    const cachedData = getCachedData(CACHE_KEYS.SEARCH_ENGINES);
                    if (cachedData) {
                        console.log('Using expired cached search engine data due to API error');
                        searchEngineOptions = cachedData;
                        resolve(cachedData);
                    } else {
                        // Use fallback data if no cache available
                        console.log('Using fallback search engine data');
                        const fallbackEngines = [
                            { value: 'google', label: 'Google Search' },
                            { value: 'duckduckgo', label: 'DuckDuckGo' },
                            { value: 'bing', label: 'Bing Search' }
                        ];
                        searchEngineOptions = fallbackEngines;
                        cacheData(CACHE_KEYS.SEARCH_ENGINES, fallbackEngines);
                        resolve(fallbackEngines);
                    }
                });
        });
    }

    // Save model settings to database
    function saveModelSettings(modelValue) {
        // Save selection to localStorage for persistence between sessions
        localStorage.setItem('lastUsedModel', modelValue);

        // 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('/research/settings/api/llm.model', {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
            },
            body: JSON.stringify({ value: modelValue })
        })
        .then(response => response.json())
        .then(data => {
            console.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 => {
            console.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) {
        // Save to localStorage
        localStorage.setItem('lastUsedSearchEngine', engineValue);

        // 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('/research/settings/api/search.tool', {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
            },
            body: JSON.stringify({ value: engineValue })
        })
        .then(response => response.json())
        .then(data => {
            console.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 => {
            console.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);
            }
        });
    }

    // Save provider setting to database
    function saveProviderSetting(providerValue) {
        // Save to localStorage
        localStorage.setItem('lastUsedProvider', providerValue);

        // 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('/research/settings/api/llm.provider', {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
            },
            body: JSON.stringify({ value: providerValue.toLowerCase() })
        })
        .then(response => response.json())
        .then(data => {
            console.log('Provider setting saved to database:', data);

            // Optionally show a notification
            if (window.ui && window.ui.showMessage) {
                window.ui.showMessage(`Provider updated to: ${providerValue}`, 'success', 2000);
            }
        })
        .catch(error => {
            console.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);
            }
        });
    }

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

        // Disable the submit button to prevent multiple submissions
        startBtn.disabled = true;
        startBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Starting...';

        // 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';

        // Get values from form fields
        const query = queryInput.value.trim();
        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 iterations = iterationsInput ? parseInt(iterationsInput.value, 10) : 2;
        const questionsPerIteration = questionsPerIterationInput ?
                                    parseInt(questionsPerIterationInput.value, 10) : 3;
        const enableNotifications = notificationToggle ? notificationToggle.checked : true;

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

        // Validate the query
        if (!query) {
            // Show error if query is empty
            showAlert('Please enter a research query.', 'error');

            // Re-enable the button
            startBtn.disabled = false;
            startBtn.innerHTML = '<i class="fas fa-rocket"></i> Start Research';
            return;
        }

        // Prepare the data for submission
        const formData = {
            query: query,
            mode: mode,
            model_provider: modelProvider,
            model: model,
            custom_endpoint: customEndpoint,
            search_engine: searchEngine,
            iterations: iterations,
            questions_per_iteration: questionsPerIteration,
            strategy: strategy
        };

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

        // Get CSRF token from meta tag
        const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content;

        // Submit the form data to the backend
        fetch('/research/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') {
                console.log('Research started successfully:', data);

                // Store research preferences in localStorage
                localStorage.setItem('lastResearchMode', mode);
                localStorage.setItem('lastModelProvider', modelProvider);
                localStorage.setItem('lastModel', model);
                localStorage.setItem('lastSearchEngine', searchEngine);
                localStorage.setItem('enableNotifications', enableNotifications);
                localStorage.setItem('lastUsedStrategy', strategy);

                // Redirect to the progress page
                window.location.href = `/research/progress/${data.research_id}`;
            } else {
                // Show error message
                showAlert(data.message || 'Failed to start research.', 'error');

                // Re-enable the button
                startBtn.disabled = false;
                startBtn.innerHTML = '<i class="fas fa-rocket"></i> Start Research';
            }
        })
        .catch(error => {
            console.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;
            startBtn.innerHTML = '<i class="fas fa-rocket"></i> Start Research';
        });
    }

    /**
     * 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') {
        const alertContainer = document.getElementById('research-alert');
        if (!alertContainer) return;

        // Clear any existing alerts
        alertContainer.innerHTML = '';

        // Create the alert element
        const alert = document.createElement('div');
        alert.className = `alert alert-${type}`;
        alert.innerHTML = `
            <i class="fas ${type === 'success' ? 'fa-check-circle' :
                         type === 'error' ? 'fa-exclamation-circle' :
                         type === 'warning' ? 'fa-exclamation-triangle' :
                         'fa-info-circle'}"></i>
            ${message}
            <span class="alert-close">&times;</span>
        `;

        // Add click handler for the close button
        const closeBtn = alert.querySelector('.alert-close');
        if (closeBtn) {
            closeBtn.addEventListener('click', () => {
                alert.remove();
                alertContainer.style.display = 'none';
            });
        }

        // Add to the container and show it
        alertContainer.appendChild(alert);
        alertContainer.style.display = 'block';

        // Auto-hide after 5 seconds
        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);
})();
