/**
 * UI utility functions
 */

// Note: sanitizer functions are available via Vite bundle or we use safe fallbacks

/**
 * Safe HTML setter - uses DOMPurify if available, otherwise sets innerHTML directly
 * for controlled/trusted content only
 */
function safeSetHTML(element, html, level) {
    if (!element) return;
    // If DOMPurify is available globally (from Vite bundle), use it
    if (typeof DOMPurify !== 'undefined') {
        element.innerHTML = DOMPurify.sanitize(html);
    } else {
        // For controlled content (UI elements we generate), direct assignment is acceptable
        element.innerHTML = html;
    }
}

/**
 * Update a progress bar UI element
 * @param {string|Element} fillElementId - The ID or element to fill
 * @param {string|Element} percentageElementId - The ID or element to show percentage
 * @param {number} percentage - The percentage to set
 */
function updateProgressBar(fillElementId, percentageElementId, percentage) {
    const progressFill = typeof fillElementId === 'string' ? document.getElementById(fillElementId) : fillElementId;
    const progressPercentage = typeof percentageElementId === 'string' ? document.getElementById(percentageElementId) : percentageElementId;

    if (progressFill && progressPercentage) {
        // Convert any value to a percentage between 0-100
        const safePercentage = Math.min(100, Math.max(0, percentage || 0));

        // Update the width of the fill element
        progressFill.style.width = `${safePercentage}%`;

        // Update the percentage text
        progressPercentage.textContent = `${Math.round(safePercentage)}%`;

        // Add classes for visual feedback
        if (safePercentage >= 100) {
            progressFill.classList.add('ldr-complete');
        } else {
            progressFill.classList.remove('ldr-complete');
        }
    }
}

/**
 * Show a loading spinner
 * @param {string|Element} container - The container ID or element to add the spinner to
 * @param {string} message - Optional message to show with the spinner
 */
function showSpinner(container, message = 'Loading...') {
    const containerEl = typeof container === 'string' ? document.getElementById(container) : container;

    if (containerEl) {
        containerEl.innerHTML = '';

        const spinnerHTML = `
            <div class="loading-spinner centered">
                <div class="spinner"></div>
                ${message ? `<div class="spinner-message">${message}</div>` : ''}
            </div>
        `;

        // Safe: spinner HTML is controlled/static, but sanitize message for safety
        safeSetHTML(containerEl, spinnerHTML, 'ui');
    }
}

/**
 * Hide a loading spinner
 * @param {string|Element} container - The container ID or element with the spinner
 */
function hideSpinner(container) {
    const containerEl = typeof container === 'string' ? document.getElementById(container) : container;

    if (containerEl) {
        const spinner = containerEl.querySelector('.ldr-loading-spinner');
        if (spinner) {
            spinner.remove();
        }
    }
}

/**
 * Show an error message
 * @param {string|Element} container - The container ID or element to add the error to
 * @param {string} message - The error message
 */
function showError(container, message) {
    const containerEl = typeof container === 'string' ? document.getElementById(container) : container;

    if (containerEl) {
        const errorHTML = `
            <div class="error-message">
                <i class="fas fa-exclamation-circle"></i>
                <span>${message}</span>
            </div>
        `;

        // Sanitize message to prevent XSS
        safeSetHTML(containerEl, errorHTML, 'ui');
    }
}

/**
 * Show a notification message
 * @param {string} message - The message to display
 * @param {string} type - Message type: 'success', 'error', 'info', 'warning'
 * @param {number} duration - How long to show the message in ms
 */
function showMessage(message, type = 'success', duration = 3000) {
    // Check if the toast container exists
    let toastContainer = document.getElementById('toast-container');

    // Create it if it doesn't exist
    if (!toastContainer) {
        toastContainer = document.createElement('div');
        toastContainer.id = 'toast-container';
        document.body.appendChild(toastContainer);
    }

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

    // Add icon based on type
    let icon = '';
    switch (type) {
        case 'success':
            icon = '<i class="fas fa-check-circle"></i>';
            break;
        case 'error':
            icon = '<i class="fas fa-exclamation-circle"></i>';
            break;
        case 'info':
            icon = '<i class="fas fa-info-circle"></i>';
            break;
        case 'warning':
            icon = '<i class="fas fa-exclamation-triangle"></i>';
            break;
    }

    // Set the content (sanitize message to prevent XSS)
    safeSetHTML(toast, `
        ${icon}
        <div class="toast-message">${message}</div>
    `, 'ui');

    // Add to container
    toastContainer.appendChild(toast);

    // Show with animation
    setTimeout(() => {
        toast.classList.add('visible');
    }, 10);

    // Remove after duration
    setTimeout(() => {
        toast.classList.remove('visible');

        // Remove from DOM after animation
        setTimeout(() => {
            toast.remove();
        }, 300);
    }, duration);
}

/**
 * Format and render Markdown content
 * @param {string} markdown - The markdown content
 * @returns {string} The rendered HTML
 */
