/**
 * XSS Protection utilities for Local Deep Research
 *
 * This module provides secure HTML sanitization functions to prevent
 * cross-site scripting (XSS) attacks when rendering dynamic content.
 * Uses DOMPurify for proven, security-reviewed HTML sanitization.
 */

(function() {
    'use strict';

    // Check if DOMPurify is available (should be loaded via app.js/Vite)
    const hasDOMPurify = typeof DOMPurify !== 'undefined';

    /**
     * HTML entity encoding map for XSS prevention
     */
    const HTML_ESCAPE_MAP = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#39;',
        '/': '&#x2F;'
    };

    /**
     * DOMPurify configuration for secure sanitization
     */
    const SANITIZE_CONFIG = {
        ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'span', 'br', 'p', 'div', 'ul', 'ol', 'li', 'a', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
        ALLOWED_ATTR: ['class', 'id', 'href', 'title', 'alt', 'target'],
        ALLOW_DATA_ATTR: false,
        FORBID_TAGS: ['script', 'iframe', 'object', 'embed', 'form', 'input', 'button', 'style', 'meta', 'link'],
        FORBID_ATTR: ['onerror', 'onload', 'onclick', 'onmouseover', 'onfocus', 'onblur', 'onchange', 'onsubmit', 'on*'],
        KEEP_CONTENT: false,
        SANITIZE_DOM: true,
        SANITIZE_NAMED_PROPS: true,
        SAFE_FOR_TEMPLATES: true,
        WHOLE_DOCUMENT: false,
        RETURN_DOM: false,
        RETURN_DOM_FRAGMENT: false,
        RETURN_DOM_IMPORT: false,
        CUSTOM_ELEMENT_HANDLING: {
            tagNameCheck: null,
            attributeNameCheck: null,
            allowCustomizedBuiltInElements: false
        }
    };

    /**
     * Escape HTML entities in a string to prevent XSS
     * @param {string} text - The text to escape
     * @returns {string} - The escaped text safe for HTML content
     */
    function escapeHtml(text) {
    if (typeof text !== 'string') {
        text = String(text);
    }

    return text.replace(/[&<>"'/]/g, (match) => HTML_ESCAPE_MAP[match]);
}

/**
 * Escape HTML attributes to prevent XSS
 * @param {string} text - The text to escape for attribute context
 * @returns {string} - The escaped text safe for HTML attributes
 */
function escapeHtmlAttribute(text) {
    if (typeof text !== 'string') {
        text = String(text);
    }

    // For attributes, we need to escape quotes and ampersands
    return text.replace(/["&'<>]/g, (match) => HTML_ESCAPE_MAP[match]);
}

/**
 * Safely set innerHTML with content sanitization using DOMPurify
 * @param {Element} element - The DOM element to update
 * @param {string} content - The content to set (will be sanitized)
 * @param {boolean} allowHtmlTags - If true, allows basic HTML tags, otherwise escapes everything
 */
function safeSetInnerHTML(element, content, allowHtmlTags = false) {
    if (!element || !content) {
        return;
    }

    const contentString = String(content);

    if (allowHtmlTags && hasDOMPurify) {
        // Use DOMPurify for secure HTML sanitization
        const sanitized = DOMPurify.sanitize(contentString, SANITIZE_CONFIG);
        element.innerHTML = sanitized;
    } else if (allowHtmlTags) {
        // DOMPurify not available but HTML requested - escape all HTML for safety
        console.warn('DOMPurify not available, escaping HTML instead of sanitizing');
        element.textContent = contentString;
    } else {
        // Escape all HTML - use textContent for maximum security
        element.textContent = contentString;
    }
}

/**
 * Create a safe DOM element with text content
 * @param {string} tagName - The HTML tag name
 * @param {string} text - The text content (will be escaped)
 * @param {Object} attributes - Optional attributes object
 * @param {string[]} classNames - Optional CSS class names
 * @returns {Element} - The created DOM element
 */
function safeCreateElement(tagName, text = '', attributes = {}, classNames = []) {
    const element = document.createElement(tagName);

    if (text) {
        element.textContent = text; // Safe - no HTML interpretation
    }

    // Set attributes safely
    Object.entries(attributes).forEach(([key, value]) => {
        if (key && value !== null && value !== undefined) {
            element.setAttribute(key, escapeHtmlAttribute(String(value)));
        }
    });

    // Add CSS classes safely
    if (classNames.length > 0) {
        element.className = classNames.join(' ');
    }

    return element;
}

/**
 * Safe text content setter that prevents XSS
 * @param {Element} element - The DOM element to update
 * @param {string} content - The content to set safely
 */
function safeSetTextContent(element, content) {
    if (!element) {
        return;
    }

    element.textContent = String(content || '');
}

/**
 * Create a safe alert message element
 * @param {string} message - The alert message (will be escaped)
 * @param {string} type - Alert type (success, error, warning, info)
 * @returns {Element} - The created alert element
 */
function createSafeAlertElement(message, type = 'info') {
    const alert = document.createElement('div');
    alert.className = `alert alert-${type}`;

    // Create icon
    const iconMap = {
        'success': 'fa-check-circle',
        'error': 'fa-exclamation-circle',
        'warning': 'fa-exclamation-triangle',
        'info': 'fa-info-circle'
    };

    const icon = document.createElement('i');
    icon.className = `fas ${iconMap[type] || iconMap['info']}`;

    // Create message text (escaped)
    const messageText = document.createElement('span');
    messageText.textContent = message; // Safe - textContent prevents HTML injection

    // Create close button
    const closeBtn = document.createElement('span');
    closeBtn.className = 'ldr-alert-close';
    closeBtn.textContent = '×';
    closeBtn.addEventListener('click', () => {
        alert.remove();
    });

    // Assemble alert
    alert.appendChild(icon);
    alert.appendChild(messageText);
    alert.appendChild(closeBtn);

    return alert;
}

/**
 * Secure HTML sanitization using DOMPurify
 * @param {string} dirty - The potentially dirty HTML string
 * @param {Object} config - Optional DOMPurify configuration overrides
 * @returns {string} - The sanitized HTML string
 */
function sanitizeHtml(dirty, config = {}) {
    if (!dirty) return '';

    if (hasDOMPurify) {
        const finalConfig = { ...SANITIZE_CONFIG, ...config };
        return DOMPurify.sanitize(String(dirty), finalConfig);
    } else {
        // Fallback: escape all HTML if DOMPurify is not available
        console.warn('DOMPurify not available, falling back to HTML escaping');
        return escapeHtml(String(dirty));
    }
}

/**
 * Validate and sanitize user input for safe display
 * @param {any} input - The input to validate and sanitize
 * @param {Object} options - Sanitization options
 * @returns {string} - The sanitized string
 */
function sanitizeUserInput(input, options = {}) {
    const {
        maxLength = 10000,
        allowLineBreaks = true,
        trimWhitespace = true,
        allowHtml = false
    } = options;

    if (input === null || input === undefined) {
        return '';
    }

    let sanitized = String(input);

    // Trim if requested
    if (trimWhitespace) {
        sanitized = sanitized.trim();
    }

    // Enforce max length
    if (sanitized.length > maxLength) {
        sanitized = sanitized.substring(0, maxLength);
    }

    // Handle line breaks
    if (allowLineBreaks) {
        sanitized = sanitized.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
    }

    // Either escape HTML or sanitize it
    if (allowHtml) {
        return sanitizeHtml(sanitized);
    } else {
        return escapeHtml(sanitized);
    }
}

  // Export to global scope
    window.XSSProtection = {
        escapeHtml: escapeHtml,
        escapeHtmlAttribute: escapeHtmlAttribute,
        safeSetInnerHTML: safeSetInnerHTML,
        safeCreateElement: safeCreateElement,
        safeSetTextContent: safeSetTextContent,
        createSafeAlertElement: createSafeAlertElement,
        sanitizeUserInput: sanitizeUserInput,
        sanitizeHtml: sanitizeHtml
    };

    /**
     * Safely update button content with icon and text
     * @param {HTMLElement} button - The button element to update
     * @param {string} iconClass - Font Awesome icon class (without 'fas')
     * @param {string} text - Button text content
     * @param {boolean} addSpinner - Whether to add spinner animation
     */
    function safeUpdateButton(button, iconClass, text, addSpinner = false) {
        if (!button) return;

        // Clear existing content
        while (button.firstChild) {
            button.removeChild(button.firstChild);
        }

        // Create icon
        const icon = document.createElement('i');
        icon.className = `fas ${iconClass}`;
        if (addSpinner) {
            icon.className += ' fa-spin';
        }

        // Add icon and text
        button.appendChild(icon);
        if (text) {
            button.appendChild(document.createTextNode(text));
        }
    }

    /**
     * Create a loading overlay with safe DOM manipulation
     * @param {Object} options - Loading overlay options
     * @returns {HTMLElement} - The created loading overlay element
     */
    function createSafeLoadingOverlay(options = {}) {
        const {
            iconClass = 'fa-spinner fa-spin fa-3x',
            title = 'Loading...',
            description = 'Please wait...',
            iconMarginBottom = '20px',
            titleMargin = '10px 0',
            textOpacity = '0.8'
        } = options;

        const overlay = document.createElement('div');
        overlay.className = 'ldr-loading-overlay';

        const content = document.createElement('div');
        content.className = 'ldr-loading-content';
        content.style.textAlign = 'center';

        // Icon
        const icon = document.createElement('i');
        icon.className = `fas ${iconClass}`;
        icon.style.marginBottom = iconMarginBottom;

        // Title
        const titleElement = document.createElement('h3');
        titleElement.style.margin = titleMargin;
        titleElement.textContent = title;

        // Description
        const descriptionElement = document.createElement('p');
        descriptionElement.style.opacity = textOpacity;
        descriptionElement.textContent = description;

        // Assemble overlay
        content.appendChild(icon);
        content.appendChild(titleElement);
        content.appendChild(descriptionElement);
        overlay.appendChild(content);

        return overlay;
    }

    /**
     * Safely set CSS styles on an element
     * @param {HTMLElement} element - The element to style
     * @param {Object} styles - Style object with CSS properties
     */
    function safeSetStyles(element, styles) {
        if (!element || !styles) return;

        Object.entries(styles).forEach(([property, value]) => {
            element.style[property] = value;
        });
    }

    /**
     * Show a safe alert message
     * @param {string} containerId - ID of the alert container
     * @param {string} message - Alert message (will be sanitized)
     * @param {string} type - Alert type (success, error, warning, info)
     */
    function showSafeAlert(containerId, message, type = 'info') {
        const alertContainer = document.getElementById(containerId);
        if (!alertContainer) return;

        // Clear existing alerts
        while (alertContainer.firstChild) {
            alertContainer.removeChild(alertContainer.firstChild);
        }

        // Create alert using our secure method
        const alert = createSafeAlertElement(message, type);
        alertContainer.appendChild(alert);
    }

    // Also export individual functions for convenience
    window.escapeHtml = escapeHtml;
    window.escapeHtmlAttribute = escapeHtmlAttribute;
    window.safeSetInnerHTML = safeSetInnerHTML;
    window.safeCreateElement = safeCreateElement;
    window.safeSetTextContent = safeSetTextContent;
    window.createSafeAlertElement = createSafeAlertElement;
    window.sanitizeUserInput = sanitizeUserInput;
    window.sanitizeHtml = sanitizeHtml;

    // Export UI helper functions
    window.safeUpdateButton = safeUpdateButton;
    window.createSafeLoadingOverlay = createSafeLoadingOverlay;
    window.safeSetStyles = safeSetStyles;
    window.showSafeAlert = showSafeAlert;

})();
