// Promptheus Web UI - Modern Application Controller
class PromptheusApp {
    constructor() {
        this.apiBaseUrl = window.location.origin;
        this.currentHistoryPage = 0; // 0-based page index
        this.currentPageSize = 20;
        this.totalHistoryPages = 0;
        this.currentAbortController = null;
        this.currentEventSource = null;
        this.streamingText = '';
        this.streamingInterval = null;
        this.currentOptimizedPrompt = ''; // Store current prompt
        this.cachedModels = {}; // Store fetched models by provider ID
        this.providerCapabilities = {}; // Store provider capability hints
        this.hasResults = false; // Track if we have results displayed
        this.init();
    }

    init() {
        // Configure marked.js to reduce extra spacing
        if (typeof marked !== 'undefined') {
            marked.setOptions({
                breaks: false,  // Don't convert \n to <br>
                gfm: true,      // GitHub Flavored Markdown
                headerIds: false,
                mangle: false
            });
        }
        this.bindEvents();
        this.loadProviders();
        this.loadHistory();
        this.loadSettings();
        this.loadVersion();
        this.initCustomDropdowns();
    }

    bindEvents() {
        // Mobile menu toggle
        const hamburgerBtn = document.getElementById('hamburger-btn');
        const mobileMenu = document.getElementById('mobile-menu');
        const mobileMenuClose = document.getElementById('mobile-menu-close');
        const settingsBtnMobile = document.getElementById('settings-btn-mobile');

        hamburgerBtn?.addEventListener('click', () => {
            const isOpen = mobileMenu.classList.contains('active');
            mobileMenu.classList.toggle('active');
            hamburgerBtn.classList.toggle('active');
            hamburgerBtn.setAttribute('aria-expanded', !isOpen);
            mobileMenu.setAttribute('aria-hidden', isOpen);
        });

        mobileMenuClose?.addEventListener('click', () => {
            mobileMenu.classList.remove('active');
            hamburgerBtn.classList.remove('active');
            hamburgerBtn.setAttribute('aria-expanded', 'false');
            mobileMenu.setAttribute('aria-hidden', 'true');
        });

        // Close mobile menu when clicking on settings
        settingsBtnMobile?.addEventListener('click', () => {
            mobileMenu.classList.remove('active');
            hamburgerBtn.classList.remove('active');
            hamburgerBtn.setAttribute('aria-expanded', 'false');
            mobileMenu.setAttribute('aria-hidden', 'true');
            // Trigger desktop settings button
            document.getElementById('settings-btn')?.click();
        });

        // Close menu when clicking outside
        document.addEventListener('click', (e) => {
            if (mobileMenu?.classList.contains('active') &&
                !mobileMenu.contains(e.target) &&
                !hamburgerBtn.contains(e.target)) {
                mobileMenu.classList.remove('active');
                hamburgerBtn.classList.remove('active');
                hamburgerBtn.setAttribute('aria-expanded', 'false');
                mobileMenu.setAttribute('aria-hidden', 'true');
            }
        });

        // Main prompt submission
        document.getElementById('submit-btn').addEventListener('click', () => this.submitPrompt());

        // New prompt button (hidden initially, shown after results)
        document.getElementById('start-over-btn').addEventListener('click', () => {
            this.startNewPrompt();
        });

        // Track input changes to detect new prompts (but only when we have results)
        const promptInput = document.getElementById('prompt-input');
        let lastPromptValue = '';
        promptInput.addEventListener('input', () => {
            if (this.hasResults) {
                this.handleInputChange(promptInput.value, lastPromptValue);
                lastPromptValue = promptInput.value;
            }
        });

        // Provider selection
        document.getElementById('provider-select').addEventListener('change', (e) => {
            this.selectProvider(e.target.value);
            this.loadModelsForProvider(e.target.value);

            // Sync mobile provider dropdown and show indicator
            const providerSelectMobile = document.getElementById('provider-select-mobile');
            if (providerSelectMobile) {
                providerSelectMobile.value = e.target.value;
                this.showSyncIndicator('provider-sync-indicator');
            }
        });

        // Model selection
        document.getElementById('model-select').addEventListener('change', (e) => {
            this.selectModel(e.target.value);

            // Sync mobile model dropdown and show indicator
            const modelSelectMobile = document.getElementById('model-select-mobile');
            if (modelSelectMobile) {
                modelSelectMobile.value = e.target.value;
                this.showSyncIndicator('model-sync-indicator');
            }
        });

        // Mobile Provider selection
        const providerSelectMobile = document.getElementById('provider-select-mobile');
        if (providerSelectMobile) {
            providerSelectMobile.addEventListener('change', (e) => {
                // Update main provider dropdown
                const providerSelect = document.getElementById('provider-select');
                if (providerSelect) {
                    providerSelect.value = e.target.value;
                }
                this.selectProvider(e.target.value);
                this.loadModelsForProvider(e.target.value);
                this.showSyncIndicator('provider-sync-indicator');
            });
        }

        // Mobile Model selection
        const modelSelectMobile = document.getElementById('model-select-mobile');
        if (modelSelectMobile) {
            modelSelectMobile.addEventListener('change', (e) => {
                // Update main model dropdown
                const modelSelect = document.getElementById('model-select');
                if (modelSelect) {
                    modelSelect.value = e.target.value;
                }
                this.selectModel(e.target.value);
                this.showSyncIndicator('model-sync-indicator');
            });
        }

        // Copy button
        document.getElementById('copy-btn').addEventListener('click', () => {
            this.copyOutputToClipboard();
        });

        // Refresh models cache (in Settings panel)
        document.getElementById('refresh-models-cache-btn').addEventListener('click', () => {
            const provider = document.getElementById('provider-select').value || this.provider;
            this.refreshModelsCache(provider || 'google');
        });

        // Validate all providers (in Settings panel)
        document.getElementById('validate-all-providers-btn').addEventListener('click', () => {
            this.runProviderPreflight();
        });

        // Provider status indicator - clicking opens settings
        document.getElementById('provider-status-btn').addEventListener('click', () => {
            this.openSettings();
        });

        // Tweak button
        document.getElementById('tweak-btn').addEventListener('click', () => {
            this.showTweakPromptDialog();
        });

        // Settings panel controls
        document.getElementById('settings-btn').addEventListener('click', () => {
            this.openSettings();
        });

        document.getElementById('settings-close-btn').addEventListener('click', () => {
            this.closeSettings();
        });

        document.getElementById('settings-overlay').addEventListener('click', (e) => {
            if (e.target === e.currentTarget) {
                this.closeSettings();
            }
        });

        // Global keyboard shortcuts
        document.addEventListener('keydown', (e) => {
            // Escape key to close settings, tooltips, dropdowns, and cancel ongoing operations
            if (e.key === 'Escape') {
                e.preventDefault();

                // Cancel any ongoing request
                if (this.currentAbortController) {
                    this.cancelCurrentRequest();
                }

                this.closeSettings();
                // Close help tooltips
                document.querySelectorAll('.help-tooltip.visible').forEach(tooltip => {
                    tooltip.classList.remove('visible');
                });
                document.querySelectorAll('.toolbar-help-icon.active').forEach(icon => {
                    icon.classList.remove('active');
                });
                // Close dropdowns
                document.querySelectorAll('.alchemical-dropdown.active').forEach(dropdown => {
                    this.closeDropdown(dropdown);
                });
                return;
            }

            // Don't process other shortcuts when typing in input/textarea
            const target = e.target;
            const isTyping = target.tagName === 'INPUT' || target.tagName === 'TEXTAREA';

            // Alt+Enter or Ctrl+Enter to submit (works even when typing)
            if ((e.altKey || e.ctrlKey) && e.key === 'Enter') {
                e.preventDefault();
                const submitBtn = document.getElementById('submit-btn');
                if (!submitBtn.classList.contains('hidden')) {
                    this.submitPrompt();
                }
                return;
            }

            // Skip other Ctrl shortcuts when typing (except Ctrl+Enter above)
            if (isTyping && e.ctrlKey && e.key.toLowerCase() !== 'enter') {
                return;
            }

            // Ctrl+M - Toggle Mode help tooltip
            if (e.ctrlKey && e.key.toLowerCase() === 'm') {
                e.preventDefault();
                const modeIcon = document.querySelector('.toolbar-help-icon[data-help-for="mode"]');
                if (modeIcon) modeIcon.click();
                return;
            }

            // Ctrl+Shift+S - Toggle Style help tooltip
            if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 's') {
                e.preventDefault();
                const styleIcon = document.querySelector('.toolbar-help-icon[data-help-for="style"]');
                if (styleIcon) styleIcon.click();
                return;
            }

            // Ctrl+P - Focus Provider dropdown
            if (e.ctrlKey && e.key.toLowerCase() === 'p') {
                e.preventDefault();
                const providerSelect = document.getElementById('provider-select');
                providerSelect.focus();
                return;
            }

            // Ctrl+L - Focus Model dropdown
            if (e.ctrlKey && e.key.toLowerCase() === 'l') {
                e.preventDefault();
                const modelSelect = document.getElementById('model-select');
                if (!modelSelect.disabled) {
                    modelSelect.focus();
                }
                return;
            }

            // Ctrl+, - Open Settings
            if (e.ctrlKey && e.key === ',') {
                e.preventDefault();
                this.openSettings();
                return;
            }

            // Ctrl+I - Focus Input textarea
            if (e.ctrlKey && e.key.toLowerCase() === 'i') {
                e.preventDefault();
                const promptInput = document.getElementById('prompt-input');
                promptInput.focus();
                return;
            }

            // Ctrl+Shift+C - Copy output
            if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'c') {
                e.preventDefault();
                const copyBtn = document.getElementById('copy-btn');
                if (!copyBtn.classList.contains('hidden')) {
                    this.copyOutputToClipboard();
                }
                return;
            }

            // Ctrl+T - Tweak prompt
            if (e.ctrlKey && e.key.toLowerCase() === 't') {
                e.preventDefault();
                const tweakBtn = document.getElementById('tweak-btn');
                if (!tweakBtn.classList.contains('hidden')) {
                    this.showTweakPromptDialog();
                }
                return;
            }

            // Ctrl+N - Start Over (New prompt)
            if (e.ctrlKey && e.key.toLowerCase() === 'n') {
                e.preventDefault();
                const startOverBtn = document.getElementById('start-over-btn');
                if (!startOverBtn.classList.contains('hidden')) {
                    this.startNewPrompt();
                }
                return;
            }

            // Ctrl+Shift+X - Cancel operation
            if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'x') {
                e.preventDefault();
                const cancelBtn = document.getElementById('cancel-btn');
                if (!cancelBtn.classList.contains('hidden')) {
                    this.cancelCurrentRequest();
                }
                return;
            }