function renderMarkdown(markdown) {
    if (!markdown) {
        return '<div class="alert alert-warning">No content available</div>';
    }

    try {
        // Use marked library if available
        if (typeof marked !== 'undefined') {
            // Configure marked options
            marked.setOptions({
                breaks: true,
                gfm: true,
                headerIds: true,
                smartLists: true,
                smartypants: true,
                highlight: function(code, language) {
                    // Use Prism for syntax highlighting if available
                    if (typeof Prism !== 'undefined' && Prism.languages[language]) {
                        return Prism.highlight(code, Prism.languages[language], language);
                    }
                    return code;
                }
            });

            // Parse markdown and return HTML
            const html = marked.parse(markdown);

            // Process any special elements like image references
            const processedHtml = processSpecialMarkdown(html);

            return `<div class="markdown-content">${processedHtml}</div>`;
        } else {
            // Basic fallback if marked is not available
            console.warn('Marked library not available. Using basic formatting.');
            const basic = markdown
                .replace(/\n\n/g, '<br><br>')
                .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
                .replace(/\*(.*?)\*/g, '<em>$1</em>')
                .replace(/\[(.*?)\]\((.*?)\)/g, '<a href="$2" target="_blank">$1</a>');

            return `<div class="markdown-content">${basic}</div>`;
        }
    } catch (error) {
        console.error('Error rendering markdown:', error);
        return `<div class="alert alert-danger">Error rendering content: ${error.message}</div>`;
    }
}

/**
 * Process special markdown elements
 * @param {string} html - HTML content to process
 * @returns {string} - Processed HTML
 */
function processSpecialMarkdown(html) {
    // Process image references
    return html.replace(/\!\[ref:([^\]]+)\]/g, (match, ref) => {
        // Check if this is a reference to a generated image
        if (ref.startsWith('image-')) {
            return `<div class="generated-image" data-image-id="${ref}">
                <img src="/static/img/generated/${ref}.png"
                     alt="Generated image ${ref}"
                     class="img-fluid"
                     loading="lazy" />
                <div class="image-caption">Generated image (${ref})</div>
            </div>`;
        }
        return match;
    });
}

/**
 * Create a dynamic favicon
 * @param {string} emoji - The emoji to use for the favicon
 */
function createDynamicFavicon(emoji = '⚡') {
    // Create a canvas element
    const canvas = document.createElement('canvas');
    canvas.width = 64;
    canvas.height = 64;

    // Get the 2D drawing context
    const ctx = canvas.getContext('2d');

    // Clear the canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Set font
    ctx.font = '48px Arial';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';

    // Draw the emoji
    ctx.fillText(emoji, 32, 32);

    // Convert to data URL
    const dataUrl = canvas.toDataURL('image/png');

    // Create or update the favicon link
    let link = document.querySelector('link[rel="icon"]');
    if (!link) {
        link = document.createElement('link');
        link.rel = 'icon';
        document.head.appendChild(link);
    }

    // Set the new favicon
    // Data URLs from canvas are safe for favicon use
    if (typeof URLValidator !== 'undefined' && URLValidator.safeAssign) {
        URLValidator.safeAssign(link, 'href', dataUrl);
    } else {
        link.href = dataUrl;
    }
}

/**
 * Update favicon based on status
 * @param {string} status - The research status
 */
function updateFavicon(status) {
    try {
        // Find favicon link or create it if it doesn't exist
        let link = document.querySelector("link[rel='icon']") ||
                document.querySelector("link[rel='shortcut icon']");

        if (!link) {
            console.log('Favicon link not found, creating a new one');
            link = document.createElement('link');
            link.rel = 'icon';
            link.type = 'image/x-icon';
            document.head.appendChild(link);
        }

        // Create dynamic favicon using canvas
        const canvas = document.createElement('canvas');
        canvas.width = 32;
        canvas.height = 32;
        const ctx = canvas.getContext('2d');

        // Background color based on status
        let bgColor = '#007bff'; // Default blue

        if (status === 'completed') {
            bgColor = '#28a745'; // Success green
        } else if (status === 'failed' || status === 'error') {
            bgColor = '#dc3545'; // Error red
        } else if (status === 'cancelled') {
            bgColor = '#6c757d'; // Gray
        }

        // Draw circle background
        ctx.fillStyle = bgColor;
        ctx.beginPath();
        ctx.arc(16, 16, 16, 0, 2 * Math.PI);
        ctx.fill();

        // Draw inner circle
        ctx.fillStyle = '#ffffff';
        ctx.beginPath();
        ctx.arc(16, 16, 10, 0, 2 * Math.PI);
        ctx.fill();

        // Draw letter R
        ctx.fillStyle = bgColor;
        ctx.font = 'bold 16px Arial';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText('R', 16, 16);

        // Set the favicon to the canvas data URL
        link.href = canvas.toDataURL('image/png');

        console.log('Updated favicon to:', status);
    } catch (error) {
        console.error('Error updating favicon:', error);
    }
}

