<?php
/*
Plugin Name: OpenRouter Chatbot
Description: Adds a popup OpenRouter chatbot to the bottom-right corner of each page.
Version: 2.2
Author: Your Name
*/

// Hook into 'wp' to safely access is_user_logged_in and user meta
add_action('wp', function () {
    if (!is_user_logged_in()) return;

    $user       = wp_get_current_user();
    $user_level = get_user_meta($user->ID, 'custom_category_access_level', true);

    if (
        in_array('administrator', (array) $user->roles, true)
        || $user_level === 'level_3'
        || $user_level === 'level_0'
    ) {
        add_action('wp_enqueue_scripts', function () {
            // Load jQuery and Marked.js
            wp_enqueue_script('jquery');
            wp_enqueue_script('marked-js', 'https://cdn.jsdelivr.net/npm/marked/marked.min.js', array(), null, true);

            // Localize post data for all pages
            $post_data = array(
                'is_singular' => false,
                'content' => '',
                'title' => '',
                'permalink' => get_home_url(),
                'site_name' => get_bloginfo('name'),
                'page_type' => 'general',
                'is_long_content' => false, // Flag for RAG system
                'word_count' => 0
            );

            if (is_singular()) {
                global $post;
                $post_content = apply_filters('the_content', $post->post_content);
                $stripped_content = wp_strip_all_tags(preg_replace('#<script(.*?)>(.*?)</script>#is', '', $post_content)); // Also remove script tags
                $word_count = str_word_count($stripped_content);

                $post_data = array(
                    'content' => $stripped_content,
                    'title' => get_the_title($post->ID),
                    'permalink' => get_permalink($post->ID),
                    'is_singular' => true,
                    'site_name' => get_bloginfo('name'),
                    'page_type' => get_post_type(),
                    'is_long_content' => $word_count > 1000, // Check if content is over 1000 words
                    'word_count' => $word_count
                );
            } elseif (is_home() || is_front_page()) {
                $post_data['page_type'] = 'homepage';
                $post_data['title'] = get_bloginfo('name') . ' - Home';
            } elseif (is_category()) {
                $post_data['page_type'] = 'category';
                $post_data['title'] = single_cat_title('', false);
            } elseif (is_tag()) {
                $post_data['page_type'] = 'tag';
                $post_data['title'] = single_tag_title('', false);
            } elseif (is_archive()) {
                $post_data['page_type'] = 'archive';
                $post_data['title'] = get_the_archive_title();
            }

            wp_localize_script('jquery', 'postData', $post_data);
        });

        add_action('wp_footer', function () {
            global $post;
            $site_name = get_bloginfo('name');
            $site_url = get_home_url();
            ?>
            <style>
                #openrouter-chatbot-container {
                    position: fixed;
                    bottom: 20px;
                    right: 20px;
                    z-index: 9999;
                    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
                }

                #openrouter-chat-toggle {
                    margin-bottom : 8px ;
                    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                    color: white;
                    padding: 15px;
                    border-radius: 50%;
                    cursor: pointer;
                    font-size: 22px;
                    text-align: center;
                    box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
                    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
                    width: 60px;
                    height: 60px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    border: none;
                    position: relative;
                    overflow: hidden;
                }

                #openrouter-chat-toggle::before {
                    content: '';
                    position: absolute;
                    top: 0;
                    left: 0;
                    right: 0;
                    bottom: 0;
                    background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
                    opacity: 0;
                    transition: opacity 0.3s ease;
                }

                #openrouter-chat-toggle:hover::before {
                    opacity: 1;
                }

                #openrouter-chat-toggle:hover {
                    transform: translateY(-2px) scale(1.05);
                    box-shadow: 0 12px 35px rgba(102, 126, 234, 0.6);
                }

                #openrouter-chat-toggle span {
                    position: relative;
                    z-index: 1;
                }

                #openrouter-chatbox {
                    width: 350px;
                    height: 480px;
                    background: white;
                    border: none;
                    border-radius: 20px;
                    overflow: hidden;
                    display: none; /* Hidden by default */
                    flex-direction: column;
                    margin-bottom: 15px;
                    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);
                    backdrop-filter: blur(10px);
                    transform: translateY(10px) scale(0.95);
                    opacity: 0;
                    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
                }

                #openrouter-chatbox.visible {
                    display: flex;
                    transform: translateY(0) scale(1);
                    opacity: 1;
                }

                #chat-header {
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    padding: 20px 20px 15px;
                    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                    color: white;
                    font-weight: 600;
                    font-size: 16px;
                    position: relative;
                    flex-shrink: 0; /* Prevents header from shrinking */
                }
                
                #chat-header-buttons {
                    display: flex;
                    align-items: center;
                    gap: 10px;
                }
                
                #close-chat-btn {
                    background: none;
                    border: none;
                    color: white;
                    font-size: 28px;
                    font-weight: 400;
                    line-height: 1;
                    padding: 0 5px;
                    cursor: pointer;
                    opacity: 0.8;
                    transition: opacity 0.2s;
                    display: none; /* Hidden by default on desktop */
                }
                #close-chat-btn:hover {
                    opacity: 1;
                }

                #chat-header::after {
                    content: '';
                    position: absolute;
                    bottom: 0;
                    left: 0;
                    right: 0;
                    height: 1px;
                    background: rgba(255, 255, 255, 0.2);
                }

                #clear-chat {
                    background: rgba(255, 255, 255, 0.1);
                    border: 1px solid rgba(255, 255, 255, 0.2);
                    color: white;
                    cursor: pointer;
                    font-size: 12px;
                    padding: 6px 12px;
                    border-radius: 15px;
                    transition: all 0.2s ease;
                    font-weight: 500;
                }

                #clear-chat:hover {
                    background: rgba(255, 255, 255, 0.2);
                    border-color: rgba(255, 255, 255, 0.3);
                    transform: translateY(-1px);
                }

                #chatbox {
                    flex: 1;
                    padding: 20px;
                    overflow-y: auto;
                    font-size: 14px;
                    background: linear-gradient(to bottom, #f8fafc, #f1f5f9);
                    scrollbar-width: thin;
                    scrollbar-color: #cbd5e1 transparent;
                }

                #chatbox::-webkit-scrollbar { width: 6px; }
                #chatbox::-webkit-scrollbar-track { background: transparent; }
                #chatbox::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 3px; }
                #chatbox::-webkit-scrollbar-thumb:hover { background: #94a3b8; }

                #input-area {
                    display: flex;
                    border-top: 1px solid #e2e8f0;
                    background: white;
                    padding: 15px;
                    gap: 10px;
                    flex-shrink: 0; /* Prevents input area from shrinking */
                }

                #userInput {
                    flex: 1;
                    padding: 12px 16px;
                    border: 2px solid #e2e8f0;
                    font-size: 14px;
                    border-radius: 25px;
                    outline: none;
                    transition: all 0.2s ease;
                    background: #f8fafc;
                }

                #userInput:focus {
                    border-color: #667eea;
                    background: white;
                    box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
                }
                
                #userInput:disabled {
                    background-color: #f1f5f9;
                    cursor: not-allowed;
                }

                #input-area button {
                    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                    color: white;
                    border: none;
                    padding: 12px 20px;
                    cursor: pointer;
                    font-size: 14px;
                    border-radius: 25px;
                    font-weight: 600;
                    transition: all 0.2s ease;
                    min-width: 80px; /* Adjusted width for French text */
                }
                #input-area button:hover { transform: translateY(-1px); box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4); }
                #input-area button:active { transform: translateY(0); }
                #input-area button:disabled { background: #d1d5db; cursor: not-allowed; box-shadow: none; transform: none;}

                .message { margin: 10px 0; padding: 12px 16px; border-radius: 18px; max-width: 85%; position: relative; line-height: 1.5; word-wrap: break-word; animation: messageSlide 0.3s ease-out; }
                @keyframes messageSlide { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
                .message.user { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; align-self: flex-end; margin-left: auto; border-bottom-right-radius: 6px; box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3); }
                .message.assistant { background: white; color: #374151; align-self: flex-start; border: 1px solid #e5e7eb; border-bottom-left-radius: 6px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08); }
                .message.system { background: linear-gradient(135deg, #10b981 0%, #059669 100%); color: white; align-self: center; margin: 10px auto; border-radius: 15px; font-size: 13px; text-align: center; box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3); max-width: 95%; }

                .message-actions { position: absolute; top: 8px; right: 8px; opacity: 0; transition: opacity 0.2s ease; }
                .message:hover .message-actions { opacity: 1; }
                .btn { display: inline-flex; align-items: center; justify-content: center; font-weight: 500; text-align: center; white-space: nowrap; vertical-align: middle; user-select: none; border: 1px solid transparent; padding: 6px 10px; font-size: 12px; line-height: 1; border-radius: 12px; transition: all 0.2s ease; cursor: pointer; }
                .btn-sm { padding: 4px 8px; font-size: 11px; border-radius: 10px; }
                .btn-outline { color: #6b7280; background-color: rgba(255, 255, 255, 0.9); border-color: #d1d5db; backdrop-filter: blur(5px); }
                .btn-outline:hover { color: white; background-color: #6b7280; border-color: #6b7280; transform: translateY(-1px); box-shadow: 0 4px 12px rgba(107, 114, 128, 0.3); }
                .btn svg { width: 12px; height: 12px; }

                .typing-indicator { display: flex; align-items: center; padding: 10px 0; }
                .typing-indicator span { height: 8px; width: 8px; margin: 0 3px; background-color: #cbd5e1; border-radius: 50%; display: inline-block; animation: typing-bounce 1.4s infinite ease-in-out both; }
                .typing-indicator span:nth-child(1) { animation-delay: -0.32s; }
                .typing-indicator span:nth-child(2) { animation-delay: -0.16s; }
                @keyframes typing-bounce { 0%, 80%, 100% { transform: scale(0); } 40% { transform: scale(1.0); } }

                /* Markdown styling */
                .message p { margin: 0 0 8px 0; }
                .message p:last-child { margin-bottom: 0; }
                .message code { background: rgba(0, 0, 0, 0.1); padding: 2px 6px; border-radius: 4px; font-size: 12px; font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; }
                .message.user code { background: rgba(255, 255, 255, 0.2); }
                .message pre { background: rgba(0, 0, 0, 0.05); padding: 10px; border-radius: 8px; overflow-x: auto; margin: 8px 0; }
                .message ul, .message ol { margin: 8px 0; padding-left: 20px; }
                .message li { margin: 4px 0; }

                /* Custom Modal for Confirmation */
                .confirm-modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 10000; display: none; align-items: center; justify-content: center; }
                .confirm-modal { background: white; padding: 25px; border-radius: 15px; text-align: center; box-shadow: 0 10px 30px rgba(0,0,0,0.1); max-width: 320px; }
                .confirm-modal p { margin: 0 0 20px; font-size: 16px; color: #333; }
                .confirm-modal-buttons button { padding: 10px 20px; border: none; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: 600; margin: 0 8px; }
                #confirm-ok-btn { background-color: #ef4444; color: white; }
                #confirm-cancel-btn { background-color: #e5e7eb; color: #374151; }

                /* === MOBILE DESIGN IMPROVEMENTS START === */
                @media (max-width: 768px) {
                    
                    #input-area button {
                        width: fit-content;
                    }
                    
                    
                    #openrouter-chatbot-container {
                        /* The container becomes a placeholder */
                        pointer-events: none; /* Allows clicks to go "through" it */
                    }
                    
                    #openrouter-chat-toggle {
                        pointer-events: auto; /* Re-enable pointer events for the button itself */
                    }
                    
                    #openrouter-chatbox {
                        pointer-events: auto; /* Enable interaction with the chatbox */
                        position: fixed;
                        bottom: 0;
                        right: 0;
                        left: 0;
                        width: 100%;
                        height: 65vh; /* Set height to 80% of viewport height */
                        margin: 0 ;
                        
                        border-radius: 20px 20px 0 0; /* Add rounded corners only to the top */
                        box-shadow: 0 -5px 25px rgba(0, 0, 0, 0.1);
                        /* New transform for a "slide up" animation */
                        transform: translateY(100%);
                        opacity: 1; /* Opacity is kept at 1 for the slide effect */
                        transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
                    }
                    
                    #openrouter-chatbox.visible {
                        /* Bring it into view */
                        transform: translateY(0);
                    }

                    #close-chat-btn {
                        display: block; /* Show the close button on mobile */
                    }

                    #clear-chat {
                        white-space: nowrap; /* Prevents text wrapping on mobile */
                    }

                    #chat-header {
                        padding: 15px;
                        padding-top: calc(15px + env(safe-area-inset-top)); /* Handle iPhone notch */
                    }
                    #input-area {
                        padding-bottom: calc(15px + env(safe-area-inset-bottom)); /* Handle iPhone home bar */
                    }
                    
                    .confirm-modal {
                        width: calc(100% - 40px);
                        max-width: 340px;
                    }
                }
                /* === MOBILE DESIGN IMPROVEMENTS END === */
            </style>

            <div id="openrouter-chatbot-container">
                 <div id="openrouter-chat-toggle"><span>💬</span></div>
                <div id="openrouter-chatbox">
                    <div id="chat-header">
                        <span>Assistant Kytisa</span>
                        <div id="chat-header-buttons">
                           <button id="clear-chat">Vider le Chat</button>
                           <button id="close-chat-btn">&times;</button>
                        </div>
                    </div>
                    <div id="chatbox"></div>
                    <div id="input-area">
                        <input type="text" id="userInput" placeholder="Posez-moi une question..." autocomplete="off" />
                        <button id="send-btn">Envoyer</button>
                    </div>
                </div>
            </div>

            <div class="confirm-modal-overlay" id="clear-chat-modal">
                <div class="confirm-modal">
                    <p>Êtes-vous sûr de vouloir vider tout l'historique du chat ?</p>
                    <div class="confirm-modal-buttons">
                        <button id="confirm-cancel-btn">Annuler</button>
                        <button id="confirm-ok-btn">Vider</button>
                    </div>
                </div>
            </div>

            <script>
            jQuery(document).ready(function ($) {
                // --- CONFIGURATION ---
                const apiKey = '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';

                // You can change the model here. See OpenRouter.ai for available models.
                const modelName = 'deepseek/deepseek-chat-v3-0324';

                // --- SETUP ---
                const apiUrl = 'https://openrouter.ai/api/v1/chat/completions';
                const siteUrl = '<?php echo esc_js($site_url); ?>';
                const siteTitle = '<?php echo esc_js($site_name); ?>';
                
                const copyIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>';
                const checkIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>';

                const globalSessionKey = 'openrouter_chat_global_session_v2';
                const currentPageKey = 'openrouter_current_page_v2';

                const chatboxEl = $('#openrouter-chatbox');
                const chatToggleBtn = $('#openrouter-chat-toggle');
                const chatHistoryEl = $('#chatbox');
                const userInputEl = $('#userInput');
                const sendBtn = $('#send-btn');
                const clearChatBtn = $('#clear-chat');
                const closeChatBtn = $('#close-chat-btn'); // New button selector
                const clearChatModal = $('#clear-chat-modal');
                const confirmOkBtn = $('#confirm-ok-btn');
                const confirmCancelBtn = $('#confirm-cancel-btn');

                let conversationHistory = [];
                try {
                    const storedHistory = localStorage.getItem(globalSessionKey);
                    if (storedHistory) {
                        const parsedHistory = JSON.parse(storedHistory);
                        if (Array.isArray(parsedHistory)) {
                            conversationHistory = parsedHistory;
                        }
                    }
                } catch (e) {
                    console.error("Could not parse conversation history from localStorage", e);
                    conversationHistory = [];
                }

                // --- SOLID RAG SYSTEM WITHOUT KEYWORD EXTRACTION ---

                function cleanText(text) {
                    return text.replace(/\s+/g, ' ')
                               .replace(/[^\w\sàâäéèêëîïôöùûüÿç]/gi, ' ')
                               .toLowerCase()
                               .trim();
                }

                // Advanced text similarity using multiple techniques
                function calculateTextSimilarity(query, chunk) {
                    const queryClean = cleanText(query);
                    const chunkClean = cleanText(chunk);
                    
                    if (!queryClean || !chunkClean) return 0;
                    
                    // 1. Word overlap scoring with length weighting
                    const queryWords = queryClean.split(/\s+/).filter(w => w.length > 2);
                    const chunkWords = chunkClean.split(/\s+/);
                    
                    let wordOverlapScore = 0;
                    queryWords.forEach(qWord => {
                        chunkWords.forEach(cWord => {
                            if (cWord === qWord) {
                                // Exact match gets highest score
                                wordOverlapScore += qWord.length * 2;
                            } else if (cWord.includes(qWord) || qWord.includes(cWord)) {
                                // Partial match gets proportional score
                                const similarity = Math.min(qWord.length, cWord.length) / Math.max(qWord.length, cWord.length);
                                wordOverlapScore += similarity * qWord.length;
                            }
                        });
                    });
                    
                    // 2. Character n-gram similarity (trigrams and bigrams)
                    let ngramScore = 0;
                    if (queryClean.length >= 2 && chunkClean.length >= 2) {
                        // Trigrams
                        const queryTrigrams = new Set();
                        const chunkTrigrams = new Set();
                        
                        for (let i = 0; i <= queryClean.length - 3; i++) {
                            queryTrigrams.add(queryClean.substring(i, i + 3));
                        }
                        
                        for (let i = 0; i <= chunkClean.length - 3; i++) {
                            chunkTrigrams.add(chunkClean.substring(i, i + 3));
                        }
                        
                        const trigramIntersection = new Set([...queryTrigrams].filter(x => chunkTrigrams.has(x)));
                        if (queryTrigrams.size > 0) {
                            ngramScore += (trigramIntersection.size / queryTrigrams.size) * 15;
                        }
                        
                        // Bigrams for shorter queries
                        if (queryClean.length < 20) {
                            const queryBigrams = new Set();
                            const chunkBigrams = new Set();
                            
                            for (let i = 0; i <= queryClean.length - 2; i++) {
                                queryBigrams.add(queryClean.substring(i, i + 2));
                            }
                            
                            for (let i = 0; i <= chunkClean.length - 2; i++) {
                                chunkBigrams.add(chunkClean.substring(i, i + 2));
                            }
                            
                            const bigramIntersection = new Set([...queryBigrams].filter(x => chunkBigrams.has(x)));
                            if (queryBigrams.size > 0) {
                                ngramScore += (bigramIntersection.size / queryBigrams.size) * 8;
                            }
                        }
                    }
                    
                    // 3. Longest common substring
                    let lcsScore = 0;
                    for (let i = 0; i < queryClean.length; i++) {
                        for (let j = 0; j < chunkClean.length; j++) {
                            let len = 0;
                            while (i + len < queryClean.length && 
                                   j + len < chunkClean.length && 
                                   queryClean[i + len] === chunkClean[j + len]) {
                                len++;
                            }
                            if (len > 3) { // Only count meaningful substrings
                                lcsScore += len * 0.8;
                            }
                        }
                    }
                    
                    // 4. Position bonus - earlier occurrences get higher scores
                    let positionBonus = 0;
                    queryWords.forEach(word => {
                        const index = chunkClean.indexOf(word);
                        if (index !== -1) {
                            positionBonus += Math.max(0, 2 - (index / chunkClean.length)) * word.length * 0.5;
                        }
                    });
                    
                    // 5. Density bonus - reward chunks with high query word density
                    const queryWordCount = queryWords.filter(word => chunkClean.includes(word)).length;
                    const densityBonus = queryWords.length > 0 ? (queryWordCount / queryWords.length) * 10 : 0;
                    
                    // 6. Length penalty for very short chunks
                    const lengthPenalty = chunkClean.length < 50 ? -5 : 0;
                    
                    return Math.max(0, wordOverlapScore + ngramScore + lcsScore + positionBonus + densityBonus + lengthPenalty);
                }

                // Small chunks for precise answers (80-250 words)
                function createSmallChunks(content) {
                    const sentences = content.split(/[.!?]+/).filter(s => s.trim().length > 10);
                    const chunks = [];
                    let currentChunk = '';
                    
                    for (const sentence of sentences) {
                        const cleanSentence = sentence.trim();
                        if (currentChunk.length + cleanSentence.length < 250) {
                            currentChunk += (currentChunk ? '. ' : '') + cleanSentence;
                        } else {
                            if (currentChunk.length > 30) chunks.push(currentChunk);
                            currentChunk = cleanSentence;
                        }
                    }
                    
                    if (currentChunk.length > 30) chunks.push(currentChunk);
                    return chunks;
                }

                // Medium chunks for balanced context (200-400 words)
                function createMediumChunks(content) {
                    // Try paragraph-based splitting first
                    let paragraphs = content.split(/\n\s*\n/).filter(p => p.trim().length > 20);
                    
                    if (paragraphs.length < 2) {
                        // Fallback: sentence-based splitting
                        paragraphs = content.split(/[.!?]\s+(?=[A-ZÀ-Ÿ])/).filter(p => p.trim().length > 20);
                    }
                    
                    const chunks = [];
                    let currentChunk = '';
                    
                    for (const paragraph of paragraphs) {
                        const cleanParagraph = paragraph.trim();
                        if (currentChunk.length + cleanParagraph.length < 400) {
                            currentChunk += (currentChunk ? '\n\n' : '') + cleanParagraph;
                        } else {
                            if (currentChunk.length > 50) chunks.push(currentChunk);
                            currentChunk = cleanParagraph;
                        }
                    }
                    
                    if (currentChunk.length > 50) chunks.push(currentChunk);
                    return chunks;
                }

                // Large chunks for comprehensive context (300-700 words)
                function createLargeChunks(content) {
                    // Split by major breaks
                    let sections = content.split(/\n\s*\n/).filter(s => s.trim().length > 30);
                    
                    if (sections.length < 2) {
                        // Try splitting by sentence groups
                        const sentences = content.split(/[.!?]+/).filter(s => s.trim().length > 15);
                        sections = [];
                        let currentSection = '';
                        
                        for (let i = 0; i < sentences.length; i += 3) {
                            const group = sentences.slice(i, i + 3).join('. ').trim();
                            if (group.length > 30) sections.push(group);
                        }
                    }
                    
                    const chunks = [];
                    let currentChunk = '';
                    
                    for (const section of sections) {
                        const cleanSection = section.trim();
                        if (currentChunk.length + cleanSection.length < 700) {
                            currentChunk += (currentChunk ? '\n\n' : '') + cleanSection;
                        } else {
                            if (currentChunk.length > 100) chunks.push(currentChunk);
                            currentChunk = cleanSection;
                        }
                    }
                    
                    if (currentChunk.length > 100) chunks.push(currentChunk);
                    return chunks;
                }

                // Sliding window for very large content with overlap
                function createSlidingChunks(content, windowSize = 600, overlap = 150) {
                    const chunks = [];
                    let start = 0;
                    
                    while (start < content.length) {
                        let end = Math.min(start + windowSize, content.length);
                        
                        // Try to end at a sentence boundary
                        if (end < content.length) {
                            const boundaries = ['.', '!', '?'];
                            let bestBoundary = -1;
                            
                            for (const boundary of boundaries) {
                                const pos = content.lastIndexOf(boundary, end);
                                if (pos > start + windowSize * 0.6) {
                                    bestBoundary = Math.max(bestBoundary, pos);
                                }
                            }
                            
                            if (bestBoundary > -1) {
                                end = bestBoundary + 1;
                            }
                        }
                        
                        const chunk = content.substring(start, end).trim();
                        if (chunk.length > 50) {
                            chunks.push(chunk);
                        }
                        
                        start = Math.max(start + windowSize - overlap, end - overlap);
                        if (start >= content.length - overlap) break;
                    }
                    
                    return chunks;
                }

                // Main hybrid content selection function
                function findHybridContent(query, content) {
                    if (!content || content.trim().length === 0) {
                        return content.substring(0, 1500);
                    }
                    
                    if (!query || query.trim().length === 0) {
                        return content.substring(0, 1500);
                    }
                    
                    const wordCount = postData.word_count || 0;
                    
                    // Choose strategy based on content length
                    if (wordCount > 3000) {
                        return findBestChunksFromSliding(query, content);
                    } else if (wordCount > 1500) {
                        return findBestChunksFromHybrid(query, content);
                    } else if (wordCount > 800) {
                        return findBestChunksFromMedium(query, content);
                    } else {
                        return findBestChunksFromSmall(query, content);
                    }
                }

                // Strategy for small content (< 800 words)
                function findBestChunksFromSmall(query, content) {
                    const chunks = createSmallChunks(content);
                    if (chunks.length <= 1) {
                        return chunks[0] || content.substring(0, 1200);
                    }
                    
                    const scoredChunks = chunks.map((chunk, index) => ({
                        chunk,
                        score: calculateTextSimilarity(query, chunk),
                        index,
                        length: chunk.length
                    }));
                    
                    scoredChunks.sort((a, b) => b.score - a.score);
                    
                    const selectedChunks = [];
                    let totalLength = 0;
                    const maxLength = 1200;
                    
                    for (let i = 0; i < Math.min(4, scoredChunks.length); i++) {
                        const chunk = scoredChunks[i];
                        if (chunk.score > 1 && totalLength + chunk.length <= maxLength) {
                            selectedChunks.push(chunk);
                            totalLength += chunk.length;
                        }
                    }
                    
                    if (selectedChunks.length === 0) {
                        return chunks.slice(0, 3).join('\n\n');
                    }
                    
                    selectedChunks.sort((a, b) => a.index - b.index);
                    return selectedChunks.map(item => item.chunk).join('\n\n');
                }

                // Strategy for medium content (800-1500 words)
                function findBestChunksFromMedium(query, content) {
                    const chunks = createMediumChunks(content);
                    if (chunks.length <= 1) {
                        return chunks[0] || content.substring(0, 1500);
                    }
                    
                    const scoredChunks = chunks.map((chunk, index) => ({
                        chunk,
                        score: calculateTextSimilarity(query, chunk),
                        index,
                        length: chunk.length
                    }));
                    
                    scoredChunks.sort((a, b) => b.score - a.score);
                    
                    const selectedChunks = [];
                    let totalLength = 0;
                    const maxLength = 1500;
                    
                    for (let i = 0; i < Math.min(3, scoredChunks.length); i++) {
                        const chunk = scoredChunks[i];
                        if (chunk.score > 2 && totalLength + chunk.length <= maxLength) {
                            selectedChunks.push(chunk);
                            totalLength += chunk.length;
                        }
                    }
                    
                    if (selectedChunks.length === 0) {
                        return chunks.slice(0, 2).join('\n\n');
                    }
                    
                    selectedChunks.sort((a, b) => a.index - b.index);
                    return selectedChunks.map(item => item.chunk).join('\n\n');
                }

                // Strategy for large content (1500-3000 words) - Hybrid approach
                function findBestChunksFromHybrid(query, content) {
                    const smallChunks = createSmallChunks(content);
                    const largeChunks = createLargeChunks(content);
                    
                    const allScoredChunks = [];
                    
                    // Score small chunks (precision focus)
                    smallChunks.forEach((chunk, index) => {
                        const score = calculateTextSimilarity(query, chunk);
                        if (score > 1) {
                            allScoredChunks.push({
                                chunk,
                                score: score * 1.4, // Boost for precision
                                index,
                                type: 'small',
                                originalIndex: index,
                                length: chunk.length
                            });
                        }
                    });
                    
                    // Score large chunks (context focus)
                    largeChunks.forEach((chunk, index) => {
                        const score = calculateTextSimilarity(query, chunk);
                        if (score > 0.8) {
                            allScoredChunks.push({
                                chunk,
                                score: score * 1.1, // Moderate boost for context
                                index: index + 10000,
                                type: 'large',
                                originalIndex: index,
                                length: chunk.length
                            });
                        }
                    });
                    
                    allScoredChunks.sort((a, b) => b.score - a.score);
                    
                    const selectedChunks = [];
                    let totalLength = 0;
                    let smallCount = 0;
                    let largeCount = 0;
                    const maxLength = 1800;
                    const maxSmall = 2;
                    const maxLarge = 2;
                    
                    for (const item of allScoredChunks) {
                        const canAddSmall = item.type === 'small' && smallCount < maxSmall;
                        const canAddLarge = item.type === 'large' && largeCount < maxLarge;
                        
                        if ((canAddSmall || canAddLarge) && totalLength + item.length <= maxLength) {
                            selectedChunks.push(item);
                            totalLength += item.length;
                            
                            if (item.type === 'small') smallCount++;
                            else largeCount++;
                        }
                        
                        if (selectedChunks.length >= 4) break;
                    }
                    
                    if (selectedChunks.length === 0) {
                        const fallback = [...smallChunks.slice(0, 2), ...largeChunks.slice(0, 1)];
                        return fallback.join('\n\n').substring(0, 1800);
                    }
                    
                    selectedChunks.sort((a, b) => a.originalIndex - b.originalIndex);
                    return selectedChunks.map(item => item.chunk).join('\n\n');
                }

                // Strategy for very large content (> 3000 words) - Sliding window
                function findBestChunksFromSliding(query, content) {
                    const chunks = createSlidingChunks(content, 700, 200);
                    if (chunks.length <= 1) {
                        return chunks[0] || content.substring(0, 2000);
                    }
                    
                    const scoredChunks = chunks.map((chunk, index) => ({
                        chunk,
                        score: calculateTextSimilarity(query, chunk),
                        index,
                        length: chunk.length
                    }));
                    
                    scoredChunks.sort((a, b) => b.score - a.score);
                    
                    const selectedChunks = [];
                    let totalLength = 0;
                    const maxLength = 2200;
                    const usedIndices = new Set();
                    
                    for (const item of scoredChunks) {
                        if (totalLength + item.length > maxLength) continue;
                        
                        // Avoid overlapping chunks
                        let hasOverlap = false;
                        for (const usedIndex of usedIndices) {
                            if (Math.abs(item.index - usedIndex) < 2) {
                                hasOverlap = true;
                                break;
                            }
                        }
                        
                        if (!hasOverlap && item.score > 2) {
                            selectedChunks.push(item);
                            usedIndices.add(item.index);
                            totalLength += item.length;
                            
                            if (selectedChunks.length >= 3) break;
                        }
                    }
                    
                    if (selectedChunks.length === 0) {
                        return chunks.slice(0, 2).join('\n---\n');
                    }
                    
                    selectedChunks.sort((a, b) => a.index - b.index);
                    return selectedChunks.map(item => item.chunk).join('\n---\n');
                }

                // --- CORE FUNCTIONS ---

                function createSystemPrompt() {
                    let basePrompt = "Vous êtes Kytisa, un assistant IA serviable. Répondez aux questions de manière utile et concise.";
                    if (postData.is_singular && postData.content) {
                        if (postData.is_long_content) {
                            basePrompt = `Vous êtes Kytisa, un assistant IA expert spécialisé dans l'analyse du document fourni. Votre rôle principal est de répondre aux questions en vous basant *exclusivement* sur le texte de l'article pertinent fourni avec la requête de l'utilisateur. Si vous ne pouvez pas répondre à la question à partir du contexte fourni, vous DEVEZ répondre avec la phrase exacte : "Désolé, je n'ai aucune information à propos de ce sujet.". N'utilisez pas vos connaissances générales ou toute autre information. Soyez précis et référez-vous directement aux informations données dans le contexte. Titre de l'article : "${postData.title}", URL de l'article : ${postData.permalink}`;
                        } else {
                            basePrompt = `Kytisa, votre assistant IA, dispose des informations relatives à l'article en cours intitulé.. "${postData.title}".\n\nContenu de l'article: ${postData.content}\n\nURL de l'article: ${postData.permalink}\n\nLorsque les utilisateurs posent des questions sur "cet article", "ce post", ou "cette page", référez-vous au contenu ci-dessus. Si l'utilisateur pose une question qui n'est pas liée au contenu de l'article, vous DEVEZ répondre avec la phrase exacte : "Désolé, je n'ai aucune information à propos de ce sujet.". N'utilisez pas vos connaissances générales.`;
                        }
                    } else if (postData.page_type === 'homepage') {
                        basePrompt = `Vous êtes un assistant IA pour le site ${postData.site_name}. Vous êtes actuellement sur la page d'accueil.`;
                    } else if (postData.page_type) {
                        basePrompt = `Vous êtes un assistant IA pour le site ${postData.site_name}. Vous êtes sur une page de type '${postData.page_type}' intitulée : "${postData.title}".`;
                    }
                    return { role: "system", content: basePrompt };
                }
                
                function setInputState(disabled) {
                    userInputEl.prop('disabled', disabled);
                    sendBtn.prop('disabled', disabled);
                    if (!disabled) {
                        userInputEl.focus();
                    }
                }

                window.sendMessage = function () {
                    const userText = userInputEl.val().trim();
                    if (!userText) return;
                    
                    setInputState(true);

                    appendMessage('user', userText);
                    conversationHistory.push({ role: 'user', content: userText });
                    saveConversation();
                    userInputEl.val('');

                    const assistantMessageId = 'assistant-message-' + Date.now();
                    chatHistoryEl.append($('<div>').addClass('message assistant').attr('id', assistantMessageId));
                    $('#' + assistantMessageId).html('<div class="typing-indicator"><span></span><span></span><span></span></div>');
                    scrollToBottom();

                    let messagesForApi = JSON.parse(JSON.stringify(conversationHistory));

                    if (postData.is_long_content && postData.content) {
                        const relevantContent = findHybridContent(userText, postData.content);
                        if (relevantContent) {
                            const lastMessage = messagesForApi[messagesForApi.length - 1];
                            lastMessage.content = `Utilisez le texte suivant de l'article pour répondre à la question de l'utilisateur :\n\n---\n${relevantContent}\n---\n\nQuestion de l'utilisateur : ${userText}`;
                        }
                    }

                    const payload = { model: modelName, messages: messagesForApi, stream: true };

                    let buffer = '';
                    fetch(apiUrl, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + apiKey, 'HTTP-Referer': siteUrl, 'X-Title': siteTitle },
                        body: JSON.stringify(payload)
                    }).then(response => {
                        if (!response.ok) throw new Error(`Erreur HTTP ! statut: ${response.status} ${response.statusText}`);
                        const reader = response.body.getReader();
                        const decoder = new TextDecoder();
                        function push() {
                            reader.read().then(({ done, value }) => {
                                if (done) {
                                    updateAssistantMessage(assistantMessageId, buffer, true);
                                    conversationHistory.push({ role: 'assistant', content: buffer });
                                    saveConversation();
                                    setInputState(false);
                                    return;
                                }
                                const chunk = decoder.decode(value, { stream: true });
                                const lines = chunk.split('\n');
                                lines.forEach(line => {
                                    if (line.startsWith('data: ')) {
                                        const jsonStr = line.slice(6).trim();
                                        if (jsonStr === '[DONE]') return;
                                        try {
                                            const data = JSON.parse(jsonStr);
                                            const token = data.choices?.[0]?.delta?.content;
                                            if (token) buffer += token;
                                        } catch (e) { /* Incomplete JSON is expected */ }
                                    }
                                });
                                updateAssistantMessage(assistantMessageId, buffer, false);
                                scrollToBottom();
                                push();
                            }).catch(error => {
                                console.error('Erreur de lecture du flux:', error);
                                updateAssistantMessage(assistantMessageId, "Désolé, une erreur est survenue lors de la réception de la réponse.", true);
                                setInputState(false);
                            });
                        }
                        push();
                    }).catch(error => {
                        console.error('Erreur Fetch API:', error);
                        updateAssistantMessage(assistantMessageId, `Désolé, une erreur de communication avec l'assistant est survenue. Détails : ${error.message}`, true);
                        setInputState(false);
                    });
                };

                // --- UI & HELPER FUNCTIONS ---

                function updateAssistantMessage(elementId, content, isFinal) {
                    let assistantDiv = $('#' + elementId);
                    if (typeof marked === 'undefined') {
                        assistantDiv.text(content);
                        return;
                    }
                    let htmlContent = marked.parse(content);
                    if (isFinal) {
                        const actionsDiv = $('<div>').addClass('message-actions').html(`<button class="btn btn-sm btn-outline" onclick="copyMessage(this)">${copyIconSvg}</button>`);
                        assistantDiv.html(htmlContent).append(actionsDiv);
                    } else {
                         assistantDiv.html(htmlContent);
                    }
                }

                function appendMessage(role, content) {
                    let htmlContent = content;
                    if (typeof marked !== 'undefined') {
                        htmlContent = marked.parse(content);
                    } else {
                        htmlContent = $('<div>').text(content).html();
                    }
                    const div = $('<div>').addClass('message ' + role).html(htmlContent);

                    if (role === 'assistant') {
                        const actionsDiv = $('<div>').addClass('message-actions').html(`<button class="btn btn-sm btn-outline" onclick="copyMessage(this)">${copyIconSvg}</button>`);
                        div.append(actionsDiv);
                    }
                    chatHistoryEl.append(div);
                    scrollToBottom();
                }
                
                function appendSystemMessage(content) {
                    const div = $('<div>').addClass('message system').html($('<div>').text(content).html());
                    chatHistoryEl.append(div);
                    scrollToBottom();
                }
                
                function displayConversationHistory() {
                    chatHistoryEl.empty();
                    conversationHistory.slice(1).forEach(msg => {
                        if (msg.role !== 'system') appendMessage(msg.role, msg.content);
                    });
                }
                
                function saveConversation() {
                    try {
                        localStorage.setItem(globalSessionKey, JSON.stringify(conversationHistory));
                    } catch (e) {
                        console.error("Could not save conversation to localStorage", e);
                    }
                }

                function scrollToBottom() {
                    chatHistoryEl.scrollTop(chatHistoryEl[0].scrollHeight);
                }

                window.copyMessage = function(button) {
                    const messageContainer = $(button).closest('.message');
                    const messageContent = messageContainer.clone().find('.message-actions').remove().end().text().trim();
                    const textArea = document.createElement("textarea");
                    textArea.value = messageContent;
                    document.body.appendChild(textArea);
                    textArea.select();
                    try {
                        document.execCommand('copy');
                        const buttonEl = $(button);
                        buttonEl.html(checkIconSvg);
                        setTimeout(() => buttonEl.html(copyIconSvg), 2000);
                    } catch (err) { console.error('Fallback: Unable to copy', err); }
                    document.body.removeChild(textArea);
                };

                // --- EVENT LISTENERS ---
                chatToggleBtn.on('click', () => {
                    chatboxEl.toggleClass('visible');
                    if (chatboxEl.hasClass('visible')) {
                        userInputEl.focus();
                    }
                });
                
                // New event listener for the mobile close button
                closeChatBtn.on('click', () => {
                    chatboxEl.removeClass('visible');
                });

                sendBtn.on('click', sendMessage);
                userInputEl.on('keypress', e => {
                    if (e.which == 13 && !e.shiftKey) {
                        e.preventDefault();
                        sendMessage();
                    }
                });

                clearChatBtn.on('click', () => clearChatModal.css('display', 'flex'));
                confirmCancelBtn.on('click', () => clearChatModal.hide());
                confirmOkBtn.on('click', () => {
                    conversationHistory = [createSystemPrompt()];
                    saveConversation();
                    displayConversationHistory();
                    let msg = postData.is_singular ? `👋 Bonjour ! Prêt à vous aider avec l'article "${postData.title}".` : `👋 Bonjour ! Comment puis-je vous aider ?`;
                    appendSystemMessage(msg);
                    clearChatModal.hide();
                });

                // --- INITIALIZATION ---
                let lastPageInfo = {};
                try {
                    const storedPageInfo = localStorage.getItem(currentPageKey);
                    if (storedPageInfo) lastPageInfo = JSON.parse(storedPageInfo);
                } catch(e) { console.error("Could not parse page info", e); }

                displayConversationHistory();

                if (conversationHistory.length === 0) {
                    conversationHistory.push(createSystemPrompt());
                    let welcomeMsg = postData.is_singular 
                        ? `👋 Bonjour ! Je peux vous aider avec l'article "${postData.title}". Que souhaitez-vous savoir ?` 
                        : `👋 Bonjour ! Je suis votre assistant. Comment puis-je vous aider ?`;
                    appendSystemMessage(welcomeMsg);
                    saveConversation();
                } else {
                    if (lastPageInfo.url && lastPageInfo.url !== window.location.href) {
                        conversationHistory[0] = createSystemPrompt(); 
                        let newPageMsg = postData.is_singular 
                            ? `Vous consultez maintenant : "${postData.title}". Le contexte a été mis à jour.`
                            : `Vous êtes maintenant sur la page : "${postData.title}". Le contexte a été mis à jour.`;
                        appendSystemMessage(newPageMsg);
                        saveConversation();
                    }
                }

                localStorage.setItem(currentPageKey, JSON.stringify({url: window.location.href}));
            });
            </script>
            <?php
        });
    }
});

//final