/**
 * Inqyra Widget
 *
 * @package Inqyra
 */

(function() {
    'use strict';

    // Check if config is available
    if (typeof window.inqyraConfig === 'undefined') {
        console.error('Inqyra: Configuration not found');
        return;
    }

    const config = window.inqyraConfig;
    const strings = config.strings || {};

    /**
     * Inqyra Widget Class
     */
    class InqyraWidget {
        constructor() {
            this.historyLoaded = false;

            if (config.conversationPersist) {
                // Try to restore session from localStorage
                const storedSession = localStorage.getItem('inqyra_session');
                const storedToken = localStorage.getItem('inqyra_session_token');
                if (storedSession && storedToken) {
                    this.sessionId = storedSession;
                    this.sessionToken = storedToken;
                } else {
                    this.sessionId = 'sess_' + this.generateId();
                    this.sessionToken = '';
                }
            } else {
                // Default: fresh session on every page load
                this.sessionId = 'sess_' + this.generateId();
                sessionStorage.setItem('inqyra_session', this.sessionId);
                sessionStorage.removeItem('inqyra_session_token');
                this.sessionToken = '';
            }

            this.isOpen = false;
            this.isLoading = false;
            this.messages = [];
            this.embeddingsReady = false;
            this.embeddingsLoading = false;

            this.init();
        }

        /**
         * Initialize the widget
         */
        init() {
            this.createWidget();
            this.attachEventListeners();

            // Auto-open if widget was open on previous page
            if (config.conversationPersist && localStorage.getItem('inqyra_widget_open') === '1') {
                this.open();
            }
        }

        /**
         * Lazy-load Transformers.js and initialize the embedding pipeline.
         * Called when the chat is opened for the first time.
         */
        async loadEmbeddings() {
            if (this.embeddingsReady || this.embeddingsLoading || !config.browserEmbeddings) {
                return;
            }

            this.embeddingsLoading = true;

            try {
                const module = await import(config.transformersUrl);
                const pipeline = module.pipeline;
                let embeddingPipeline = null;

                window.inqyraGetQueryEmbedding = async function(text) {
                    if (!embeddingPipeline) {
                        embeddingPipeline = await pipeline('feature-extraction', 'Xenova/paraphrase-multilingual-MiniLM-L12-v2');
                    }
                    const result = await embeddingPipeline(text, { pooling: 'mean', normalize: true });
                    return Array.from(result.data);
                };

                this.embeddingsReady = true;
            } catch (e) {
                console.warn('Inqyra: Could not load embeddings module', e);
            } finally {
                this.embeddingsLoading = false;
            }
        }

        /**
         * Create the widget HTML
         */
        createWidget() {
            const container = document.getElementById('inqyra-widget-container');
            if (!container) return;

            const position = config.position || 'bottom-right';
            const primaryColor = config.primaryColor || '#5B7FFF';
            const textColor = config.textColor || '#ffffff';

            // Inject CSS variables for dynamic theming
            this.injectThemeStyles(primaryColor);

            container.innerHTML = `
                <div id="inqyra-widget" class="inqyra-widget inqyra-position-${position}">
                    <button id="inqyra-toggle" class="inqyra-toggle" style="background-color: ${primaryColor}; color: ${textColor};">
                        <span class="inqyra-toggle-icon inqyra-icon-chat">
                            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
                            </svg>
                        </span>
                        <span class="inqyra-toggle-icon inqyra-icon-close" style="display: none;">
                            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <line x1="18" y1="6" x2="6" y2="18"></line>
                                <line x1="6" y1="6" x2="18" y2="18"></line>
                            </svg>
                        </span>
                        ${config.buttonText ? `<span class="inqyra-toggle-text">${this.escapeHtml(config.buttonText)}</span>` : ''}
                    </button>

                    <div id="inqyra-container" class="inqyra-container" style="display: none;">
                        <div class="inqyra-header" style="background-color: ${primaryColor}; color: ${textColor};">
                            ${config.headerIconUrl ? `<img class="inqyra-header-icon" src="${this.escapeHtml(config.headerIconUrl)}" alt="">` : ''}
                            <div class="inqyra-header-info">
                                <h3 class="inqyra-header-title">${this.escapeHtml(config.headerTitle || 'Chat')}</h3>
                                ${config.headerSubtitle ? `<p class="inqyra-header-subtitle">${this.escapeHtml(config.headerSubtitle)}</p>` : ''}
                            </div>
                            <button id="inqyra-close" class="inqyra-close" aria-label="Close">
                                <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                    <line x1="18" y1="6" x2="6" y2="18"></line>
                                    <line x1="6" y1="6" x2="18" y2="18"></line>
                                </svg>
                            </button>
                        </div>

                        <div id="inqyra-messages" class="inqyra-messages"></div>

                        <div class="inqyra-input-container">
                            <textarea
                                id="inqyra-input"
                                class="inqyra-input"
                                placeholder="${this.escapeHtml(strings.placeholder || 'Ask a question...')}"
                                rows="1"
                            ></textarea>
                            <button id="inqyra-send" class="inqyra-send${this.getSendButtonClass()}" disabled>
                                ${this.getSendButtonContent()}
                            </button>
                        </div>

                        ${config.poweredBy ? `<div class="inqyra-footer">${config.poweredByUrl ? `<a href="${this.escapeHtml(config.poweredByUrl)}" target="_blank" rel="noopener noreferrer">${this.escapeHtml(config.poweredBy)}</a>` : this.escapeHtml(config.poweredBy)}</div>` : ''}
                    </div>
                </div>
            `;

            // Store references
            this.widget = document.getElementById('inqyra-widget');
            this.toggleBtn = document.getElementById('inqyra-toggle');
            this.container = document.getElementById('inqyra-container');
            this.messagesEl = document.getElementById('inqyra-messages');
            this.inputEl = document.getElementById('inqyra-input');
            this.sendBtn = document.getElementById('inqyra-send');
            this.closeBtn = document.getElementById('inqyra-close');

            // Show greeting if set
            if (config.greeting) {
                this.addMessage('assistant', config.greeting);
            }
        }

        /**
         * Attach event listeners
         */
        attachEventListeners() {
            // Toggle chat
            this.toggleBtn.addEventListener('click', () => this.toggle());
            this.closeBtn.addEventListener('click', () => this.close());

            // Send message
            this.sendBtn.addEventListener('click', () => this.sendMessage());

            // Input handling
            this.inputEl.addEventListener('input', () => this.handleInput());
            this.inputEl.addEventListener('keydown', (e) => {
                if (e.key === 'Enter' && !e.shiftKey) {
                    e.preventDefault();
                    this.sendMessage();
                }
            });

            // Auto-resize textarea
            this.inputEl.addEventListener('input', () => {
                this.inputEl.style.height = 'auto';
                this.inputEl.style.height = Math.min(this.inputEl.scrollHeight, 120) + 'px';
            });
        }

        /**
         * Toggle chat open/closed
         */
        toggle() {
            if (this.isOpen) {
                this.close();
            } else {
                this.open();
            }
        }

        /**
         * Open chat
         */
        open() {
            this.isOpen = true;
            this.container.style.display = 'flex';
            this.widget.classList.add('inqyra-open');
            this.toggleBtn.querySelector('.inqyra-icon-chat').style.display = 'none';
            this.toggleBtn.querySelector('.inqyra-icon-close').style.display = 'inline-block';
            this.inputEl.focus();
            this.scrollToBottom();

            if (config.conversationPersist) {
                localStorage.setItem('inqyra_widget_open', '1');
            }

            // Load persisted conversation history on first open
            if (config.conversationPersist && !this.historyLoaded && this.sessionToken) {
                this.historyLoaded = true;
                this.loadConversationHistory();
            }

            // Lazy-load embeddings on first open (no await — loads in background)
            this.loadEmbeddings();
        }

        /**
         * Close chat
         */
        close() {
            this.isOpen = false;
            this.container.style.display = 'none';
            this.widget.classList.remove('inqyra-open');
            this.toggleBtn.querySelector('.inqyra-icon-chat').style.display = 'inline-block';
            this.toggleBtn.querySelector('.inqyra-icon-close').style.display = 'none';

            if (config.conversationPersist) {
                localStorage.removeItem('inqyra_widget_open');
            }
        }

        /**
         * Handle input changes
         */
        handleInput() {
            const hasText = this.inputEl.value.trim().length > 0;
            this.sendBtn.disabled = !hasText || this.isLoading;
        }

        /**
         * Send a message
         */
        async sendMessage() {
            const message = this.inputEl.value.trim();
            if (!message || this.isLoading) return;

            // Clear input
            this.inputEl.value = '';
            this.inputEl.style.height = 'auto';
            this.handleInput();

            // Add user message
            this.addMessage('user', message);

            // Show typing indicator
            this.showTyping();

            try {
                // Get query embedding if available
                let queryEmbedding = null;
                if (this.embeddingsReady && typeof window.inqyraGetQueryEmbedding === 'function') {
                    try {
                        queryEmbedding = await window.inqyraGetQueryEmbedding(message);
                    } catch (e) {
                        console.warn('Inqyra: Could not generate query embedding', e);
                    }
                }

                // Send to API
                const response = await this.fetchChat(message, queryEmbedding);

                // Hide typing and show response
                this.hideTyping();

                if (response.success) {
                    this.addMessage('assistant', response.response);
                    if (response.session_id) {
                        this.sessionId = response.session_id;
                        sessionStorage.setItem('inqyra_session', this.sessionId);
                    }
                    if (response.session_token) {
                        this.sessionToken = response.session_token;
                        sessionStorage.setItem('inqyra_session_token', this.sessionToken);
                    }
                    if (config.conversationPersist) {
                        localStorage.setItem('inqyra_session', this.sessionId);
                        localStorage.setItem('inqyra_session_token', this.sessionToken);
                    }
                } else {
                    this.addMessage('assistant', strings.error || 'An error occurred. Please try again.');
                }

            } catch (error) {
                console.error('Inqyra error:', error);
                this.hideTyping();

                if (!navigator.onLine) {
                    this.addMessage('assistant', strings.offline || 'No internet connection.');
                } else if (error.status === 429) {
                    this.addMessage('assistant', strings.rateLimit || 'Too many messages. Please wait.');
                } else {
                    this.addMessage('assistant', strings.error || 'An error occurred. Please try again.');
                }
            }
        }

        /**
         * Fetch chat response from API
         */
        async fetchChat(message, queryEmbedding = null) {
            this.isLoading = true;

            const body = {
                agent_id: config.agentId,
                message: message,
                session_id: this.sessionId,
            };

            if (queryEmbedding) {
                body.query_embedding = queryEmbedding;
            }

            try {
                const response = await fetch(config.restUrl + '/chat', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        'X-WP-Nonce': config.nonce,
                    },
                    body: JSON.stringify(body),
                });

                if (!response.ok) {
                    const error = new Error('API request failed');
                    error.status = response.status;
                    throw error;
                }

                return await response.json();

            } finally {
                this.isLoading = false;
            }
        }

        /**
         * Add a message to the chat
         */
        addMessage(role, content) {
            const messageEl = document.createElement('div');
            messageEl.className = `inqyra-message inqyra-message-${role}`;

            // Add icon for assistant messages if enabled
            if (role === 'assistant' && config.showIconInMessages && config.headerIconUrl) {
                const iconEl = document.createElement('img');
                iconEl.className = 'inqyra-message-icon';
                iconEl.src = config.headerIconUrl;
                iconEl.alt = '';
                messageEl.appendChild(iconEl);
            }

            const contentEl = document.createElement('div');
            contentEl.className = 'inqyra-message-content';
            contentEl.innerHTML = this.formatMessage(content);

            // Apply primary color to user messages
            if (role === 'user') {
                const primaryColor = config.primaryColor || '#5B7FFF';
                contentEl.style.backgroundColor = primaryColor;
            }

            messageEl.appendChild(contentEl);
            this.messagesEl.appendChild(messageEl);

            this.messages.push({ role, content });
            this.scrollToBottom();
        }

        /**
         * Format message content (basic markdown)
         */
        formatMessage(content) {
            // Escape HTML first
            let formatted = this.escapeHtml(content);

            // Code blocks: ```code``` (must be before other formatting)
            formatted = formatted.replace(/```(\w*)\n?([\s\S]*?)```/g, '<pre><code>$2</code></pre>');

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

            // Bold: **text** or __text__
            formatted = formatted.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
            formatted = formatted.replace(/__(.*?)__/g, '<strong>$1</strong>');

            // Italic: *text* or _text_ (but not within URLs or words with underscores)
            formatted = formatted.replace(/(?<!\w)\*([^*]+)\*(?!\w)/g, '<em>$1</em>');
            formatted = formatted.replace(/(?<!\w)_([^_]+)_(?!\w)/g, '<em>$1</em>');

            // Strikethrough: ~~text~~
            formatted = formatted.replace(/~~(.*?)~~/g, '<del>$1</del>');

            // Headings: ### text (at start of line)
            formatted = formatted.replace(/^#### (.+)$/gm, '<strong class="inqyra-h4">$1</strong>');
            formatted = formatted.replace(/^### (.+)$/gm, '<strong class="inqyra-h3">$1</strong>');
            formatted = formatted.replace(/^## (.+)$/gm, '<strong class="inqyra-h2">$1</strong>');
            formatted = formatted.replace(/^# (.+)$/gm, '<strong class="inqyra-h1">$1</strong>');

            // Horizontal rule: --- or ***
            formatted = formatted.replace(/^(-{3,}|\*{3,})$/gm, '<hr>');

            // Markdown links: [text](url) — only allow safe URL schemes
            formatted = formatted.replace(/\[([^\]]+)\]\(([^)]+)\)/g, function(match, text, url) {
                if (/^(https?:|mailto:|\/)/.test(url)) {
                    return '<a href="' + url + '" target="_blank" rel="noopener">' + text + '</a>';
                }
                return text;
            });

            // Auto-link URLs (not already inside an href or anchor tag)
            formatted = formatted.replace(/(?<!href="|">)(https?:\/\/[^\s<]+)/g, '<a href="$1" target="_blank" rel="noopener">$1</a>');

            // Auto-link email addresses
            formatted = formatted.replace(/(?<!href="mailto:)([a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,})/g, '<a href="mailto:$1">$1</a>');

            // Auto-link phone numbers (international and local formats)
            formatted = formatted.replace(/(?<![\d\-])(\+?\d[\d\s\-().]{7,}\d)(?![\d\-])/g, function(match) {
                const cleaned = match.replace(/[\s\-().]/g, '');
                return '<a href="tel:' + cleaned + '">' + match + '</a>';
            });

            // Unordered lists: lines starting with - or *
            formatted = formatted.replace(/^[\-\*] (.+)$/gm, '<li>$1</li>');
            formatted = formatted.replace(/((?:<li>.*<\/li>\n?)+)/g, '<ul>$1</ul>');

            // Ordered lists: lines starting with 1. 2. etc.
            formatted = formatted.replace(/^\d+\. (.+)$/gm, '<li>$1</li>');
            // Wrap consecutive <li> not already in <ul> into <ol>
            formatted = formatted.replace(/(?<!<\/ul>)((?:<li>.*<\/li>\n?)+)(?!<\/ul>)/g, function(match) {
                // Only wrap in <ol> if not already wrapped in <ul>
                if (match.indexOf('<ul>') === -1) {
                    return '<ol>' + match + '</ol>';
                }
                return match;
            });

            // Blockquote: > text
            formatted = formatted.replace(/^&gt; (.+)$/gm, '<blockquote>$1</blockquote>');
            // Merge consecutive blockquotes
            formatted = formatted.replace(/<\/blockquote>\n?<blockquote>/g, '<br>');

            // Line breaks (but not inside block elements)
            formatted = formatted.replace(/\n/g, '<br>');

            // Clean up: remove <br> after block elements
            formatted = formatted.replace(/<\/(ul|ol|pre|blockquote|hr)><br>/g, '</$1>');
            formatted = formatted.replace(/<br><(ul|ol|pre|blockquote|hr)/g, '<$1');

            return formatted;
        }

        /**
         * Show typing indicator
         */
        showTyping() {
            this.isLoading = true;
            this.handleInput();

            const typingEl = document.createElement('div');
            typingEl.id = 'inqyra-typing';
            typingEl.className = 'inqyra-message inqyra-message-assistant inqyra-typing';

            // Add icon if enabled
            const iconHtml = (config.showIconInMessages && config.headerIconUrl)
                ? `<img class="inqyra-message-icon" src="${this.escapeHtml(config.headerIconUrl)}" alt="">`
                : '';

            typingEl.innerHTML = `
                ${iconHtml}
                <div class="inqyra-message-content">
                    <div class="inqyra-typing-dots">
                        <span></span>
                        <span></span>
                        <span></span>
                    </div>
                </div>
            `;

            this.messagesEl.appendChild(typingEl);
            this.scrollToBottom();
        }

        /**
         * Hide typing indicator
         */
        hideTyping() {
            this.isLoading = false;
            this.handleInput();

            const typingEl = document.getElementById('inqyra-typing');
            if (typingEl) {
                typingEl.remove();
            }
        }

        /**
         * Scroll messages to bottom
         */
        scrollToBottom() {
            this.messagesEl.scrollTop = this.messagesEl.scrollHeight;
        }

        /**
         * Get or create session ID
         */
        getOrCreateSessionId() {
            let sessionId = sessionStorage.getItem('inqyra_session');
            if (!sessionId) {
                sessionId = 'sess_' + this.generateId();
                sessionStorage.setItem('inqyra_session', sessionId);
            }
            return sessionId;
        }

        /**
         * Generate random ID
         */
        generateId() {
            return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
        }

        /**
         * Load conversation history from server
         */
        async loadConversationHistory() {
            // Skip if no session token (first visit, no history to load)
            if (!this.sessionToken) {
                return;
            }

            try {
                const response = await fetch(config.restUrl + '/conversation/' + this.sessionId + '?token=' + encodeURIComponent(this.sessionToken), {
                    headers: {
                        'X-WP-Nonce': config.nonce,
                    },
                });

                if (response.ok) {
                    const data = await response.json();
                    if (data.success && data.messages && data.messages.length > 0) {
                        // Clear greeting if we have history
                        if (this.messages.length === 1 && config.greeting) {
                            this.messagesEl.innerHTML = '';
                            this.messages = [];
                        }

                        data.messages.forEach(msg => {
                            this.addMessage(msg.role, msg.content);
                        });
                    }
                }
            } catch (e) {
                console.warn('Inqyra: Could not load conversation history', e);
            }
        }

        /**
         * Escape HTML entities
         */
        escapeHtml(text) {
            const div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }

        /**
         * Get the CSS class for the send button
         */
        getSendButtonClass() {
            // Styling handled via CSS :has(.inqyra-send-text)
            return '';
        }

        /**
         * Get the content for the send button
         */
        getSendButtonContent() {
            const hasCustomIcon = config.sendButtonIconUrl;
            const hasText = config.sendButtonText;

            // Default: show default SVG icon
            const defaultIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                <line x1="22" y1="2" x2="11" y2="13"></line>
                <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
            </svg>`;

            // Custom icon
            const customIcon = hasCustomIcon
                ? `<span class="inqyra-send-icon"><img src="${this.escapeHtml(config.sendButtonIconUrl)}" alt=""></span>`
                : '';

            // Text
            const text = hasText
                ? `<span class="inqyra-send-text">${this.escapeHtml(config.sendButtonText)}</span>`
                : '';

            // If no custom icon and no text, use default icon
            if (!hasCustomIcon && !hasText) {
                return defaultIcon;
            }

            // If has custom icon but no text, use custom icon only
            if (hasCustomIcon && !hasText) {
                return customIcon;
            }

            // If has text but no custom icon, use default icon + text
            if (!hasCustomIcon && hasText) {
                return defaultIcon + text;
            }

            // Has both custom icon and text
            return customIcon + text;
        }

        /**
         * Inject theme styles for dynamic primary color
         */
        injectThemeStyles(primaryColor) {
            const styleId = 'inqyra-theme-styles';
            let styleEl = document.getElementById(styleId);

            if (!styleEl) {
                styleEl = document.createElement('style');
                styleEl.id = styleId;
                document.head.appendChild(styleEl);
            }

            const textColor = config.textColor || '#ffffff';
            styleEl.textContent = `
                .inqyra-input:focus {
                    border-color: ${primaryColor} !important;
                }
                .inqyra-message-assistant .inqyra-message-content a {
                    color: ${primaryColor};
                }
                .inqyra-message-assistant .inqyra-message-content a:hover {
                    color: ${primaryColor};
                    filter: brightness(0.85);
                }
                .inqyra-toggle {
                    background-color: ${primaryColor} !important;
                    color: ${textColor} !important;
                }
                .inqyra-send {
                    background-color: ${primaryColor} !important;
                    color: ${textColor} !important;
                }
                .inqyra-header {
                    background-color: ${primaryColor} !important;
                    color: ${textColor} !important;
                }
                .inqyra-header-title {
                    color: ${textColor} !important;
                }
                .inqyra-header-subtitle {
                    color: ${textColor} !important;
                }
                .inqyra-message-user .inqyra-message-content {
                    color: ${textColor} !important;
                }
            `;
        }
    }

    // Initialize widget when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => new InqyraWidget());
    } else {
        new InqyraWidget();
    }

})();