/**
 * Show an alert message in a container on the page
 * @param {string} message - The message to display
 * @param {string} type - The alert type: success, error, warning, info
 * @param {boolean} skipIfToastShown - Whether to skip showing this alert if a toast was already shown
 */
function showAlert(message, type = 'info', skipIfToastShown = true) {
    // If we're showing a toast and we want to skip the regular alert, just return
    if (skipIfToastShown && window.ui && window.ui.showMessage) {
        return;
    }

    // Find the alert container - look for different possible alert containers
    let alertContainer = document.getElementById('filtered-settings-alert');

    // If not found, try other common alert containers
    if (!alertContainer) {
        alertContainer = document.getElementById('settings-alert');
    }

    if (!alertContainer) {
        alertContainer = document.getElementById('research-alert');
    }

    if (!alertContainer) return;

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

    // Create alert element
    const alert = document.createElement('div');
    alert.className = `alert alert-${type}`;
    safeSetHTML(alert, `<i class="fas ${type === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle'}"></i> ${message}`, 'ui');

    // Add a close button
    const closeBtn = document.createElement('span');
    closeBtn.className = 'ldr-alert-close';
    closeBtn.textContent = '×'; // Use textContent instead of innerHTML for security
    closeBtn.addEventListener('click', () => {
        alert.remove();
        alertContainer.style.display = 'none';
    });

    alert.appendChild(closeBtn);

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

    // Auto-hide after 5 seconds
    setTimeout(() => {
        alert.remove();
        if (alertContainer.children.length === 0) {
            alertContainer.style.display = 'none';
        }
    }, 5000);
}

// Add CSS for toast messages
function addToastStyles() {
    if (document.getElementById('toast-styles')) return;

    const styleEl = document.createElement('style');
    styleEl.id = 'toast-styles';
    styleEl.textContent = `
        #toast-container {
            position: fixed;
            top: 20px;
            right: 20px;
            z-index: 9999;
            display: flex;
            flex-direction: column;
            gap: 10px;
        }

        .toast {
            display: flex;
            align-items: center;
            gap: 10px;
            background-color: var(--card-bg, #2a2a2a);
            color: var(--text-color, #fff);
            padding: 12px 16px;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
            max-width: 350px;
            transform: translateX(120%);
            opacity: 0;
            transition: transform 0.3s ease, opacity 0.3s ease;
            border-left: 4px solid transparent;
        }

        .toast.visible {
            transform: translateX(0);
            opacity: 1;
        }

        .toast i {
            font-size: 1.2rem;
        }

        .toast-success {
            border-left-color: var(--success-color, #28a745);
        }

        .toast-success i {
            color: var(--success-color, #28a745);
        }

        .toast-error {
            border-left-color: var(--danger-color, #dc3545);
        }

        .toast-error i {
            color: var(--danger-color, #dc3545);
        }

        .toast-info {
            border-left-color: var(--info-color, #17a2b8);
        }

        .toast-info i {
            color: var(--info-color, #17a2b8);
        }

        .toast-warning {
            border-left-color: var(--warning-color, #ffc107);
        }

        .toast-warning i {
            color: var(--warning-color, #ffc107);
        }
    `;

    document.head.appendChild(styleEl);
}

// Add CSS for alert styles
function addAlertStyles() {
    if (document.getElementById('alert-styles')) return;

    const styleEl = document.createElement('style');
    styleEl.id = 'alert-styles';
    styleEl.textContent = `
        .alert {
            padding: 12px 16px;
            margin-bottom: 1rem;
            border-radius: 8px;
            display: flex;
            align-items: center;
            position: relative;
        }

        .alert i {
            margin-right: 12px;
            font-size: 1.2rem;
        }

        .alert-success {
            background-color: rgba(40, 167, 69, 0.15);
            color: var(--success-color, #28a745);
            border-left: 4px solid var(--success-color, #28a745);
        }

        .alert-error, .alert-danger {
            background-color: rgba(220, 53, 69, 0.15);
            color: var(--danger-color, #dc3545);
            border-left: 4px solid var(--danger-color, #dc3545);
        }

        .alert-info {
            background-color: rgba(23, 162, 184, 0.15);
            color: var(--info-color, #17a2b8);
            border-left: 4px solid var(--info-color, #17a2b8);
        }

        .alert-warning {
            background-color: rgba(255, 193, 7, 0.15);
            color: var(--warning-color, #ffc107);
            border-left: 4px solid var(--warning-color, #ffc107);
        }

        .alert-close {
            position: absolute;
            right: 10px;
            top: 8px;
            font-size: 1.2rem;
            font-weight: bold;
            cursor: pointer;
            opacity: 0.7;
        }

        .alert-close:hover {
            opacity: 1;
        }
    `;

    document.head.appendChild(styleEl);
}

// Add toast styles when the script loads
addToastStyles();
// Add alert styles when the script loads
addAlertStyles();

// Export the UI functions
window.ui = {
    updateProgressBar,
    showSpinner,
    hideSpinner,
    showError,
    showMessage,
    renderMarkdown,
    createDynamicFavicon,
    updateFavicon,
    showAlert
};