            // Ctrl+Shift+H - Clear History
            if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'h') {
                e.preventDefault();
                const clearHistoryBtn = document.getElementById('clear-history-btn');
                if (clearHistoryBtn) {
                    this.showConfirmDialog(
                        'Clear All History',
                        'Are you sure you want to clear all history? This action cannot be undone.',
                        () => this.clearHistory()
                    );
                }
                return;
            }

            // Ctrl+[ - Previous history page
            if (e.ctrlKey && e.key === '[') {
                e.preventDefault();
                const prevBtn = document.getElementById('prev-page-btn');
                if (!prevBtn.disabled) {
                    this.previousHistoryPage();
                }
                return;
            }

            // Ctrl+] - Next history page
            if (e.ctrlKey && e.key === ']') {
                e.preventDefault();
                const nextBtn = document.getElementById('next-page-btn');
                if (!nextBtn.disabled) {
                    this.nextHistoryPage();
                }
                return;
            }

            // ? - Show keyboard shortcuts help
            if (e.key === '?' && !isTyping) {
                e.preventDefault();
                this.showKeyboardShortcuts();
                return;
            }
        });

        // History pagination
        document.getElementById('prev-page-btn').addEventListener('click', () => {
            this.previousHistoryPage();
        });

        document.getElementById('next-page-btn').addEventListener('click', () => {
            this.nextHistoryPage();
        });

        document.getElementById('page-size-select').addEventListener('change', (e) => {
            this.currentPageSize = parseInt(e.target.value);
            this.currentHistoryPage = 0;
            this.loadHistory();
        });

        // Cancel button
        document.getElementById('cancel-btn').addEventListener('click', () => {
            this.cancelCurrentRequest();
        });

        // Clear history button
        document.getElementById('clear-history-btn').addEventListener('click', () => {
            this.showConfirmDialog(
                'Clear All History',
                'Are you sure you want to clear all history? This action cannot be undone.',
                () => this.clearHistory()
            );
        });
    }

    /* ===================================================================
       SETTINGS PANEL MANAGEMENT
       =================================================================== */

    openSettings() {
        const overlay = document.getElementById('settings-overlay');
        const panel = document.getElementById('settings-panel');

        overlay.classList.add('active');
        panel.classList.add('active');

        // Load cached validation results if available
        this.loadCachedValidationResults();

        // Focus first focusable element
        setTimeout(() => {
            const firstInput = panel.querySelector('input, button, select');
            if (firstInput) firstInput.focus();
        }, 300);
    }

    closeSettings() {
        const overlay = document.getElementById('settings-overlay');
        const panel = document.getElementById('settings-panel');

        overlay.classList.remove('active');
        panel.classList.remove('active');
    }

    /* ===================================================================
       INPUT STATE MANAGEMENT
       =================================================================== */

    startNewPrompt() {
        const promptInput = document.getElementById('prompt-input');
        const outputDiv = document.getElementById('output');
        const tweakBtn = document.getElementById('tweak-btn');
        const copyBtn = document.getElementById('copy-btn');
        const startOverBtn = document.getElementById('start-over-btn');

        // Clear the input field and reset state
        promptInput.value = '';
        this.hasResults = false;

        // Clear output with transition
        this.clearOutputWithTransition();

        // Hide action buttons and start over button
        tweakBtn.classList.add('hidden');
        copyBtn.classList.add('hidden');
        startOverBtn.classList.add('hidden');

        // Update placeholder text to initial state
        promptInput.placeholder = 'Enter your prompt here...';

        // Focus input for convenience
        promptInput.focus();
    }

    showResultsState() {
        const promptInput = document.getElementById('prompt-input');
        const startOverBtn = document.getElementById('start-over-btn');

        this.hasResults = true;

        // Update placeholder to indicate they can optimize another prompt
        promptInput.placeholder = 'Optimize another prompt...';

        // Show the "Start Over" button
        startOverBtn.classList.remove('hidden');
    }

    handleInputChange(currentValue, lastValue) {
        const outputDiv = document.getElementById('output');
        const hasOutput = outputDiv.querySelector('.optimized-prompt-content');

        if (!hasOutput) return;

        // Calculate similarity between current and last prompt
        const isSimilar = this.calculateSimilarity(currentValue, lastValue) > 0.7;

        // If user is typing something significantly different (more than 10 chars changed)
        if (!isSimilar && currentValue.length > 10 && Math.abs(currentValue.length - lastValue.length) > 5) {
            this.clearOutputWithTransition();
            this.hasResults = false;
            document.getElementById('start-over-btn').classList.add('hidden');
            document.getElementById('tweak-btn').classList.add('hidden');
            document.getElementById('copy-btn').classList.add('hidden');
        }
    }

    calculateSimilarity(str1, str2) {
        if (!str1 || !str2) return 0;

        const longer = str1.length > str2.length ? str1 : str2;
        const shorter = str1.length > str2.length ? str2 : str1;

        if (longer.length === 0) return 1.0;

        const editDistance = this.levenshteinDistance(longer, shorter);
        return (longer.length - editDistance) / longer.length;
    }

    levenshteinDistance(str1, str2) {
        const matrix = [];

        for (let i = 0; i <= str2.length; i++) {
            matrix[i] = [i];
        }

        for (let j = 0; j <= str1.length; j++) {
            matrix[0][j] = j;
        }

        for (let i = 1; i <= str2.length; i++) {
            for (let j = 1; j <= str1.length; j++) {
                if (str2.charAt(i - 1) === str1.charAt(j - 1)) {
                    matrix[i][j] = matrix[i - 1][j - 1];
                } else {
                    matrix[i][j] = Math.min(
                        matrix[i - 1][j - 1] + 1,
                        matrix[i][j - 1] + 1,
                        matrix[i - 1][j] + 1
                    );
                }
            }
        }

        return matrix[str2.length][str1.length];
    }

    clearOutputWithTransition() {
        const outputDiv = document.getElementById('output');
        const tweakBtn = document.getElementById('tweak-btn');
        const copyBtn = document.getElementById('copy-btn');

        // Add fade-out class
        outputDiv.style.opacity = '0';
        outputDiv.style.transition = 'opacity 0.2s ease-out';

        setTimeout(() => {
            // Clear output and show ready state
            outputDiv.innerHTML = '';

            // Hide tweak and copy buttons
            tweakBtn.classList.add('hidden');
            copyBtn.classList.add('hidden');

            // Fade back in
            setTimeout(() => {
                outputDiv.style.opacity = '1';
                outputDiv.style.transition = 'opacity 0.3s ease-in';
            }, 50);
        }, 200);
    }

    /* ===================================================================
       PROMPT SUBMISSION & PROCESSING
       =================================================================== */

    async submitPrompt() {
        const promptInput = document.getElementById('prompt-input');
        const outputDiv = document.getElementById('output');
        const submitBtn = document.getElementById('submit-btn');
        const cancelBtn = document.getElementById('cancel-btn');
        const questionMode = document.getElementById('question-mode').value;
        const style = document.getElementById('style-select')?.value || 'default';

        const prompt = promptInput.value.trim();
        if (!prompt) {
            this.showMessage('error', 'Please enter a prompt');
            return;
        }

        const provider = document.getElementById('provider-select').value;
        let model = document.getElementById('model-select')?.value || null;

        // Don't send the "load all models" placeholder as an actual model
        if (model === '__load_all__') {
            model = null; // Let backend use auto/default model
        }

        // Determine skip_questions and force_questions from mode
        const skipQuestions = questionMode === 'skip';
        const forceQuestions = questionMode === 'force';

        // Cancel any existing request
        if (this.currentAbortController) {
            this.currentAbortController.abort();
        }

        // Create new AbortController
        this.currentAbortController = new AbortController();

        // Show loading state - keep button visible at top
        submitBtn.disabled = true;
        submitBtn.innerHTML = '<span class="spinner"></span><span>Processing...</span>';
        cancelBtn.classList.remove('hidden');

        try {
            // Check if clarifying questions are needed
            if (!skipQuestions) {
                // Show analyzing indicator while generating questions
                this.showProgressIndicator('analyzing');

                    const questionsResponse = await fetch(`${this.apiBaseUrl}/api/questions/generate`, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({
                            prompt,
                            provider: provider || null,
                            model: model || null,
                            force_questions: forceQuestions
                        }),
                        signal: this.currentAbortController.signal
                    });

                if (this.currentAbortController.signal.aborted) return;

                const questionsData = await questionsResponse.json();

                if (this.currentAbortController.signal.aborted) return;

                if (questionsData.success && questionsData.questions && questionsData.questions.length > 0) {
                    const answersResult = await this.showQuestionsAndCollectAnswers(questionsData.questions);

                    if (answersResult === null) {
                        submitBtn.disabled = false;
                        submitBtn.innerHTML = '<span>Optimize Prompt</span>';
                        cancelBtn.classList.add('hidden');
                        return;
                    }

                    const { responses, mapping } = answersResult;

                    // Show refining indicator
                    this.showProgressIndicator('refining');

                    // Submit with answers
                    const response = await fetch(`${this.apiBaseUrl}/api/prompt/submit`, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({
                            prompt,
                            provider: provider || null,
                            model: model || null,
                            skip_questions: false,
                            refine: forceQuestions,
                            style,
                            answers: responses,
                            question_mapping: mapping
                        }),
                        signal: this.currentAbortController.signal
                    });

                    if (this.currentAbortController.signal.aborted) return;

                    const data = await response.json();
                    this.handlePromptResponse(data);
                } else {
                    await this.submitPromptDirect(prompt, provider, skipQuestions, forceQuestions, style);
                }
            } else {
                await this.submitPromptDirect(prompt, provider, skipQuestions, forceQuestions, style);
            }
        } catch (error) {
            if (error.name === 'AbortError') return;
            console.error('Error submitting prompt:', error);
            this.showMessage('error', 'Network error: ' + error.message);
        } finally {
            this.currentAbortController = null;
            submitBtn.disabled = false;
            submitBtn.innerHTML = '<span>Optimize Prompt</span>';
            cancelBtn.classList.add('hidden');
        }
    }

    async submitPromptDirect(prompt, provider, skipQuestions, forceQuestions = false, style = 'default') {
        const outputDiv = document.getElementById('output');
        const tweakBtn = document.getElementById('tweak-btn');
        const copyBtn = document.getElementById('copy-btn');
        let model = document.getElementById('model-select')?.value || null;

        // Don't send the "load all models" placeholder as an actual model
        if (model === '__load_all__') {
            model = null; // Let backend use auto/default model
        }

        // Use streaming endpoint
        const params = new URLSearchParams({
            prompt,
            skip_questions: skipQuestions,
            refine: forceQuestions,
            style
        });

        if (provider) params.append('provider', provider);
        if (model) params.append('model', model);

        // Show optimizing indicator briefly before streaming
        this.showProgressIndicator(forceQuestions ? 'refining' : 'optimizing');

        // Small delay to let the progress indicator display
        await new Promise(resolve => setTimeout(resolve, 200));

        this.streamingText = '';
        outputDiv.innerHTML = '<div class="optimized-prompt-content streaming"><span class="streaming-cursor">|</span></div>';

        const eventSource = new EventSource(`${this.apiBaseUrl}/api/prompt/stream?${params.toString()}`);
        this.currentEventSource = eventSource;

        const contentDiv = outputDiv.querySelector('.optimized-prompt-content');
        const cursorSpan = contentDiv.querySelector('.streaming-cursor');

        eventSource.onmessage = (event) => {
            const data = JSON.parse(event.data);

            if (data.type === 'token') {
                this.streamingText += data.content;
                contentDiv.textContent = this.streamingText;
                contentDiv.appendChild(cursorSpan);
            } else if (data.type === 'done') {
                eventSource.close();
                this.currentEventSource = null;
                cursorSpan.remove();
                contentDiv.classList.remove('streaming');
                this.currentOptimizedPrompt = this.streamingText; // Store for markdown toggle
                tweakBtn.classList.remove('hidden'); // Show tweak button
                copyBtn.classList.remove('hidden'); // Show copy button
                this.showResultsState(); // Show contextual results state
                this.loadHistory();
            } else if (data.type === 'error') {
                eventSource.close();
                this.currentEventSource = null;
                tweakBtn.classList.add('hidden');
                copyBtn.classList.add('hidden');

                // Check if this is an API key related error and add settings link
                if (data.content && (
                    data.content.toLowerCase().includes('api key') ||
                    data.content.toLowerCase().includes('missing') ||
                    data.content.toLowerCase().includes('unauthorized') ||
                    data.content.toLowerCase().includes('authentication')
                )) {
                    this.showMessageWithSettings(data.content, 'error');
                } else {
                    this.showMessage('error', data.content);
                }
            }
        };

        eventSource.onerror = (error) => {
            console.error('EventSource error:', error);
            eventSource.close();
            this.currentEventSource = null;

            if (!this.streamingText) {
                this.showMessage('error', 'Streaming connection failed');
            } else {
                cursorSpan.remove();
                contentDiv.classList.remove('streaming');
            }
        };
    }

    handlePromptResponse(data) {
        const outputDiv = document.getElementById('output');
        const tweakBtn = document.getElementById('tweak-btn');
        const copyBtn = document.getElementById('copy-btn');

        if (data.success) {
            this.currentOptimizedPrompt = data.refined_prompt;
            this.renderOutput();
            tweakBtn.classList.remove('hidden'); // Show tweak button
            copyBtn.classList.remove('hidden'); // Show copy button
            this.showResultsState(); // Show contextual results state
            this.loadHistory();
        } else {
            this.showMessage('error', data.error || 'Failed to process prompt');
            tweakBtn.classList.add('hidden');
            copyBtn.classList.add('hidden');
        }
    }

    renderOutput() {
        const outputDiv = document.getElementById('output');

        // Remove redundant "Optimized Prompt" heading if present
        let cleanedPrompt = this.currentOptimizedPrompt.trim();

        // Remove common redundant headings
        const redundantHeadings = [
            /^#\s*Optimized Prompt\s*\n+/i,
            /^##\s*Optimized Prompt\s*\n+/i,
            /^\*\*Optimized Prompt\*\*\s*\n+/i,
            /^Optimized Prompt:\s*\n+/i
        ];

        for (const pattern of redundantHeadings) {
            cleanedPrompt = cleanedPrompt.replace(pattern, '');
        }

        // Enhanced plain text rendering with selective formatting
        const formattedText = this.formatEnhancedText(cleanedPrompt);
        outputDiv.innerHTML = `<div class="optimized-prompt-content">${formattedText}</div>`;
    }

    formatEnhancedText(text) {
        // Escape HTML first
        let formatted = this.escapeHtml(text);

        // Convert **bold** to <strong>
        formatted = formatted.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');

        // Convert *italic* to <em>
        formatted = formatted.replace(/\*(.+?)\*/g, '<em>$1</em>');

        // Convert `inline code` to <code>
        formatted = formatted.replace(/`([^`]+)`/g, '<code>$1</code>');

        // Preserve line breaks
        formatted = formatted.replace(/\n/g, '<br>');

        return formatted;
    }

    async showQuestionsAndCollectAnswers(questions) {
        const outputDiv = document.getElementById('output');
        const submitBtn = document.getElementById('submit-btn');

        let currentQuestionIndex = 0;
        const answers = {};
        const questionMapping = {};

        const renderQuestion = (index) => {
            const question = questions[index];
            const questionKey = `q${index}`;
            const questionText = question.question || `Question ${index + 1}`;
            const questionType = question.type || 'text';
            const required = question.required !== false;
            const isLastQuestion = index === questions.length - 1;

            questionMapping[questionKey] = questionText;

            let formHtml = '<div class="question-wizard">';

            // Progress dots
            formHtml += '<div class="wizard-progress">';
            for (let i = 0; i < questions.length; i++) {
                formHtml += `<span class="progress-dot ${i === index ? 'active' : ''} ${i < index ? 'completed' : ''}"></span>`;
            }
            formHtml += '</div>';

            // Question content
            formHtml += '<div class="wizard-content">';
            formHtml += `<div class="wizard-question-number">Question ${index + 1} of ${questions.length}</div>`;
            formHtml += `<h3 class="wizard-question-text">${this.escapeHtml(questionText)}${required ? ' <span style="color: var(--color-primary);">*</span>' : ''}</h3>`;

            formHtml += '<form id="wizard-form">';
            formHtml += '<div class="wizard-input-container">';

            if (questionType === 'radio' && question.options && question.options.length > 0) {
                question.options.forEach((option, optIndex) => {
                    formHtml += `<label class="wizard-option">`;
                    formHtml += `<input type="radio" name="${questionKey}" value="${this.escapeHtml(option)}" ${optIndex === 0 ? 'checked' : ''}>`;
                    formHtml += `<span class="wizard-option-text">${this.escapeHtml(option)}</span>`;
                    formHtml += `</label>`;
                });
            } else if (questionType === 'checkbox' && question.options && question.options.length > 0) {
                question.options.forEach((option, optIndex) => {
                    formHtml += `<label class="wizard-option">`;
                    formHtml += `<input type="checkbox" name="${questionKey}" value="${this.escapeHtml(option)}">`;
                    formHtml += `<span class="wizard-option-text">${this.escapeHtml(option)}</span>`;
                    formHtml += `</label>`;
                });
            } else {
                const savedAnswer = answers[questionKey] || '';
                const placeholder = required ? "Type your answer here..." : "Optional - Leave blank to skip";
                formHtml += `<textarea id="${questionKey}" name="${questionKey}" ${required ? 'required' : ''} class="wizard-input" placeholder="${placeholder}" rows="4">${this.escapeHtml(savedAnswer)}</textarea>`;
            }

            formHtml += '</div>'; // wizard-input-container

            // Navigation buttons
            formHtml += '<div class="wizard-actions">';

            if (index > 0) {
                formHtml += '<button type="button" id="wizard-prev-btn" class="btn btn-secondary">';
                formHtml += '<span>← Previous</span>';
                formHtml += '</button>';
            } else {
                formHtml += '<div></div>'; // Spacer
            }

            if (!required) {
                formHtml += '<button type="button" id="wizard-skip-btn" class="btn btn-tertiary">';
                formHtml += '<span>Skip</span>';
                formHtml += '</button>';
            }

            if (isLastQuestion) {
                formHtml += '<button type="submit" class="btn btn-primary">';
                formHtml += '<span>Submit Answers</span>';
                formHtml += '</button>';
            } else {
                formHtml += '<button type="submit" class="btn btn-primary">';
                formHtml += '<span>Next →</span>';
                formHtml += '</button>';
            }

            formHtml += '</div>'; // wizard-actions
            formHtml += '</form>';
            formHtml += '</div>'; // wizard-content

            // Cancel button
            formHtml += '<button type="button" id="wizard-cancel-btn" class="wizard-cancel-btn" title="Cancel">✕</button>';

            formHtml += '</div>'; // question-wizard

            outputDiv.innerHTML = formHtml;

            // Focus the input
            const firstInput = outputDiv.querySelector('input, textarea');
            if (firstInput && firstInput.type !== 'radio' && firstInput.type !== 'checkbox') {
                setTimeout(() => firstInput.focus(), 100);
            }
        };

        return new Promise((resolve) => {
            const handleNext = (form) => {
                const question = questions[currentQuestionIndex];
                const questionKey = `q${currentQuestionIndex}`;
                const questionType = question.type || 'text';

                // Collect answer
                if (questionType === 'checkbox') {
                    const checkboxes = form.querySelectorAll(`input[name="${questionKey}"]:checked`);
                    answers[questionKey] = Array.from(checkboxes).map(cb => cb.value);
                } else if (questionType === 'radio') {
                    const radio = form.querySelector(`input[name="${questionKey}"]:checked`);
                    answers[questionKey] = radio ? radio.value : '';
                } else {
                    const input = form.querySelector(`[name="${questionKey}"]`);
                    answers[questionKey] = input ? input.value : '';
                }

                // Move to next question or finish
                if (currentQuestionIndex < questions.length - 1) {
                    currentQuestionIndex++;
                    renderQuestion(currentQuestionIndex);
                    attachEventListeners();
                } else {
                    // All questions answered
                    submitBtn.innerHTML = '<span class="spinner"></span><span>Generating optimized prompt...</span>';
                    this.showProgressIndicator('optimizing');
                    resolve({ responses: answers, mapping: questionMapping });
                }
            };

            const handlePrevious = () => {
                if (currentQuestionIndex > 0) {
                    currentQuestionIndex--;
                    renderQuestion(currentQuestionIndex);
                    attachEventListeners();
                }
            };

            const handleSkip = () => {
                const questionKey = `q${currentQuestionIndex}`;
                answers[questionKey] = '';

                if (currentQuestionIndex < questions.length - 1) {
                    currentQuestionIndex++;
                    renderQuestion(currentQuestionIndex);
                    attachEventListeners();
                } else {
                    submitBtn.innerHTML = '<span class="spinner"></span><span>Generating optimized prompt...</span>';
                    this.showProgressIndicator('optimizing');
                    resolve({ responses: answers, mapping: questionMapping });
                }
            };

            const handleCancel = () => {
                this.cancelCurrentRequest();
                resolve(null);
            };

            const attachEventListeners = () => {
                const form = document.getElementById('wizard-form');
                const prevBtn = document.getElementById('wizard-prev-btn');
                const skipBtn = document.getElementById('wizard-skip-btn');
                const cancelBtn = document.getElementById('wizard-cancel-btn');

                if (form) {
                    form.addEventListener('submit', (e) => {
                        e.preventDefault();
                        handleNext(form);
                    });
                }

                if (prevBtn) {
                    prevBtn.addEventListener('click', handlePrevious);
                }

                if (skipBtn) {
                    skipBtn.addEventListener('click', handleSkip);
                }

                if (cancelBtn) {
                    cancelBtn.addEventListener('click', handleCancel);
                }

                // Enter key to submit
                const textInput = form?.querySelector('textarea');
                if (textInput) {
                    textInput.addEventListener('keydown', (e) => {
                        if (e.key === 'Enter' && e.ctrlKey) {
                            e.preventDefault();
                            form.dispatchEvent(new Event('submit'));
                        }
                    });
                }
            };

            // Render first question
            renderQuestion(currentQuestionIndex);
            attachEventListeners();
        });
    }

    cancelCurrentRequest() {
        if (this.currentAbortController) {
            this.currentAbortController.abort();
            this.currentAbortController = null;
        }

        if (this.currentEventSource) {
            this.currentEventSource.close();
            this.currentEventSource = null;
        }

        const submitBtn = document.getElementById('submit-btn');
        const cancelBtn = document.getElementById('cancel-btn');
        const outputDiv = document.getElementById('output');

        if (submitBtn) {
            submitBtn.disabled = false;
            submitBtn.innerHTML = '<span>Optimize Prompt</span>';
        }
        if (cancelBtn) {
            cancelBtn.classList.add('hidden');
        }
        if (outputDiv) {
            this.showMessage('info', 'Request cancelled');
        }
    }

    /* ===================================================================
       PROVIDERS MANAGEMENT
       =================================================================== */

    updateModelCacheInfo(timestamp) {
        const el = document.getElementById('model-cache-info');
        if (!el) return;
        if (!timestamp) {
            el.textContent = 'Models last updated: --';
        } else {
            el.textContent = `Models last updated: ${new Date(timestamp).toLocaleString()}`;
        }
    }

    updateCapabilitiesInfo(providerId) {
        const el = document.getElementById('provider-capabilities');
        if (!el) return;
        const caps = this.providerCapabilities?.[providerId] || {};
        if (!Object.keys(caps).length) {
            el.textContent = 'Capabilities: --';
            return;
        }
        const parts = [];
        if (caps.supports_json) parts.push('JSON mode');
        if (caps.supports_tools) parts.push('Tools');
        if (caps.supports_vision) parts.push('Vision');
        if (caps.max_output_tokens) parts.push(`Max output tokens: ${caps.max_output_tokens}`);
        el.textContent = `Capabilities: ${parts.join(', ') || '--'}`;
    }

    async loadProviders() {
        try {
            const response = await fetch(`${this.apiBaseUrl}/api/providers`);
            const data = await response.json();

            // Invalidate any stale preflight cache
            this.clearProviderStatusCache();

            // Cache capabilities and cache timestamp
            this.providerCapabilities = {};
            data.available_providers.forEach(p => {
                this.providerCapabilities[p.id] = p.capabilities || {};
                // Cache models for all providers from the initial load
                if (p.models && p.models.length > 0) {
                    this.cachedModels[p.id] = {
                        models: p.models,
                        current_model: p.id === data.current_provider ? data.current_model : p.default_model,
                        fetchedAll: false
                    };
                }
            });
            this.updateCapabilitiesInfo(data.current_provider);
            this.updateModelCacheInfo(data.cache_last_updated);

            // Update cache timestamp in Settings panel
            const cacheTimestampEl = document.getElementById('cache-timestamp-settings');
            if (cacheTimestampEl && data.cache_last_updated) {
                const cacheDate = new Date(data.cache_last_updated);
                cacheTimestampEl.textContent = `Last updated: ${this.formatTimestamp(cacheDate)}`;
            }

        // Update provider select dropdown
        const providerSelect = document.getElementById('provider-select');
        providerSelect.innerHTML = '<option value="">Auto</option>';

            // Sort providers alphabetically by name for consistent ordering
            const sortedProviders = [...data.available_providers].sort((a, b) => a.name.localeCompare(b.name));

            sortedProviders.forEach(provider => {
                const option = document.createElement('option');
                option.value = provider.id;
                option.textContent = provider.name;
                option.selected = provider.id === data.current_provider;

                // Add status indicator based on availability (no implicit preflight)
                if (provider.available) {
                    option.setAttribute('data-status', 'configured');
                    option.setAttribute('title', `${provider.name} - Ready`);
                } else {
                    option.setAttribute('data-status', 'unconfigured');
                    option.setAttribute('title', `${provider.name} - Needs API key`);
                }

                providerSelect.appendChild(option);
            });

            // Update mobile provider dropdown
            const providerSelectMobile = document.getElementById('provider-select-mobile');
            if (providerSelectMobile) {
                providerSelectMobile.innerHTML = '<option value="">Auto</option>';
                sortedProviders.forEach(provider => {
                    const option = document.createElement('option');
                    option.value = provider.id;
                    option.textContent = provider.name;
                    option.selected = provider.id === data.current_provider;

                    // Add status indicator based on availability
                    if (provider.available) {
                        option.setAttribute('data-status', 'configured');
                        option.setAttribute('title', `${provider.name} - Ready`);
                    } else {
                        option.setAttribute('data-status', 'unconfigured');
                        option.setAttribute('title', `${provider.name} - Needs API key`);
                    }

                    providerSelectMobile.appendChild(option);
                });
            }

            // Load models for current provider
            if (data.current_provider) {
                await this.loadModelsForProvider(data.current_provider);
            }
        } catch (error) {
            console.error('Error loading providers:', error);
            this.showMessage('error', 'Failed to load providers');
        }
    }

    async refreshModelsCache(providerId) {
        try {
            this.showToast('info', 'Refreshing model cache...');
            const resp = await fetch(`${this.apiBaseUrl}/api/providers/cache/refresh`, {
                method: 'POST'
            });
            const data = await resp.json();
            if (resp.ok) {
                this.updateModelCacheInfo(data.cache_last_updated);

                // Update cache timestamp in Settings panel
                const cacheTimestampEl = document.getElementById('cache-timestamp-settings');
                if (cacheTimestampEl && data.cache_last_updated) {
                    const cacheDate = new Date(data.cache_last_updated);
                    cacheTimestampEl.textContent = `Last updated: ${this.formatTimestamp(cacheDate)}`;
                }

                if (providerId) {
                    await this.loadModelsForProvider(providerId, true);
                }
                this.showToast('success', 'Model cache refreshed');
            } else {
                this.showToast('error', data.detail || 'Failed to refresh cache');
            }
        } catch (error) {
            console.error('Error refreshing model cache:', error);
            this.showToast('error', 'Failed to refresh cache');
        }
    }

    async runProviderPreflight() {
        try {
            // Clear cache to force fresh validation
            this.clearProviderStatusCache();

            // Show persistent loading state in the table
            const tbody = document.getElementById('provider-status-tbody');
            if (tbody) {
                tbody.innerHTML = `
                    <tr>
                        <td colspan="4" style="text-align: center; padding: var(--space-6);">
                            <div class="progress-indicator">
                                <div class="progress-symbol">⚗</div>
                                <div class="progress-text">Validating all providers...</div>
                            </div>
                        </td>
                    </tr>
                `;
            }

            this.showToast('info', 'Validating providers...');
            const resp = await fetch(`${this.apiBaseUrl}/api/providers/preflight`);
            const data = await resp.json();
            if (!resp.ok) {
                this.showToast('error', data.detail || 'Validation failed');
                // Clear loading state
                if (tbody) tbody.innerHTML = '';
                return;
            }

            // Cache the validation results with timestamp
            const cacheData = {
                results: data,
                timestamp: Date.now()
            };
            localStorage.setItem('promptheus_validation_cache', JSON.stringify(cacheData));

            // Also cache provider status for dropdown indicators
            this.cacheProviderStatus(data);

            // Update the provider status table in Settings panel
            this.updateProviderStatusTable(data);

            // Update the status dot based on results
            this.updateSystemStatus(data);

            // Only count actual errors, not missing keys (which is expected)
            const errors = data.filter(r => r.status === 'error');
            const configured = data.filter(r => r.status === 'ok').length;

            if (errors.length) {
                this.showToast('error', `${errors.length} configured provider(s) failed validation`);
            } else if (configured > 0) {
                this.showToast('success', `${configured} provider(s) validated successfully`);
            } else {
                this.showToast('info', 'No providers configured yet');
            }
        } catch (error) {
            console.error('Preflight error:', error);
            this.showToast('error', 'Validation failed');
            // Clear loading state
            const tbody = document.getElementById('provider-status-tbody');
            if (tbody) tbody.innerHTML = '';
        }
    }

    loadCachedValidationResults() {
        try {
            const cached = localStorage.getItem('promptheus_validation_cache');
            if (!cached) return false;

            const cacheData = JSON.parse(cached);
            const age = Date.now() - cacheData.timestamp;
            const oneHour = 60 * 60 * 1000;

            // Expire after 1 hour
            if (age > oneHour) {
                localStorage.removeItem('promptheus_validation_cache');
                return false;
            }

            // Update the table with cached results
            this.updateProviderStatusTable(cacheData.results);
            this.updateSystemStatus(cacheData.results);

            // Show age of cached data
            const ageMinutes = Math.floor(age / 60000);
            const ageText = ageMinutes < 1 ? 'just now' :
                           ageMinutes === 1 ? '1 minute ago' :
                           `${ageMinutes} minutes ago`;

            // Add cache indicator to the table
            const tbody = document.getElementById('provider-status-tbody');
            if (tbody && tbody.querySelector('tr')) {
                const indicator = document.createElement('tr');
                indicator.className = 'cache-indicator-row';
                indicator.innerHTML = `
                    <td colspan="4" style="text-align: center; padding: var(--space-2); font-size: var(--text-xs); color: var(--text-tertiary); font-style: italic;">
                        Cached results from ${ageText}
                    </td>
                `;
                tbody.insertBefore(indicator, tbody.firstChild);
            }

            return true;
        } catch (error) {
            console.error('Error loading cached validation:', error);
            return false;
        }
    }

    updateProviderStatusTable(results) {
        const tbody = document.getElementById('provider-status-tbody');
        if (!tbody) return;

        tbody.innerHTML = '';

        results.forEach(result => {
            const row = document.createElement('tr');

            // Provider name
            const nameCell = document.createElement('td');
            nameCell.textContent = result.display_name;
            row.appendChild(nameCell);

            // Status
            const statusCell = document.createElement('td');
            const statusIcon = result.status === 'ok' ? '✓' :
                               result.status === 'missing_key' ? '⚠' : '✗';
            const statusColor = result.status === 'ok' ? 'var(--color-success)' :
                                result.status === 'missing_key' ? 'var(--color-warning)' :
                                'var(--color-error)';
            statusCell.innerHTML = `<span style="color: ${statusColor}; font-weight: var(--font-semibold);">${statusIcon} ${result.message || result.status}</span>`;
            row.appendChild(statusCell);

            // Models count (only for successful validations)
            const modelsCell = document.createElement('td');
            if (result.status === 'ok') {
                // Fetch model count from cached data
                const providerId = result.provider_id;
                const cachedData = this.cachedModels[providerId];
                if (cachedData && cachedData.models) {
                    modelsCell.textContent = `${cachedData.models.length} models`;
                } else {
                    modelsCell.textContent = '--';
                }
            } else {
                modelsCell.textContent = '--';
            }
            row.appendChild(modelsCell);

            // Updated timestamp
            const timeCell = document.createElement('td');
            if (result.duration_ms) {
                timeCell.textContent = `${result.duration_ms}ms`;
                timeCell.style.fontFamily = 'var(--font-mono)';
                timeCell.style.fontSize = 'var(--text-xs)';
            } else {
                timeCell.textContent = 'Just now';
            }
            row.appendChild(timeCell);

            tbody.appendChild(row);
        });

        // Update cache timestamp in Settings panel
        const cacheTimestampEl = document.getElementById('cache-timestamp-settings');
        if (cacheTimestampEl) {
            cacheTimestampEl.textContent = `Last validated: ${this.formatTimestamp(new Date())}`;
        }
    }

    updateSystemStatus(results) {
        const statusBtn = document.getElementById('provider-status-btn');
        const statusDot = statusBtn?.querySelector('.status-dot');
        if (!statusDot) return;

        const hasErrors = results.some(r => r.status === 'error');
        const hasConfigured = results.some(r => r.status === 'ok');

        // Remove all status classes
        statusDot.classList.remove('status-ok', 'status-warning', 'status-error');

        // Add appropriate status class
        // Only show error if configured providers have actual errors
        if (hasErrors) {
            statusDot.classList.add('status-error');
            statusBtn.title = 'Configured providers have errors - click to view details';
        } else if (hasConfigured) {
            statusDot.classList.add('status-ok');
            statusBtn.title = 'All configured providers working';
        } else {
            // No providers configured - show neutral/info state
            statusDot.classList.add('status-ok');
            statusBtn.title = 'All systems operational';
        }
    }

    /**
     * Show sync indicator briefly to indicate mobile/main dropdown sync
     * @param {string} indicatorId - ID of the sync indicator element
     */
    showSyncIndicator(indicatorId) {
        const indicator = document.getElementById(indicatorId);
        if (!indicator) return;

        indicator.classList.add('active');
        setTimeout(() => {
            indicator.classList.remove('active');
        }, 600); // Match animation duration
    }

    formatTimestamp(date) {
        const now = new Date();
        const diffMs = now - date;
        const diffSec = Math.floor(diffMs / 1000);
        const diffMin = Math.floor(diffSec / 60);
        const diffHour = Math.floor(diffMin / 60);
        const diffDay = Math.floor(diffHour / 24);

        if (diffSec < 60) return 'Just now';
        if (diffMin < 60) return `${diffMin}m ago`;
        if (diffHour < 24) return `${diffHour}h ago`;
        if (diffDay < 7) return `${diffDay}d ago`;

        return date.toLocaleDateString(undefined, {
            month: 'short',
            day: 'numeric',
            hour: '2-digit',
            minute: '2-digit'
        });
    }

    async selectProvider(providerId) {
        try {
            const payloadId = providerId || "";

            if (!payloadId) {
                const modelSelect = document.getElementById('model-select');
                if (modelSelect) {
                    modelSelect.innerHTML = '<option value="">Auto</option>';
                    modelSelect.disabled = true;
                }
            }

            const response = await fetch(`${this.apiBaseUrl}/api/providers/select`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ provider_id: payloadId })
            });

            const data = await response.json();

            if (response.ok) {
                if (payloadId === "") {
                    this.showToast('success', 'Provider reset to auto-detect');
                } else {
                    this.showToast('success', `Provider changed to ${data.current_provider}${data.available === false ? ' (key not set yet)' : ''}`);
                }
                // Persist selection in UI/state and reload models
                const providerSelect = document.getElementById('provider-select');
                if (providerSelect) {
                    providerSelect.value = payloadId;
                }
                this.provider = payloadId || '';
                await this.loadModelsForProvider(payloadId || data.current_provider || '');
                this.updateCapabilitiesInfo(payloadId || data.current_provider || this.provider);
            } else {
                this.showToast('error', data.detail || 'Failed to change provider');
            }
        } catch (error) {
            console.error('Error selecting provider:', error);
            this.showToast('error', 'Network error: ' + error.message);
        }
    }

    async loadModelsForProvider(providerId, fetchAll = false) {
        if (!providerId) {
            const modelSelect = document.getElementById('model-select');
            if (modelSelect) {
                modelSelect.innerHTML = '<option value="">Auto</option>';
                modelSelect.disabled = true;
            }

            // Sync mobile model dropdown using helper
            this.syncMobileModelDropdown(null, null, true);
            return;
        }

        const modelSelect = document.getElementById('model-select');
        if (!modelSelect) return;

        try {
            // Check if we have cached models for this provider
            if (this.cachedModels[providerId] && !fetchAll) {
                const cachedData = this.cachedModels[providerId];
                const hasCachedModels = Array.isArray(cachedData.models) && cachedData.models.length > 0;

                // Do not stick to an empty cache; allow a refetch after transient failures
                if (!hasCachedModels) {
                    delete this.cachedModels[providerId];
                } else {
                    modelSelect.disabled = false;
                    this.populateModelSelect(modelSelect, cachedData.models, cachedData.current_model, cachedData.fetchedAll || false);
                    return;
                }
            }

            // Show loading state if fetching all models
            if (fetchAll) {
                modelSelect.disabled = true;
                modelSelect.innerHTML = '<option>Loading all models...</option>';
            }

            const url = fetchAll
                ? `${this.apiBaseUrl}/api/providers/${providerId}/models?fetch_all=true`
                : `${this.apiBaseUrl}/api/providers/${providerId}/models`;

            const response = await fetch(url);
            const data = await response.json();

            this.updateModelCacheInfo(data.cache_last_updated || data.cacheLastUpdated);
            this.updateCapabilitiesInfo(providerId);

            // Cache the models for this provider
            if (fetchAll && data.models && data.models.length > 0) {
                this.cachedModels[providerId] = {
                    models: data.models,
                    current_model: data.current_model,
                    fetchedAll: true
                };
            }

            modelSelect.innerHTML = '';
            modelSelect.disabled = false;

            this.populateModelSelect(modelSelect, data.models, data.current_model, fetchAll);

            // Show toast notification if we loaded all models
            if (fetchAll && data.models && data.models.length > 0) {
                this.showToast('success', `Loaded ${data.models.length} models for ${providerId}`);
            }
        } catch (error) {
            console.error('Error loading models:', error);
            modelSelect.innerHTML = '<option value="">Error loading models</option>';
            modelSelect.disabled = false;
            this.showToast('error', 'Failed to load models');
        }
    }

    /**
     * Helper method to sync mobile model dropdown with main dropdown
     * @param {Array} models - Array of model names
     * @param {string} currentModel - Currently selected model
     * @param {boolean} disabled - Whether dropdown should be disabled
     */
    syncMobileModelDropdown(models, currentModel, disabled = false) {
        const modelSelectMobile = document.getElementById('model-select-mobile');
        if (!modelSelectMobile) return;

        modelSelectMobile.innerHTML = '';

        if (models && models.length > 0) {
            models.forEach((model, index) => {
                const option = document.createElement('option');
                option.value = model;
                option.textContent = model;

                // Select current model if set, otherwise select first model
                if (currentModel) {
                    option.selected = model === currentModel;
                } else if (index === 0) {
                    option.selected = true;
                }

                modelSelectMobile.appendChild(option);
            });
            modelSelectMobile.disabled = disabled;
        } else {
            const emptyOption = document.createElement('option');
            emptyOption.value = '';
            emptyOption.textContent = models === null ? 'Auto' : 'No models available';
            modelSelectMobile.appendChild(emptyOption);
            modelSelectMobile.disabled = true;
        }
    }

    populateModelSelect(modelSelect, models, currentModel, fetchedAll) {
        modelSelect.innerHTML = '';

        // If we got models, populate them
        if (models && models.length > 0) {
            models.forEach((model, index) => {
                const option = document.createElement('option');
                option.value = model;
                option.textContent = model;

                // Select current model if set, otherwise select first model
                if (currentModel) {
                    option.selected = model === currentModel;
                } else if (index === 0) {
                    option.selected = true;
                }

                modelSelect.appendChild(option);
            });

            // Sync mobile model dropdown using helper
            this.syncMobileModelDropdown(models, currentModel, false);
        } else {
            // No models found
            const emptyOption = document.createElement('option');
            emptyOption.value = '';
            emptyOption.textContent = 'No models available';
            modelSelect.appendChild(emptyOption);

            // Sync mobile model dropdown using helper
            this.syncMobileModelDropdown([], currentModel, true);
        }

        // Append the "Load All Models" option last so real models stay primary
        if (!fetchedAll && models && models.length > 0) {
            const loadAllOption = document.createElement('option');
            loadAllOption.value = '__load_all__';
            loadAllOption.textContent = '↻ Load All Models...';
            loadAllOption.style.fontStyle = 'italic';
            loadAllOption.style.color = 'var(--text-secondary)';
            modelSelect.appendChild(loadAllOption);
        }
    }

    async selectModel(model) {
        const providerId = document.getElementById('provider-select').value;

        if (!providerId || !model) return;

        // Check if user selected "Load All Models"
        if (model === '__load_all__') {
            await this.loadModelsForProvider(providerId, true);
            return;
        }

        try {
            const response = await fetch(`${this.apiBaseUrl}/api/providers/select-model`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    provider_id: providerId,
                    model: model
                })
            });

            const data = await response.json();

            if (response.ok) {
                this.showToast('success', `Model changed to ${data.current_model}`);
            } else {
                this.showToast('error', data.detail || 'Failed to change model');
            }
        } catch (error) {
            console.error('Error selecting model:', error);
            this.showToast('error', 'Network error: ' + error.message);
        }
    }

    /* ===================================================================
       HISTORY MANAGEMENT
       =================================================================== */

    async loadHistory() {
        try {
            const offset = this.currentHistoryPage * this.currentPageSize;
            const response = await fetch(`${this.apiBaseUrl}/api/history?limit=${this.currentPageSize}&offset=${offset}`);
            const data = await response.json();

            const historyList = document.getElementById('history-list');
            historyList.innerHTML = '';

            if (data.entries.length === 0) {
                historyList.innerHTML = `
                    <div class="empty-state">
                        <div class="empty-state-icon">📜</div>
                        <div class="empty-state-title">No History Yet</div>
                        <div class="empty-state-description">Your optimized prompts will appear here</div>
                    </div>
                `;
                this.totalHistoryPages = 0;
                this.updateHistoryPagination();
                return;
            }

            this.totalHistoryPages = Math.ceil(data.total / this.currentPageSize);

            data.entries.forEach(entry => {
                const card = this.createHistoryCard(entry);
                historyList.appendChild(card);
            });

            this.updateHistoryPagination();
        } catch (error) {
            console.error('Error loading history:', error);
            this.showMessage('error', 'Failed to load history');
        }
    }

    createHistoryCard(entry) {
        const card = document.createElement('div');
        card.className = 'history-card';
        card.setAttribute('role', 'listitem');

        const timestamp = new Date(entry.timestamp).toLocaleString(undefined, {
            month: 'short',
            day: 'numeric',
            hour: '2-digit',
            minute: '2-digit'
        });

        const taskType = entry.task_type || 'general';
        const badgeClass = `badge-${taskType.toLowerCase()}`;

        card.innerHTML = `
            <div class="history-card-header">
                <div class="history-card-timestamp">${timestamp}</div>
                <span class="history-card-badge ${badgeClass}">${this.escapeHtml(taskType)}</span>
            </div>
            <div class="history-card-content">
                <div class="history-card-preview">${this.escapeHtml(entry.original_prompt)}</div>
            </div>
            <div class="history-card-footer">
                <div class="history-card-meta">${this.escapeHtml(entry.provider)} • ${this.escapeHtml(entry.model)}</div>
                <button class="history-card-delete" title="Delete this entry" data-timestamp="${entry.timestamp}">
                    🗑
                </button>
            </div>
        `;

        // Add delete button handler
        const deleteBtn = card.querySelector('.history-card-delete');
        deleteBtn.addEventListener('click', async (e) => {
            e.stopPropagation(); // Prevent card click event
            await this.deleteHistoryEntry(entry.timestamp);
        });

        card.addEventListener('click', () => {
            // Restore both input and output
            const promptInput = document.getElementById('prompt-input');
            const outputDiv = document.getElementById('output');
            const tweakBtn = document.getElementById('tweak-btn');
            const copyBtn = document.getElementById('copy-btn');

            // Set the input value
            promptInput.value = entry.original_prompt;

            // Restore the optimized output if available
            if (entry.refined_prompt) {
                this.currentOptimizedPrompt = entry.refined_prompt;
                this.renderOutput();
                tweakBtn.classList.remove('hidden');
                copyBtn.classList.remove('hidden');
                this.showResultsState(); // Show contextual results state
            }

            // Scroll to top to see the restored content
            window.scrollTo({ top: 0, behavior: 'smooth' });
        });

        return card;
    }

    previousHistoryPage() {
        if (this.currentHistoryPage > 0) {
            this.currentHistoryPage--;
            this.loadHistory();
        }
    }

    nextHistoryPage() {
        if (this.currentHistoryPage < this.totalHistoryPages - 1) {
            this.currentHistoryPage++;
            this.loadHistory();
        }
    }

    updateHistoryPagination() {
        const prevBtn = document.getElementById('prev-page-btn');
        const nextBtn = document.getElementById('next-page-btn');
        const currentPageSpan = document.getElementById('current-page');

        prevBtn.disabled = this.currentHistoryPage <= 0;
        nextBtn.disabled = this.currentHistoryPage >= this.totalHistoryPages - 1 || this.totalHistoryPages <= 1;

        const currentPageDisplay = this.currentHistoryPage + 1;
        const totalPagesDisplay = this.totalHistoryPages || 1;
        currentPageSpan.textContent = `${currentPageDisplay} of ${totalPagesDisplay}`;
    }

    async deleteHistoryEntry(timestamp) {
        try {
            const response = await fetch(`${this.apiBaseUrl}/api/history/${encodeURIComponent(timestamp)}`, {
                method: 'DELETE'
            });

            if (response.ok) {
                this.showToast('success', 'History entry deleted');
                this.loadHistory(); // Reload to refresh the list
            } else {
                this.showToast('error', 'Failed to delete history entry');
            }
        } catch (error) {
            console.error('Error deleting history entry:', error);
            this.showToast('error', 'Network error: ' + error.message);
        }
    }

    async clearHistory() {
        try {
            const response = await fetch(`${this.apiBaseUrl}/api/history`, {
                method: 'DELETE'
            });

            if (response.ok) {
                this.showToast('success', 'History cleared successfully');
                this.currentHistoryPage = 0;
                this.loadHistory();
            } else {
                this.showToast('error', 'Failed to clear history');
            }
        } catch (error) {
            console.error('Error clearing history:', error);
            this.showToast('error', 'Network error: ' + error.message);
        }
    }

    /* ===================================================================
       SETTINGS MANAGEMENT
       =================================================================== */

    async loadSettings() {
        try {
            const response = await fetch(`${this.apiBaseUrl}/api/settings`);
            const data = await response.json();

            const settingsForm = document.getElementById('settings-form');
            settingsForm.innerHTML = '';

            // Check if settings is an array
            if (!Array.isArray(data.settings)) {
                console.error('Settings is not an array:', data.settings);
                settingsForm.innerHTML = '<p style="color: var(--text-error);">Error: Invalid settings format</p>';
                return;
            }

            // Group settings by category
            const groupedSettings = {};
            data.settings.forEach(setting => {
                if (!groupedSettings[setting.category]) {
                    groupedSettings[setting.category] = [];
                }
                groupedSettings[setting.category].push(setting);
            });

            // Render each category
            Object.entries(groupedSettings).forEach(([category, settings]) => {
                // Skip provider category (handled in top bar)
                if (category === 'provider') return;

                // Only show API Keys and General sections
                if (category !== 'api_keys' && category !== 'general') return;

                // Create category section
                const categorySection = document.createElement('div');
                categorySection.className = 'settings-category';

                // Add special class and heading for categories
                if (category === 'general') {
                    categorySection.classList.add('general-settings');
                    const categoryHeading = document.createElement('h2');
                    categoryHeading.className = 'settings-category-heading';
                    categoryHeading.textContent = 'General';
                    categorySection.appendChild(categoryHeading);
                } else if (category === 'api_keys') {
                    categorySection.classList.add('api-keys-settings');
                    const categoryHeading = document.createElement('h2');
                    categoryHeading.className = 'settings-category-heading';
                    categoryHeading.textContent = 'API Keys';
                    categorySection.appendChild(categoryHeading);
                }

                // Render each setting in the category
                settings.forEach(setting => {
                    const item = document.createElement('div');
                    item.className = 'settings-item';

                    // Add special class for checkbox items
                    if (setting.type === 'checkbox') {
                        item.classList.add('checkbox-item');
                    }

                    const labelContainer = document.createElement('div');
                    labelContainer.className = 'settings-label-container';

                    const label = document.createElement('label');
                    label.className = 'settings-label';
                    label.textContent = setting.label;
                    label.htmlFor = `setting-${setting.key}`;

                    const description = document.createElement('p');
                    description.className = 'settings-description';
                    description.textContent = setting.description;

                    labelContainer.appendChild(label);
                    labelContainer.appendChild(description);

                    const inputContainer = document.createElement('div');
                    inputContainer.className = 'settings-input-container';

                    // Create input based on type
                    let inputElement;

                    if (setting.type === 'select') {
                        inputElement = document.createElement('select');
                        inputElement.className = 'settings-input';
                        setting.options.forEach(option => {
                            const opt = document.createElement('option');
                            opt.value = option;
                            opt.textContent = option === '' ? 'Auto' : option.charAt(0).toUpperCase() + option.slice(1);
                            if (option === setting.value) opt.selected = true;
                            inputElement.appendChild(opt);
                        });
                    } else if (setting.type === 'checkbox') {
                        // Create custom toggle switch
                        inputElement = document.createElement('input');
                        inputElement.type = 'checkbox';
                        inputElement.className = 'settings-checkbox';
                        inputElement.checked = setting.value === 'true';

                        // Create toggle wrapper
                        const toggleWrapper = document.createElement('label');
                        toggleWrapper.className = 'settings-toggle-wrapper';
                        toggleWrapper.htmlFor = `setting-${setting.key}`;

                        // Create toggle switch
                        const toggleSwitch = document.createElement('div');
                        toggleSwitch.className = 'settings-toggle-switch';

                        // Create toggle label
                        const toggleLabel = document.createElement('span');
                        toggleLabel.className = 'settings-toggle-label';
                        toggleLabel.textContent = setting.value === 'true' ? 'Enabled' : 'Disabled';

                        toggleWrapper.appendChild(toggleSwitch);
                        toggleWrapper.appendChild(toggleLabel);

                        // Auto-save checkbox changes immediately
                        inputElement.addEventListener('change', async (e) => {
                            const newValue = e.target.checked ? 'true' : 'false';
                            toggleLabel.textContent = e.target.checked ? 'Enabled' : 'Disabled';

                            try {
                                await this.updateSetting(setting.key, newValue);
                                this.showToast('success', `${setting.label} ${e.target.checked ? 'enabled' : 'disabled'}`);

                                // If disabling history, offer to clear existing history
                                if (setting.key === 'PROMPTHEUS_ENABLE_HISTORY' && !e.target.checked) {
                                    // Ask user if they want to clear history with custom dialog
                                    setTimeout(() => {
                                        this.showConfirmDialog(
                                            'Clear History?',
                                            'History has been disabled. Would you like to clear existing history as well?',
                                            () => this.clearHistory()
                                        );
                                    }, 500);
                                }
                            } catch (error) {
                                console.error('Error saving checkbox setting:', error);
                                this.showToast('error', 'Failed to save setting');
                                // Revert the checkbox state
                                e.target.checked = !e.target.checked;
                                toggleLabel.textContent = e.target.checked ? 'Enabled' : 'Disabled';
                            }
                        });

                        // Store the toggle wrapper to insert later
                        inputElement.toggleWrapper = toggleWrapper;

                        // Prevent the default change handler from triggering
                        inputElement.dataset.autoSave = 'true';
                    } else if (setting.type === 'password') {
                        inputElement = document.createElement('input');
                        inputElement.type = 'password';
                        inputElement.className = 'settings-input';

                        // If key exists (masked), show as placeholder and keep field empty
                        // User must enter new key to update it
                        if (setting.masked) {
                            inputElement.value = '';
                            inputElement.placeholder = `${setting.value} (current key)`;
                            inputElement.dataset.hasExistingKey = 'true';
                        } else {
                            inputElement.value = '';
                            inputElement.placeholder = 'Enter your API key';
                            inputElement.dataset.hasExistingKey = 'false';
                        }

                        // Add eye icon for password visibility toggle
                        const eyeButton = document.createElement('button');
                        eyeButton.type = 'button';
                        eyeButton.className = 'settings-eye-btn';
                        eyeButton.innerHTML = '👁';
                        eyeButton.title = 'Show/Hide API Key';
                        eyeButton.addEventListener('click', () => {
                            if (inputElement.type === 'password') {
                                inputElement.type = 'text';
                                eyeButton.innerHTML = '👁‍🗨';
                            } else {
                                inputElement.type = 'password';
                                eyeButton.innerHTML = '👁';
                            }
                        });
                        inputContainer.appendChild(eyeButton);
                    } else {
                        inputElement = document.createElement('input');
                        inputElement.type = 'text';
                        inputElement.className = 'settings-input';
                        inputElement.value = setting.value || '';
                    }

                    inputElement.id = `setting-${setting.key}`;
                    inputElement.name = setting.key;

                    // Auto-save on change for non-checkbox/non-password fields
                    if (!inputElement.dataset.autoSave && setting.type !== 'password') {
                        inputElement.addEventListener('change', async () => {
                            try {
                                await this.updateSetting(setting.key, inputElement.value);
                                this.showToast('success', `${setting.label} updated`);
                            } catch (error) {
                                console.error('Error saving setting:', error);
                                this.showToast('error', 'Failed to save setting');
                            }
                        });
                    }

                    // Insert checkbox and toggle wrapper if it's a checkbox
                    if (setting.type === 'checkbox' && inputElement.toggleWrapper) {
                        inputContainer.appendChild(inputElement);
                        inputContainer.appendChild(inputElement.toggleWrapper);
                    } else {
                        inputContainer.insertBefore(inputElement, inputContainer.firstChild);
                    }

                    // Add Save & Validate button for API keys
                    if (setting.type === 'password') {
                        // Determine provider from key name
                        const providerMatch = setting.key.match(/^(\w+)_API_KEY$/);
                        let providerName = providerMatch ? providerMatch[1].toLowerCase() : null;
                        if (providerName === 'dashscope') providerName = 'qwen';
                        if (providerName === 'gemini') providerName = 'google';
                        if (providerName === 'zai' || providerName === 'zhipuai') providerName = 'glm';

                        // Create button container
                        const buttonContainer = document.createElement('div');
                        buttonContainer.style.display = 'flex';
                        buttonContainer.style.gap = 'var(--space-2)';
                        buttonContainer.style.alignItems = 'center';
                        buttonContainer.style.marginTop = 'var(--space-2)';

                        // Add Save button for individual API key
                        const saveBtn = document.createElement('button');
                        saveBtn.type = 'button';
                        saveBtn.className = 'btn btn-secondary btn-sm';
                        saveBtn.innerHTML = '<span>💾</span><span>Save</span>';
                        saveBtn.style.minWidth = '80px';

                        // Create status container for validation feedback
                        const statusContainer = document.createElement('div');
                        statusContainer.id = `status-${setting.key}`;
                        statusContainer.className = 'validation-status-container';

                        saveBtn.addEventListener('click', async () => {
                            await this.saveAndValidateApiKey(setting.key, inputElement, providerName, statusContainer);
                        });

                        buttonContainer.appendChild(saveBtn);
                        item.appendChild(labelContainer);
                        item.appendChild(inputContainer);
                        item.appendChild(buttonContainer);
                        item.appendChild(statusContainer);
                    } else {
                        item.appendChild(labelContainer);
                        item.appendChild(inputContainer);
                    }

                    categorySection.appendChild(item);
                });

                settingsForm.appendChild(categorySection);
            });

        } catch (error) {
            console.error('Error loading settings:', error);
            this.showToast('error', 'Failed to load settings');
        }
    }

    async updateSetting(key, value) {
        try {
            const response = await fetch(`${this.apiBaseUrl}/api/settings`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ key, value })
            });

            const data = await response.json();

            if (response.ok) {
                this.showToast('success', `Setting "${key}" updated`);
                this.loadProviders();
            } else {
                this.showToast('error', data.detail || 'Failed to update setting');
            }
        } catch (error) {
            console.error('Error updating setting:', error);
            this.showToast('error', 'Network error: ' + error.message);
        }
    }

    async saveAndValidateApiKey(key, inputElement, providerName, statusContainer) {
        const apiKey = inputElement.value.trim();
        const hasExistingKey = inputElement.dataset.hasExistingKey === 'true';

        // If field is empty and there's an existing key, we need to get it from backend to validate
        if (!apiKey && hasExistingKey) {
            // User wants to test existing key without re-entering it
            // We can't validate without the actual key, so just show a message
            this.showToast('info', 'Enter a new API key to save and validate, or use the existing key');
            return;
        }

        if (!apiKey) {
            this.showToast('error', 'Please enter an API key');
            return;
        }

        // Save the API key first
        try {
            await this.updateSetting(key, apiKey);
            // After saving, mark that we now have an existing key and remember the value for quick retries
            inputElement.dataset.hasExistingKey = 'true';
            inputElement.dataset.lastSavedKey = apiKey;
            // Clear the field and update placeholder
            const maskedKey = '●'.repeat(Math.max(0, apiKey.length - 4)) + apiKey.slice(-4);
            inputElement.value = '';
            inputElement.placeholder = `${maskedKey} (current key)`;
        } catch (error) {
            this.showToast('error', 'Failed to save API key');
            return;
        }

            // Now validate the connection if provider is known
            if (!providerName) {
                this.showToast('success', 'API key saved');
                return;
            }

        await this.validateApiKey(providerName, apiKey, key, inputElement, statusContainer);
        // Refresh provider availability after successful save/validate
        this.loadProviders();
    }

    async validateApiKey(provider, apiKey, settingKey, inputElement, statusContainer) {
        // Show validating status
        inputElement.classList.remove('valid', 'invalid');
        inputElement.classList.add('validating');

        // Normalize provider aliases
        const normalizedProvider = (() => {
            const p = (provider || '').toLowerCase();
            if (p === 'dashscope') return 'qwen';
            if (p === 'gemini') return 'google';
            if (p === 'zai' || p === 'zhipuai') return 'glm';
            return p;
        })();

        statusContainer.innerHTML = `
            <div class="validation-status validating">
                <span class="validation-status-icon">⚗</span>
                <span class="validation-status-text">Verifying connection...</span>
            </div>
        `;

        try {
            const response = await fetch(`${this.apiBaseUrl}/api/settings/validate`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ provider: normalizedProvider, api_key: apiKey })
            });

            const data = await response.json();

            inputElement.classList.remove('validating');

            if (data.valid) {
                // Success state
                inputElement.classList.add('valid');

                const modelsInfo = data.models_available && data.models_available.length > 0
                    ? `<div style="margin-top: var(--space-1); font-size: var(--text-xs); opacity: 0.8;">Models: ${data.models_available.slice(0, 3).join(', ')}${data.models_available.length > 3 ? '...' : ''}</div>`
                    : '';

                statusContainer.innerHTML = `
                    <div class="validation-status success">
                        <span class="validation-status-icon">✓</span>
                        <span class="validation-status-text">Connected to ${provider}</span>
                        <span class="validation-status-time">Just now</span>
                    </div>
                    ${modelsInfo}
                `;

                this.showToast('success', `✓ ${provider} API key validated`);
            } else {
                // Error state
                inputElement.classList.add('invalid');

                statusContainer.innerHTML = `
                    <div class="validation-status error">
                        <span class="validation-status-icon">✗</span>
                        <span class="validation-status-text">Connection Failed</span>
                    </div>
                    <div class="validation-error-details">
                        <strong>Error:</strong> ${this.escapeHtml(data.error || 'Unknown error')}<br>
                        <strong>Suggestion:</strong> ${this.escapeHtml(data.suggestion || 'Check your API key and try again')}
                    </div>
                    <button class="validation-retry-btn" onclick="window.promptheusApp.retryValidation('${provider}', '${settingKey}')">
                        ↻ Retry
                    </button>
                `;

                this.showToast('error', `✗ ${provider} validation failed`);
            }
        } catch (error) {
            inputElement.classList.remove('validating');
            inputElement.classList.add('invalid');

            statusContainer.innerHTML = `
                <div class="validation-status error">
                    <span class="validation-status-icon">✗</span>
                    <span class="validation-status-text">Validation Error</span>
                </div>
                <div class="validation-error-details">
                    Network error: ${this.escapeHtml(error.message)}
                </div>
            `;

            this.showToast('error', 'Network error during validation');
        }
    }

    retryValidation(provider, settingKey) {
        const inputElement = document.getElementById(`setting-${settingKey}`);
        const statusContainer = document.getElementById(`status-${settingKey}`);

        if (!inputElement || !statusContainer) {
            this.showToast('error', 'Unable to retry validation—input not found');
            return;
        }

        let apiKey = inputElement.value.trim();
        if (!apiKey) {
            apiKey = inputElement.dataset.lastSavedKey || '';
        }

        if (!apiKey) {
            this.showToast('info', 'Enter an API key to validate');
            return;
        }

        this.validateApiKey(provider, apiKey, settingKey, inputElement, statusContainer);
    }

    /* ===================================================================
       PROMPT TWEAKING
       =================================================================== */

    async showTweakPromptDialog() {
        const outputDiv = document.getElementById('output');
        const optimizedPromptDiv = outputDiv.querySelector('.optimized-prompt-content');

        if (!optimizedPromptDiv) {
            this.showMessage('error', 'No prompt to tweak');
            return;
        }

        const currentPrompt = optimizedPromptDiv.textContent || optimizedPromptDiv.innerText;

        // Show tweak input form
        let formHtml = '<div class="tweak-container">';
        formHtml += '<div class="tweak-header">';
        formHtml += '<h3 class="tweak-title">Tweak Your Prompt</h3>';
        formHtml += '<p class="tweak-description">Describe how you want to modify the optimized prompt:</p>';
        formHtml += '</div>';
        formHtml += '<form id="tweak-form">';
        formHtml += '<div class="tweak-item">';
        formHtml += '<textarea id="tweak-instruction" placeholder="e.g., Make it more formal, Add more details about X, Make it shorter" required class="tweak-input"></textarea>';
        formHtml += '</div>';
        formHtml += '<div class="tweak-examples">';
        formHtml += '<p style="font-size: var(--text-sm); color: var(--text-secondary); margin-bottom: var(--space-2);">Examples:</p>';
        formHtml += '<ul style="font-size: var(--text-sm); color: var(--text-secondary); margin-left: var(--space-4);">';
        formHtml += '<li>Make it more formal and professional</li>';
        formHtml += '<li>Add specific examples for each point</li>';
        formHtml += '<li>Make it more concise and direct</li>';
        formHtml += '<li>Convert to bullet points</li>';
        formHtml += '</ul>';
        formHtml += '</div>';
        formHtml += '<div class="tweak-actions">';
        formHtml += '<button type="submit" class="btn btn-primary">Apply Tweak</button>';
        formHtml += '<button type="button" id="cancel-tweak-btn" class="btn btn-secondary">Cancel</button>';
        formHtml += '</div>';
        formHtml += '</form></div>';

        outputDiv.innerHTML = formHtml;

        const form = document.getElementById('tweak-form');
        const cancelBtn = document.getElementById('cancel-tweak-btn');
        const tweakBtn = document.getElementById('tweak-btn');
        const copyBtn = document.getElementById('copy-btn');

        tweakBtn.classList.add('hidden'); // Hide tweak button while tweaking
        copyBtn.classList.add('hidden'); // Hide copy button while tweaking

        cancelBtn.addEventListener('click', () => {
            // Restore the original prompt
            outputDiv.innerHTML = `<div class="optimized-prompt-content">${this.escapeHtml(currentPrompt)}</div>`;
            tweakBtn.classList.remove('hidden');
            copyBtn.classList.remove('hidden');
        });

        form.addEventListener('submit', async (e) => {
            e.preventDefault();
            const tweakInstruction = document.getElementById('tweak-instruction').value.trim();

            if (!tweakInstruction) {
                this.showMessage('error', 'Please enter a tweak instruction');
                return;
            }

            const submitButton = form.querySelector('button[type="submit"]');
            submitButton.disabled = true;
            submitButton.innerHTML = '<span class="spinner"></span><span>Applying tweak...</span>';

            try {
                const provider = document.getElementById('provider-select').value;
                const response = await fetch(`${this.apiBaseUrl}/api/prompt/tweak`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        current_prompt: currentPrompt,
                        tweak_instruction: tweakInstruction,
                        provider: provider || null
                    })
                });

                const data = await response.json();

                if (data.success) {
                    this.currentOptimizedPrompt = data.tweaked_prompt;
                    this.renderOutput();
                    tweakBtn.classList.remove('hidden');
                    copyBtn.classList.remove('hidden');
                } else {
                    this.showMessage('error', data.error || 'Failed to tweak prompt');
                }
            } catch (error) {
                console.error('Error tweaking prompt:', error);
                this.showMessage('error', 'Network error: ' + error.message);
            } finally {
                submitButton.disabled = false;
                submitButton.innerHTML = '<span>Apply Tweak</span>';
            }
        });
    }

    /* ===================================================================
       UI HELPERS
       =================================================================== */

    extractTextWithNewlines(node) {
        if (!node) return '';
        // Work off rendered HTML to normalize line breaks consistently
        const html = node.innerHTML;
        const withBreaks = html
            .replace(/<br\s*\/?>(\r?\n)?/gi, '\n')
            .replace(/<\/(p|div|section|article|h[1-6])>/gi, '\n\n')
            .replace(/<\/(li)>/gi, '\n')
            .replace(/<li>/gi, '- ')
            .replace(/<[^>]+>/g, '')
            .replace(/&nbsp;/gi, ' ')
            .replace(/&amp;/gi, '&')
            .replace(/&lt;/gi, '<')
            .replace(/&gt;/gi, '>')
            .replace(/&quot;/gi, '"')
            .replace(/&#39;/gi, "'");

        return withBreaks.replace(/\n{3,}/g, '\n\n').trim();
    }

    async copyOutputToClipboard() {
        const outputDiv = document.getElementById('output');
        const optimizedPromptDiv = outputDiv.querySelector('.optimized-prompt-content');

        if (!optimizedPromptDiv) {
            this.showToast('info', 'Nothing to copy');
            return;
        }

        const textFromState = (this.currentOptimizedPrompt || '').trim();
        const textFromDom = this.extractTextWithNewlines(optimizedPromptDiv);
        const textToCopy = textFromState || textFromDom;

        try {
            await navigator.clipboard.writeText(textToCopy);
            this.showToast('success', 'Copied to clipboard!');
        } catch (err) {
            console.error('Failed to copy:', err);

            // Fallback
            const textArea = document.createElement('textarea');
            textArea.value = textToCopy;
            textArea.style.position = 'fixed';
            textArea.style.opacity = '0';
            document.body.appendChild(textArea);
            textArea.select();

            try {
                const successful = document.execCommand('copy');
                document.body.removeChild(textArea);

                if (successful) {
                    this.showToast('success', 'Copied to clipboard!');
                } else {
                    this.showToast('error', 'Failed to copy');
                }
            } catch (err) {
                document.body.removeChild(textArea);
                this.showToast('error', 'Failed to copy');
            }
        }
    }

    showToast(type, message) {
        // Ensure toast container exists
        let toastContainer = document.querySelector('.toast-container');
        if (!toastContainer) {
            toastContainer = document.createElement('div');
            toastContainer.className = 'toast-container';
            document.body.appendChild(toastContainer);
        }

        // Create toast element
        const toast = document.createElement('div');
        toast.className = `toast toast-${type}`;

        const iconMap = {
            success: '✓',
            error: '⚠',
            info: '💡',
            warning: '⚡'
        };

        toast.innerHTML = `
            <span class="toast-icon">${iconMap[type] || '💡'}</span>
            <span class="toast-message">${this.escapeHtml(message)}</span>
        `;

        // Add to container (prepend so new toasts appear at bottom)
        toastContainer.appendChild(toast);

        // Trigger animation
        setTimeout(() => toast.classList.add('show'), 10);

        // Limit to maximum 4 toasts
        const allToasts = toastContainer.querySelectorAll('.toast');
        if (allToasts.length > 4) {
            // Remove oldest toast (first in the stack)
            const oldestToast = allToasts[0];
            oldestToast.classList.remove('show');
            setTimeout(() => oldestToast.remove(), 300);
        }

        // Remove after 3 seconds
        setTimeout(() => {
            if (toast.parentElement) {
                toast.classList.remove('show');
                setTimeout(() => {
                    if (toast.parentElement) {
                        toast.remove();
                        // Clean up container if empty
                        if (toastContainer.children.length === 0) {
                            toastContainer.remove();
                        }
                    }
                }, 300);
            }
        }, 3000);
    }

    showConfirmDialog(title, message, onConfirm) {
        // Create overlay
        const overlay = document.createElement('div');
        overlay.className = 'confirm-dialog-overlay';

        // Create dialog
        const dialog = document.createElement('div');
        dialog.className = 'confirm-dialog';

        dialog.innerHTML = `
            <div class="confirm-dialog-header">
                <h3 class="confirm-dialog-title">${this.escapeHtml(title)}</h3>
            </div>
            <div class="confirm-dialog-body">
                <p class="confirm-dialog-message">${this.escapeHtml(message)}</p>
            </div>
            <div class="confirm-dialog-actions">
                <button class="btn btn-secondary confirm-dialog-cancel">Cancel</button>
                <button class="btn btn-primary confirm-dialog-confirm">Confirm</button>
            </div>
        `;

        overlay.appendChild(dialog);
        document.body.appendChild(overlay);

        // Trigger animation
        setTimeout(() => {
            overlay.classList.add('active');
            dialog.classList.add('active');
        }, 10);

        // Handle confirm
        const confirmBtn = dialog.querySelector('.confirm-dialog-confirm');
        confirmBtn.addEventListener('click', () => {
            this.closeConfirmDialog(overlay, dialog);
            if (onConfirm) onConfirm();
        });

        // Handle cancel
        const cancelBtn = dialog.querySelector('.confirm-dialog-cancel');
        cancelBtn.addEventListener('click', () => {
            this.closeConfirmDialog(overlay, dialog);
        });

        // Handle overlay click
        overlay.addEventListener('click', (e) => {
            if (e.target === overlay) {
                this.closeConfirmDialog(overlay, dialog);
            }
        });

        // Handle escape key
        const escapeHandler = (e) => {
            if (e.key === 'Escape') {
                this.closeConfirmDialog(overlay, dialog);
                document.removeEventListener('keydown', escapeHandler);
            }
        };
        document.addEventListener('keydown', escapeHandler);
    }

    closeConfirmDialog(overlay, dialog) {
        dialog.classList.remove('active');
        overlay.classList.remove('active');
        setTimeout(() => overlay.remove(), 300);
    }

    showKeyboardShortcuts() {
        // Create overlay
        const overlay = document.createElement('div');
        overlay.className = 'confirm-dialog-overlay';

        // Create dialog
        const dialog = document.createElement('div');
        dialog.className = 'confirm-dialog keyboard-shortcuts-dialog';

        dialog.innerHTML = `
            <div class="confirm-dialog-header">
                <h3 class="confirm-dialog-title">⌨️ Keyboard Shortcuts</h3>
                <button class="help-tooltip-close" aria-label="Close">✕</button>
            </div>
            <div class="confirm-dialog-body shortcuts-body">
                <div class="shortcuts-section">
                    <h4 class="shortcuts-section-title">Primary Actions</h4>
                    <div class="shortcuts-list">
                        <div class="shortcut-row">
                            <div class="shortcut-keys">Ctrl + ↵</div>
                            <div class="shortcut-desc">Submit/Optimize Prompt</div>
                        </div>
                        <div class="shortcut-row">
                            <div class="shortcut-keys">Ctrl + N</div>
                            <div class="shortcut-desc">Start Over</div>
                        </div>
                        <div class="shortcut-row">
                            <div class="shortcut-keys">Ctrl + Shift + X</div>
                            <div class="shortcut-desc">Cancel</div>
                        </div>
                        <div class="shortcut-row">
                            <div class="shortcut-keys">Ctrl + Shift + C</div>
                            <div class="shortcut-desc">Copy output</div>
                        </div>
                        <div class="shortcut-row">
                            <div class="shortcut-keys">Ctrl + T</div>
                            <div class="shortcut-desc">Tweak prompt</div>
                        </div>
                    </div>
                </div>

                <div class="shortcuts-section">
                    <h4 class="shortcuts-section-title">Configuration</h4>
                    <div class="shortcuts-list">
                        <div class="shortcut-row">
                            <div class="shortcut-keys">Ctrl + M</div>
                            <div class="shortcut-desc">Mode help</div>
                        </div>
                        <div class="shortcut-row">
                            <div class="shortcut-keys">Ctrl + Shift + S</div>
                            <div class="shortcut-desc">Style help</div>
                        </div>
                        <div class="shortcut-row">
                            <div class="shortcut-keys">Ctrl + P</div>
                            <div class="shortcut-desc">Provider</div>
                        </div>
                        <div class="shortcut-row">
                            <div class="shortcut-keys">Ctrl + L</div>
                            <div class="shortcut-desc">Model</div>
                        </div>
                        <div class="shortcut-row">
                            <div class="shortcut-keys">Ctrl + ,</div>
                            <div class="shortcut-desc">Settings</div>
                        </div>
                    </div>
                </div>

                <div class="shortcuts-section">
                    <h4 class="shortcuts-section-title">Navigation</h4>
                    <div class="shortcuts-list">
                        <div class="shortcut-row">
                            <div class="shortcut-keys">Ctrl + I</div>
                            <div class="shortcut-desc">Focus input</div>
                        </div>
                        <div class="shortcut-row">
                            <div class="shortcut-keys">Ctrl + Shift + H</div>
                            <div class="shortcut-desc">Clear history</div>
                        </div>
                        <div class="shortcut-row">
                            <div class="shortcut-keys">Ctrl + [</div>
                            <div class="shortcut-desc">Prev page</div>
                        </div>
                        <div class="shortcut-row">
                            <div class="shortcut-keys">Ctrl + ]</div>
                            <div class="shortcut-desc">Next page</div>
                        </div>
                    </div>
                </div>

                <div class="shortcuts-section">
                    <h4 class="shortcuts-section-title">General</h4>
                    <div class="shortcuts-list">
                        <div class="shortcut-row">
                            <div class="shortcut-keys">Esc</div>
                            <div class="shortcut-desc">Close all & cancel</div>
                        </div>
                        <div class="shortcut-row">
                            <div class="shortcut-keys">?</div>
                            <div class="shortcut-desc">Show this help</div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="confirm-dialog-actions">
                <button class="btn btn-primary confirm-dialog-confirm">Got it</button>
            </div>
        `;

        overlay.appendChild(dialog);
        document.body.appendChild(overlay);

        // Trigger animation
        setTimeout(() => {
            overlay.classList.add('active');
            dialog.classList.add('active');
        }, 10);

        // Handle close button
        const closeBtn = dialog.querySelector('.help-tooltip-close');
        closeBtn.addEventListener('click', () => {
            this.closeConfirmDialog(overlay, dialog);
        });

        // Handle confirm button
        const confirmBtn = dialog.querySelector('.confirm-dialog-confirm');
        confirmBtn.addEventListener('click', () => {
            this.closeConfirmDialog(overlay, dialog);
        });

        // Handle overlay click
        overlay.addEventListener('click', (e) => {
            if (e.target === overlay) {
                this.closeConfirmDialog(overlay, dialog);
            }
        });

        // Handle escape key
        const escapeHandler = (e) => {
            if (e.key === 'Escape') {
                this.closeConfirmDialog(overlay, dialog);
                document.removeEventListener('keydown', escapeHandler);
            }
        };
        document.addEventListener('keydown', escapeHandler);
    }

    showMessage(type, message) {
        const outputDiv = document.getElementById('output');
        const iconMap = {
            success: '✓',
            error: '⚠',
            info: '💡'
        };

        // Generate contextual help for errors
        let helpHTML = '';
        if (type === 'error') {
            helpHTML = this.generateErrorHelp(message);
        }

        outputDiv.innerHTML = `
            <div class="message message-${type}">
                <span class="message-icon">${iconMap[type]}</span>
                <div class="message-content">
                    <div class="message-text">${this.escapeHtml(message)}</div>
                    ${helpHTML}
                </div>
            </div>
        `;
    }

    generateErrorHelp(message) {
        const messageLower = message.toLowerCase();

        // Model not found error
        if (messageLower.includes('404') || (messageLower.includes('model') && messageLower.includes('not found'))) {
            return `
                <div class="error-help">
                    <strong>Model Not Available</strong>
                    <ul>
                        <li>Try selecting a different model from the dropdown</li>
                        <li>Use "↻ Load All Models" to see all available options</li>
                        <li>Some models may have been deprecated or renamed</li>
                    </ul>
                </div>
            `;
        }

        // API key / authentication error
        if (messageLower.includes('api key') || messageLower.includes('authentication') ||
            messageLower.includes('401') || messageLower.includes('403')) {
            return `
                <div class="error-help">
                    <strong>Authentication Issue</strong>
                    <ul>
                        <li>Check your API key in Settings ⚙️</li>
                        <li>Ensure the key has proper permissions</li>
                        <li>Verify the key hasn't expired</li>
                    </ul>
                </div>
            `;
        }

        // Rate limit error
        if (messageLower.includes('rate limit') || messageLower.includes('429') ||
            messageLower.includes('too many requests')) {
            return `
                <div class="error-help">
                    <strong>Rate Limit Reached</strong>
                    <ul>
                        <li>Wait a few moments before trying again</li>
                        <li>Consider upgrading your API plan for higher limits</li>
                    </ul>
                </div>
            `;
        }

        // Network/connection error
        if (messageLower.includes('network') || messageLower.includes('connection') ||
            messageLower.includes('timeout') || messageLower.includes('econnrefused')) {
            return `
                <div class="error-help">
                    <strong>Connection Error</strong>
                    <ul>
                        <li>Check your internet connection</li>
                        <li>Verify the API endpoint is accessible</li>
                        <li>Try again in a few moments</li>
                    </ul>
                </div>
            `;
        }

        return '';
    }

    showMessageWithSettings(message, type = 'error') {
        const outputDiv = document.getElementById('output');

        outputDiv.innerHTML = `
            <div class="message message-${type}">
                <div class="message-content">
                    <div class="message-text">
                        ${this.escapeHtml(message)}
                        <button class="message-settings-btn" onclick="window.promptheusApp.openSettings()">
                            ⚙️ Settings
                        </button>
                    </div>
                </div>
            </div>
        `;
    }

    showProgressIndicator(phase) {
        const outputDiv = document.getElementById('output');
        const phases = {
            analyzing: {
                symbol: '🔮',
                text: 'Analyzing prompt...'
            },
            generating_questions: {
                symbol: '❓',
                text: 'Generating questions...'
            },
            optimizing: {
                symbol: '⚗',
                text: 'Optimizing...'
            },
            refining: {
                symbol: '✨',
                text: 'Refining with your answers...'
            }
        };

        const phaseData = phases[phase] || phases.optimizing;

        outputDiv.innerHTML = `
            <div class="progress-indicator">
                <div class="progress-symbol">${phaseData.symbol}</div>
                <div class="progress-text">${phaseData.text}</div>
            </div>
        `;
    }

    escapeHtml(text) {
        if (typeof text !== 'string') return '';
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }

    // Provider status caching methods
    getCachedProviderStatus() {
        try {
            const cached = localStorage.getItem('promptheus_provider_status_cache');
            if (!cached) return null;

            const cacheData = JSON.parse(cached);
            const age = Date.now() - cacheData.timestamp;
            const twentyFourHours = 24 * 60 * 60 * 1000;

            // Expire after 24 hours
            if (age > twentyFourHours) {
                localStorage.removeItem('promptheus_provider_status_cache');
                return null;
            }

            return cacheData.status;
        } catch (error) {
            console.error('Error loading provider status cache:', error);
            return null;
        }
    }

    cacheProviderStatus(status) {
        try {
            const cacheData = {
                status: status,
                timestamp: Date.now()
            };
            localStorage.setItem('promptheus_provider_status_cache', JSON.stringify(cacheData));
        } catch (error) {
            console.error('Error caching provider status:', error);
        }
    }

    clearProviderStatusCache() {
        localStorage.removeItem('promptheus_provider_status_cache');
    }

    clearProviderStatusCache() {
        localStorage.removeItem('promptheus_provider_status_cache');
    }

    // Style Help functionality

    // ===================================================================
    // CUSTOM ALCHEMICAL DROPDOWN FUNCTIONALITY
    // ===================================================================

    initCustomDropdowns() {
        const dropdowns = document.querySelectorAll('.alchemical-dropdown');

        dropdowns.forEach(dropdown => {
            const select = dropdown.querySelector('select');
            const panel = dropdown.querySelector('.alchemical-dropdown-panel');
            const options = dropdown.querySelectorAll('.alchemical-option');

            // Initialize selected state
            this.updateDropdownSelectedState(dropdown, select.value);

            // Toggle dropdown on select click
            select.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                this.toggleDropdown(dropdown);
            });

            // Handle option selection
            options.forEach(option => {
                option.addEventListener('click', (e) => {
                    e.preventDefault();
                    e.stopPropagation();
                    const value = option.dataset.value;
                    select.value = value;
                    this.updateDropdownSelectedState(dropdown, value);
                    this.closeDropdown(dropdown);

                    // Trigger change event on the original select
                    select.dispatchEvent(new Event('change', { bubbles: true }));
                });

                option.addEventListener('mouseenter', () => {
                    // Add mystical glow effect on hover
                    option.style.boxShadow = 'inset 0 0 20px rgba(212, 165, 116, 0.1)';
                });

                option.addEventListener('mouseleave', () => {
                    option.style.boxShadow = '';
                });
            });

            // Sync with original select change events
            select.addEventListener('change', () => {
                this.updateDropdownSelectedState(dropdown, select.value);
            });
        });

        // Initialize help tooltip system
        const helpIcons = document.querySelectorAll('.toolbar-help-icon');
        helpIcons.forEach(icon => {
            const helpFor = icon.getAttribute('data-help-for');
            const tooltip = document.getElementById(`${helpFor}-help-tooltip`);
            const closeBtn = tooltip?.querySelector('.help-tooltip-close');

            if (!tooltip) return;

            // Move tooltip to body for proper stacking
            document.body.appendChild(tooltip);

            // Set initial position immediately to prevent jump on first open
            const iconRect = icon.getBoundingClientRect();
            const tooltipWidth = 400; // max-width from CSS
            const tooltipHeight = 300; // estimated max height
            const spacing = 8;

            // Calculate horizontal position (clamp to viewport)
            let left = iconRect.left;
            if (left + tooltipWidth > window.innerWidth) {
                // Would overflow right edge, align to right edge instead
                left = window.innerWidth - tooltipWidth - spacing;
            }
            if (left < spacing) {
                // Would overflow left edge
                left = spacing;
            }

            // Calculate vertical position (prefer below, but show above if no room)
            let top = iconRect.bottom + spacing;
            let showAbove = false;
            if (top + tooltipHeight > window.innerHeight) {
                // Not enough room below, try above
                const topAbove = iconRect.top - tooltipHeight - spacing;
                if (topAbove >= 0 || topAbove > top + tooltipHeight - window.innerHeight) {
                    // Either fits above, or fits better above than below
                    top = topAbove;
                    showAbove = true;
                }
            }

            tooltip.style.position = 'fixed';
            tooltip.style.left = `${left}px`;
            tooltip.style.top = `${top}px`;
            tooltip.dataset.showAbove = showAbove;

            // Toggle tooltip on icon click
            icon.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();

                // Close other tooltips
                document.querySelectorAll('.help-tooltip.visible').forEach(t => {
                    if (t !== tooltip) {
                        t.classList.remove('visible');
                    }
                });
                document.querySelectorAll('.toolbar-help-icon.active').forEach(i => {
                    if (i !== icon) {
                        i.classList.remove('active');
                    }
                });

                const isVisible = tooltip.classList.contains('visible');

                if (!isVisible) {
                    // Position tooltip relative to icon BEFORE making visible
                    const iconRect = icon.getBoundingClientRect();
                    const tooltipWidth = 400; // max-width from CSS
                    const tooltipHeight = 300; // estimated max height
                    const spacing = 8;

                    // Calculate horizontal position (clamp to viewport)
                    let left = iconRect.left;
                    if (left + tooltipWidth > window.innerWidth) {
                        // Would overflow right edge, align to right edge instead
                        left = window.innerWidth - tooltipWidth - spacing;
                    }
                    if (left < spacing) {
                        // Would overflow left edge
                        left = spacing;
                    }

                    // Calculate vertical position (prefer below, but show above if no room)
                    let top = iconRect.bottom + spacing;
                    let showAbove = false;
                    if (top + tooltipHeight > window.innerHeight) {
                        // Not enough room below, try above
                        const topAbove = iconRect.top - tooltipHeight - spacing;
                        if (topAbove >= 0 || topAbove > top + tooltipHeight - window.innerHeight) {
                            // Either fits above, or fits better above than below
                            top = topAbove;
                            showAbove = true;
                        }
                    }

                    tooltip.style.position = 'fixed';
                    tooltip.style.left = `${left}px`;
                    tooltip.style.top = `${top}px`;
                    tooltip.dataset.showAbove = showAbove;
                }

                // Toggle current tooltip
                tooltip.classList.toggle('visible');
                icon.classList.toggle('active');
            });

            // Close tooltip on close button click
            if (closeBtn) {
                closeBtn.addEventListener('click', (e) => {
                    e.stopPropagation();
                    tooltip.classList.remove('visible');
                    icon.classList.remove('active');
                });
            }
        });

        // Close dropdowns and tooltips when clicking outside
        document.addEventListener('click', (e) => {
            if (!e.target.closest('.alchemical-dropdown')) {
                document.querySelectorAll('.alchemical-dropdown.active').forEach(dropdown => {
                    this.closeDropdown(dropdown);
                });
            }
            // Close help tooltips when clicking outside
            if (!e.target.closest('.toolbar-help-icon') && !e.target.closest('.help-tooltip')) {
                document.querySelectorAll('.help-tooltip.visible').forEach(tooltip => {
                    tooltip.classList.remove('visible');
                });
                document.querySelectorAll('.toolbar-help-icon.active').forEach(icon => {
                    icon.classList.remove('active');
                });
            }
        });
    }

    toggleDropdown(dropdown) {
        if (dropdown.classList.contains('active')) {
            this.closeDropdown(dropdown);
        } else {
            // Close all other dropdowns first
            document.querySelectorAll('.alchemical-dropdown.active').forEach(other => {
                if (other !== dropdown) {
                    this.closeDropdown(other);
                }
            });
            this.openDropdown(dropdown);
        }
    }

    openDropdown(dropdown) {
        dropdown.classList.add('active');
        const select = dropdown.querySelector('select');

        // Add mystical entrance animation
        const panel = dropdown.querySelector('.alchemical-dropdown-panel');
        panel.style.animation = 'dropdownMysticalEntrance 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55)';

        // Add accessibility
        select.setAttribute('aria-expanded', 'true');
    }

    closeDropdown(dropdown) {
        dropdown.classList.remove('active');
        const select = dropdown.querySelector('select');

        // Add mystical exit animation
        const panel = dropdown.querySelector('.alchemical-dropdown-panel');
        panel.style.animation = 'dropdownMysticalExit 0.3s cubic-bezier(0.4, 0, 0.2, 1)';

        // Add accessibility
        select.setAttribute('aria-expanded', 'false');
    }

    updateDropdownSelectedState(dropdown, value) {
        const options = dropdown.querySelectorAll('.alchemical-option');
        const select = dropdown.querySelector('select');

        options.forEach(option => {
            if (option.dataset.value === value) {
                option.classList.add('selected');

                // Add mystical selection animation
                option.style.animation = 'optionMysticalSelect 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55)';
                setTimeout(() => {
                    option.style.animation = '';
                }, 400);
            } else {
                option.classList.remove('selected');
            }
        });

        // Update the original select display
        this.updateSelectDisplay(select);
    }

    updateSelectDisplay(select) {
        const selectedOption = select.options[select.selectedIndex];
        const dropdown = select.closest('.alchemical-dropdown');

        // Update visual feedback without changing the actual value
        const panel = dropdown.querySelector('.alchemical-dropdown-panel');
        if (panel) {
            // Add a brief glow effect to indicate change
            panel.style.boxShadow = '0 0 40px rgba(212, 165, 116, 0.3)';
            setTimeout(() => {
                panel.style.boxShadow = '';
            }, 300);
        }
    }

    async loadVersion() {
        try {
            console.log('Loading version from:', `${this.apiBaseUrl}/api/version`);
            const response = await fetch(`${this.apiBaseUrl}/api/version`);
            console.log('Version response status:', response.status);

            if (!response.ok) {
                throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }

            const data = await response.json();
            console.log('Version data:', data);

            const versionText = document.getElementById('version-text');
            const buildInfo = document.getElementById('build-info');
            const footerVersion = document.getElementById('footer-version');

            console.log('Found versionText element:', !!versionText);
            console.log('Found buildInfo element:', !!buildInfo);
            console.log('Found footerVersion element:', !!footerVersion);

            if (versionText) {
                let versionStr = data.full_version || data.version || 'Unknown';
                if (data.commit_hash) {
                    versionStr += ` (${data.commit_hash}`;
                    if (data.is_dirty) {
                        versionStr += '-dirty';
                    }
                    versionStr += ')';
                }
                versionText.textContent = versionStr;
                console.log('Set version text to:', versionStr);
            }

            if (footerVersion) {
                let footerVersionStr = data.full_version || data.version || 'Unknown';
                if (data.commit_hash) {
                    footerVersionStr += ` (${data.commit_hash}`;
                    if (data.is_dirty) {
                        footerVersionStr += '-dirty';
                    }
                    footerVersionStr += ')';
                }
                footerVersion.textContent = footerVersionStr;
                console.log('Set footer version to:', footerVersionStr);
            }

            if (buildInfo && data.commit_date) {
                const buildType = data.build_type === 'dev' ? 'Development' : 'Clean';
                buildInfo.innerHTML = `
                    <div class="build-row">
                        <span class="build-field">Type:</span>
                        <span class="build-value ${data.build_type === 'dev' ? 'build-dev' : 'build-clean'}">${buildType}</span>
                    </div>
                    <div class="build-row">
                        <span class="build-field">Updated:</span>
                        <span class="build-value">${new Date(data.commit_date).toLocaleDateString()}</span>
                    </div>
                    ${data.commit_hash ? `
                    <div class="build-row">
                        <span class="build-field">Commit:</span>
                        <span class="build-value code">${data.commit_hash}</span>
                    </div>
                    ` : ''}
                `;
                console.log('Set build info');
            }
        } catch (error) {
            console.error('Failed to load version info:', error);
            const versionText = document.getElementById('version-text');
            const footerVersion = document.getElementById('footer-version');
            if (versionText) {
                versionText.textContent = 'Error';
            }
            if (footerVersion) {
                footerVersion.textContent = 'Error';
            }
        }
    }
}

// Initialize the app when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
    window.promptheusApp = new PromptheusApp();
});
