Edit

        setTimeout(() => { msgEl.textContent = ''; }, 3000);
    } catch (error) {
        alert('Error saving: ' + error.message);
    }
}

setTimeout(() => { msgEl.textContent = ''; }, 3000);
    } catch (error) {
        alert('Error saving: ' + error.message);
    }
}

// ============================================
// AI CHAT PANEL
// ============================================

const aiChat = {
    isOpen: false,
    mode: 'general',
    threadId: null,
    contactId: null,
    emailId: null,
    threadSubject: null,
    contactName: null,
    history: [],
    isDragging: false,
    dragOffsetX: 0,
    dragOffsetY: 0,
    // Context builder
    contextThreads: [],      // [{thread_id, subject, email_count, contact_name}]
    contextContact: null,    // {id, name, email}
    _availableThreads: [],   // temp storage for thread picker
    // Session persistence
    sessionId: null,
    // Agent
    agent: 'general',
    // Contact memories
    contactMemories: [],
};

// Provider/Model config — synced with Chrome extension contentScript.js
const AI_PROVIDER_MODELS = {
    claude: [
        { id: 'claude-sonnet-4-5-20250929', name: 'Sonnet 4.5' },
        { id: 'claude-opus-4-5-20251101', name: 'Opus 4.5 (Best)' },
        { id: 'claude-haiku-4-5-20251001', name: 'Haiku 4.5 (Fast)' },
    ],
    openai: [
        { id: 'gpt-5.2', name: 'GPT-5.2 (Latest)' },
        { id: 'gpt-5.2-pro', name: 'GPT-5.2 Pro (Best)' },
        { id: 'gpt-5-mini', name: 'GPT-5 Mini' },
        { id: 'gpt-5-nano', name: 'GPT-5 Nano (Fast)' },
    ],
    gemini: [
        { id: 'gemini-2.5-flash', name: 'Gemini 2.5 Flash' },
        { id: 'gemini-3-pro', name: 'Gemini 3 Pro' },
        { id: 'gemini-2.5-flash-lite', name: 'Flash-Lite (Fast)' },
    ],
    grok: [
        { id: 'grok-4', name: 'Grok 4 (Latest)' },
        { id: 'grok-3', name: 'Grok 3' },
        { id: 'grok-3-mini', name: 'Grok 3 Mini (Fast)' },
    ],
    deepseek: [
        { id: 'deepseek-chat', name: 'DeepSeek V3.2' },
        { id: 'deepseek-reasoner', name: 'Reasoner (Thinking)' },
    ],
    qwen: [
        { id: 'qwen-max-latest', name: 'Qwen Max' },
        { id: 'qwen-turbo-latest', name: 'Qwen Turbo (Fast)' },
    ],
    mistral: [
        { id: 'mistral-large-latest', name: 'Mistral Large' },
        { id: 'mistral-small-latest', name: 'Mistral Small (Fast)' },
    ],
    cohere: [
        { id: 'command-a-03-2025', name: 'Command A' },
        { id: 'command-r7b-12-2024', name: 'Command R7B (Fast)' },
    ],
};

const AI_PROVIDER_NAMES = {
    claude: 'Claude', openai: 'OpenAI', gemini: 'Gemini', grok: 'Grok',
    deepseek: 'DeepSeek', qwen: 'Qwen', mistral: 'Mistral', cohere: 'Cohere',
};

// Agent presets
const AI_AGENTS = {
    general:             { id: 'general',             name: 'General',    icon: '\u{1F4AC}', preferredProvider: null,    preferredModel: null, quickPrompts: ['What are my most at-risk clients?', 'Which threads need urgent attention?', 'Summarize recent activity'] },
    quote_analyst:       { id: 'quote_analyst',       name: 'Quotes',     icon: '\u{1F4B0}', preferredProvider: 'claude', preferredModel: 'claude-sonnet-4-5-20250929', quickPrompts: ['How much have we quoted across these threads?', 'What is the price sensitivity?', 'Suggest optimal pricing', 'What discounts were given?'] },
    deception_detector:  { id: 'deception_detector',  name: 'Deception',  icon: '\u{1F50D}', preferredProvider: 'claude', preferredModel: 'claude-opus-4-5-20251101', quickPrompts: ['What is the deception level?', 'Any contradictions between statements?', 'Red flags or pressure tactics?', 'Rate honesty 1-10 with evidence'] },
    contact_profiler:    { id: 'contact_profiler',    name: 'Profiler',   icon: '\u{1F464}', preferredProvider: 'claude', preferredModel: 'claude-sonnet-4-5-20250929', quickPrompts: ['Build a complete profile', 'Communication style analysis', 'Decision-making patterns', 'How should I approach them?'] },
    email_composer:      { id: 'email_composer',      name: 'Composer',   icon: '\u{270D}\u{FE0F}', preferredProvider: 'openai', preferredModel: 'gpt-5.2', quickPrompts: ['Write a professional reply', 'Write a firm but polite response', 'Write a follow-up email', 'Write a brief acknowledgment'] },
};

const AI_QUICK_PROMPTS = {
    general: ['What are my most at-risk clients?', 'Which threads need urgent attention?', 'Summarize recent activity'],
    thread: ['Summarize this thread', 'What are the key risks?', 'What action should I take next?', 'Is this client trustworthy?', 'What are they really asking for?'],
    contact: ['What is their communication style?', 'Are there any red flags?', 'How should I approach them?', 'What opportunities exist with them?'],
    quote: ['How much should I quote for this project?', 'What is the scope of work?', 'What are the risks?', 'Suggest a project timeline'],
    reply: ['Write a professional reply', 'Write a firm but polite response', 'Write a follow-up email', 'Write a brief acknowledgment'],
    multithread: ['Summarize all conversations', 'How much have we quoted?', 'What is the deception level?', 'Build a complete profile', 'What patterns emerge across these threads?'],
};

function toggleAiChat() {
    const panel = document.getElementById('ai-chat-panel');
    aiChat.isOpen = !aiChat.isOpen;
    panel.style.display = aiChat.isOpen ? 'flex' : 'none';
    if (aiChat.isOpen) { document.getElementById('ai-chat-input').focus(); renderQuickPrompts(); }
}

function openAiChatForThread(threadId, subject, contactId) {
    aiChat.threadId = threadId; aiChat.contactId = contactId || null;
    aiChat.threadSubject = subject || threadId; aiChat.emailId = null;
    setAiChatMode('thread', document.querySelector('.ai-mode-btn[data-mode="thread"]'));
    if (!aiChat.isOpen) toggleAiChat(); else document.getElementById('ai-chat-input').focus();
}

function openAiChatForContact(contactId, contactName) {
    aiChat.contactId = contactId; aiChat.contactName = contactName || 'Contact';
    aiChat.threadId = null; aiChat.emailId = null;
    setAiChatMode('contact', document.querySelector('.ai-mode-btn[data-mode="contact"]'));
    if (!aiChat.isOpen) toggleAiChat(); else document.getElementById('ai-chat-input').focus();
}

function openAiChatForReply(threadId, emailId, subject) {
    aiChat.threadId = threadId; aiChat.emailId = emailId; aiChat.threadSubject = subject || threadId;
    setAiChatMode('reply', document.querySelector('.ai-mode-btn[data-mode="reply"]'));
    if (!aiChat.isOpen) toggleAiChat(); else document.getElementById('ai-chat-input').focus();
}

function setAiChatMode(mode, btn) {
    aiChat.mode = mode;
    document.querySelectorAll('.ai-mode-btn').forEach(b => { b.style.background = '#2d2d4e'; b.style.color = '#94a3b8'; });
    if (btn) { btn.style.background = '#6366f1'; btn.style.color = '#fff'; }
    updateAiChatContextLabel(); renderQuickPrompts();
}

function updateAiChatContextLabel() {
    const label = document.getElementById('ai-chat-context-label');
    if (!label) return;

    // Multi-thread context takes priority
    if (aiChat.contextThreads.length > 0) {
        const totalEmails = aiChat.contextThreads.reduce((sum, t) => sum + (t.email_count || 0), 0);
        const contactLabel = aiChat.contextContact ? aiChat.contextContact.name : '';
        label.textContent = `${aiChat.contextThreads.length} threads, ~${totalEmails} emails` + (contactLabel ? ` from ${contactLabel}` : '');
        label.style.color = '#10b981';
        return;
    }

    const modeLabels = { general: 'General Chat', thread: 'Thread Analysis', contact: 'Contact Intelligence', quote: 'Quote Assistant', reply: 'Reply Composer' };
    let ctx = modeLabels[aiChat.mode] || 'General Chat';
    if (aiChat.mode === 'thread' && aiChat.threadSubject) ctx += ' \u00B7 ' + aiChat.threadSubject.substring(0, 30);
    if (aiChat.mode === 'contact' && aiChat.contactName) ctx += ' \u00B7 ' + aiChat.contactName;
    label.textContent = ctx;
    label.style.color = 'rgba(255,255,255,0.7)';
}

function renderQuickPrompts() {
    const container = document.getElementById('ai-quick-prompts');
    if (!container) return;
    // Use agent prompts if agent selected, then multithread if context loaded, then mode
    var prompts;
    var agent = AI_AGENTS[aiChat.agent];
    if (agent && agent.id !== 'general') {
        prompts = agent.quickPrompts;
    } else if (aiChat.contextThreads.length > 0) {
        prompts = AI_QUICK_PROMPTS.multithread;
    } else {
        prompts = AI_QUICK_PROMPTS[aiChat.mode] || AI_QUICK_PROMPTS.general;
    }
    container.innerHTML = prompts.map(function(p) {
        return '<button onclick="sendAiChatPrompt(' + JSON.stringify(p).replace(/"/g, '"') + ')" style="background:#2d2d4e;color:#94a3b8;border:1px solid #3d3d5c;border-radius:12px;padding:3px 10px;font-size:0.68em;cursor:pointer;white-space:nowrap;" onmouseover="this.style.background=\'#6366f1\';this.style.color=\'#fff\'" onmouseout="this.style.background=\'#2d2d4e\';this.style.color=\'#94a3b8\'">' + escapeHtml(p) + '</button>';
    }).join('');
}

function sendAiChatPrompt(prompt) {
    document.getElementById('ai-chat-input').value = prompt;
    sendAiChat();
}

function handleAiChatKey(e) {
    if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendAiChat(); }
}

// --- Provider/Model Dropdown ---
function initAiProviderDropdown() {
    var providerSelect = document.getElementById('ai-chat-provider');
    if (!providerSelect) return;
    providerSelect.innerHTML = '';
    Object.keys(AI_PROVIDER_MODELS).forEach(function(code) {
        var opt = document.createElement('option');
        opt.value = code;
        opt.textContent = AI_PROVIDER_NAMES[code] || code;
        providerSelect.appendChild(opt);
    });
    providerSelect.value = 'claude';
    updateAiModelDropdown();
}

function updateAiModelDropdown() {
    var providerSelect = document.getElementById('ai-chat-provider');
    var modelSelect = document.getElementById('ai-chat-model');
    if (!providerSelect || !modelSelect) return;
    var provider = providerSelect.value;
    var models = AI_PROVIDER_MODELS[provider] || [];
    modelSelect.innerHTML = '';
    models.forEach(function(m) {
        var opt = document.createElement('option');
        opt.value = m.id;
        opt.textContent = m.name;
        modelSelect.appendChild(opt);
    });
}

// --- Agent Selector ---
function selectAgent(agentId) {
    aiChat.agent = agentId;
    var agent = AI_AGENTS[agentId];
    // Highlight active agent button
    document.querySelectorAll('.ai-agent-btn').forEach(function(b) {
        b.style.background = b.dataset.agent === agentId ? '#6366f1' : '#2d2d4e';
        b.style.color = b.dataset.agent === agentId ? '#fff' : '#94a3b8';
    });
    // Set preferred provider/model
    if (agent && agent.preferredProvider) {
        var providerSelect = document.getElementById('ai-chat-provider');
        if (providerSelect) { providerSelect.value = agent.preferredProvider; updateAiModelDropdown(); }
        if (agent.preferredModel) {
            var modelSelect = document.getElementById('ai-chat-model');
            if (modelSelect) modelSelect.value = agent.preferredModel;
        }
    }
    updateAiChatContextLabel();
    renderQuickPrompts();
}

// --- Context Builder ---
function toggleContextBuilder() {
    var area = document.getElementById('ai-context-search-area');
    var icon = document.getElementById('ai-context-toggle-icon');
    if (!area) return;
    var isVisible = area.style.display !== 'none';
    area.style.display = isVisible ? 'none' : 'block';
    icon.textContent = isVisible ? '+' : '-';
}

async function searchContextContacts() {
    var query = document.getElementById('ai-context-search-input').value.trim();
    if (!query) return;
    // Strip wildcard chars — backend already does partial matching
    var cleanQuery = query.replace(/[*%]/g, '').trim();
    if (!cleanQuery) return;

    var resultsDiv = document.getElementById('ai-context-search-results');
    resultsDiv.innerHTML = '
Searching contacts & threads...
';

    try {
        // Search both contacts and threads in parallel
        var results = await Promise.all([
            apiCall('contacts', { search: cleanQuery, limit: 10 }),
            apiCall('threads', { search: cleanQuery, limit: 10 }),
        ]);
        var contactsData = results[0];
        var threadsData = results[1];

        var html = '';
        var contacts = contactsData.contacts || [];
        var threads = threadsData.threads || [];

        if (contacts.length === 0 && threads.length === 0) {
            resultsDiv.innerHTML = '
No contacts or threads found for "' + escapeHtml(cleanQuery) + '"
';
            return;
        }

        // Contacts section
        if (contacts.length > 0) {
            html += '
CONTACTS
';
            html += contacts.map(function(c) {
                var name = c.name || c.email;
                return '
' +
                    '\u{1F464} ' + escapeHtml(name) + ' ' + escapeHtml(c.email) + '' +
                    'show threads \u25B6' +
                '
';
            }).join('');
        }

        // Threads section — directly addable
        if (threads.length > 0) {
            html += '
THREADS
';
            html += threads.map(function(t) {
                var isAdded = aiChat.contextThreads.some(function(ct) { return ct.thread_id === t.thread_id; });
                var subject = t.subject || '(No Subject)';
                return '
' +
                    '' +
                        '\u{1F4E7} ' + escapeHtml(subject.substring(0, 45)) +
                        ' (' + (t.email_count || '?') + ')' +
                    '' +
                    '<button onclick="event.stopPropagation();addThreadToContext(\'' + t.thread_id + '\', \'' + escapeHtml(subject.substring(0,50).replace(/'/g,"")) + '\', ' + (t.email_count||0) + ', \'\')"' +
                            ' style="background:' + (isAdded ? '#10b981' : '#6366f1') + '; color:#fff; border:none; border-radius:4px; padding:2px 8px; font-size:0.85em; cursor:pointer; margin-left:4px; white-space:nowrap;"' +
                            (isAdded ? ' disabled' : '') + '>' +
                        (isAdded ? '\u2713 Added' : '+ Add') +
                    '</button>' +
                '
';
            }).join('');
        }

        resultsDiv.innerHTML = html;
    } catch (err) {
        resultsDiv.innerHTML = '
Error: ' + escapeHtml(err.message) + '
';
    }
}

async function selectContextContact(contactId, name, email) {
    aiChat.contextContact = { id: contactId, name: name, email: email };
    aiChat.contactId = contactId;
    aiChat.contactName = name;
    document.getElementById('ai-context-search-results').innerHTML = '';

    var picker = document.getElementById('ai-context-thread-picker');
    picker.style.display = 'block';
    picker.innerHTML = '
Loading threads...
';

    // Load contact memories
    loadContactMemories(contactId);

    try {
        var data = await apiCall('threads', { contact: contactId, limit: 50 });
        if (!data.threads || data.threads.length === 0) {
            picker.innerHTML = '
No threads for this contact
';
            return;
        }
        aiChat._availableThreads = data.threads;
        var html = '
' +
            '' + escapeHtml(name) + ' - ' + data.threads.length + ' threads' +
            '<button onclick="addAllContactThreads()" style="background:#10b981; color:#fff; border:none; border-radius:4px; padding:2px 8px; font-size:0.68em; cursor:pointer;">+ Add All</button>' +
        '
';
        html += data.threads.map(function(t) {
            var isAdded = aiChat.contextThreads.some(function(ct) { return ct.thread_id === t.thread_id; });
            return '
' +
                '' +
                    escapeHtml((t.subject || '(No Subject)').substring(0, 40)) +
                    ' (' + (t.email_count || '?') + ' emails)' +
                '' +
                '<button onclick="addThreadToContext(\'' + t.thread_id + '\', \'' + escapeHtml((t.subject||'').substring(0,50).replace(/'/g,"")) + '\', ' + (t.email_count||0) + ', \'' + escapeHtml(name.replace(/'/g,"")) + '\')"' +
                        ' style="background:' + (isAdded ? '#4b5563' : '#6366f1') + '; color:#fff; border:none; border-radius:3px; padding:1px 6px; font-size:0.95em; cursor:pointer; margin-left:4px;"' +
                        (isAdded ? ' disabled' : '') + '>' +
                    (isAdded ? '\u2713' : '+') +
                '</button>' +
            '
';
        }).join('');
        picker.innerHTML = html;
    } catch (err) {
        picker.innerHTML = '
Error: ' + escapeHtml(err.message) + '
';
    }
}

function addThreadToContext(threadId, subject, emailCount, contactName) {
    if (aiChat.contextThreads.some(function(t) { return t.thread_id === threadId; })) return;
    aiChat.contextThreads.push({ thread_id: threadId, subject: subject, email_count: emailCount, contact_name: contactName });
    updateContextCart();
    updateAiChatContextLabel();
    renderQuickPrompts();
    // Refresh picker to update button states
    if (aiChat.contextContact) selectContextContact(aiChat.contextContact.id, aiChat.contextContact.name, aiChat.contextContact.email);
}

function removeThreadFromContext(threadId) {
    aiChat.contextThreads = aiChat.contextThreads.filter(function(t) { return t.thread_id !== threadId; });
    updateContextCart();
    updateAiChatContextLabel();
    renderQuickPrompts();
}

function addAllContactThreads() {
    var threads = aiChat._availableThreads || [];
    threads.forEach(function(t) {
        if (!aiChat.contextThreads.some(function(ct) { return ct.thread_id === t.thread_id; })) {
            aiChat.contextThreads.push({
                thread_id: t.thread_id, subject: t.subject || '(No Subject)',
                email_count: t.email_count || 0, contact_name: (aiChat.contextContact && aiChat.contextContact.name) || 'Unknown'
            });
        }
    });
    updateContextCart();
    updateAiChatContextLabel();
    renderQuickPrompts();
    if (aiChat.contextContact) selectContextContact(aiChat.contextContact.id, aiChat.contextContact.name, aiChat.contextContact.email);
}

function clearContextCart() {
    aiChat.contextThreads = [];
    aiChat.contextContact = null;
    aiChat.contactMemories = [];
    aiChat._availableThreads = [];
    updateContextCart();
    updateAiChatContextLabel();
    renderQuickPrompts();
    var picker = document.getElementById('ai-context-thread-picker');
    if (picker) picker.style.display = 'none';
    var memDiv = document.getElementById('ai-context-memories');
    if (memDiv) memDiv.style.display = 'none';
}

function updateContextCart() {
    var cartDiv = document.getElementById('ai-context-cart');
    if (!cartDiv) return;
    if (aiChat.contextThreads.length === 0) { cartDiv.style.display = 'none'; return; }
    cartDiv.style.display = 'block';
    var totalEmails = aiChat.contextThreads.reduce(function(sum, t) { return sum + (t.email_count || 0); }, 0);
    cartDiv.innerHTML =
        '
' +
            'Context: ' + aiChat.contextThreads.length + ' thread' + (aiChat.contextThreads.length > 1 ? 's' : '') + ', ~' + totalEmails + ' emails' +
            '<button onclick="clearContextCart()" style="background:#7f1d1d; color:#fca5a5; border:none; border-radius:3px; padding:1px 6px; font-size:0.65em; cursor:pointer;">Clear All</button>' +
        '
' +
        '
' +
            aiChat.contextThreads.map(function(t) {
                return '
' +
                    '' + escapeHtml(t.subject.substring(0, 35)) + '' +
                    '<button onclick="removeThreadFromContext(\'' + t.thread_id + '\')" style="background:none; border:none; color:#f87171; cursor:pointer; font-size:1.1em; padding:0 2px;">\u00D7</button>' +
                '
';
            }).join('') +
        '
';
}

// --- Contact Memory ---
async function loadContactMemories(contactId) {
    var memDiv = document.getElementById('ai-context-memories');
    if (!memDiv) return;
    try {
        var data = await apiCall('ai_contact_memories', { contact_id: contactId });
        aiChat.contactMemories = data.memories || [];
        renderContactMemories();
    } catch (e) {
        aiChat.contactMemories = [];
    }
}

function renderContactMemories() {
    var memDiv = document.getElementById('ai-context-memories');
    if (!memDiv) return;
    if (aiChat.contactMemories.length === 0 && !aiChat.contextContact) { memDiv.style.display = 'none'; return; }
    memDiv.style.display = 'block';
    memDiv.innerHTML =
        '
' +
            'Memories (' + aiChat.contactMemories.length + ')' +
            '<button onclick="promptAddMemory()" style="background:#2d2d4e; color:#94a3b8; border:1px solid #3d3d5c; border-radius:3px; padding:1px 6px; font-size:0.63em; cursor:pointer;">+ Add</button>' +
        '
' +
        '
' +
            aiChat.contactMemories.map(function(m) {
                return '' +
                    (m.source === 'auto' ? '\u{1F916}' : '\u{1F4CC}') + ' ' + escapeHtml(m.fact.substring(0, 40)) + (m.fact.length > 40 ? '...' : '') +
                    ' <button onclick="deleteContactMemory(\'' + m.id + '\')" style="background:none;border:none;color:#f87171;cursor:pointer;font-size:1em;padding:0;line-height:1;">\u00D7</button>' +
                '';
            }).join('') +
        '
';
}

function promptAddMemory() {
    var fact = prompt('Enter a fact about this contact:');
    if (!fact || !aiChat.contextContact) return;
    fetch('api.php?action=ai_contact_memory_add', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ contact_id: aiChat.contextContact.id, fact: fact })
    }).then(function(r) { return r.json(); }).then(function(data) {
        if (data.success && data.memory) {
            aiChat.contactMemories.push(data.memory);
            renderContactMemories();
        }
    });
}

function deleteContactMemory(memoryId) {
    if (!aiChat.contextContact) return;
    fetch('api.php?action=ai_contact_memory_delete', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ contact_id: aiChat.contextContact.id, memory_id: memoryId })
    }).then(function(r) { return r.json(); }).then(function(data) {
        if (data.success) {
            aiChat.contactMemories = aiChat.contactMemories.filter(function(m) { return m.id !== memoryId; });
            renderContactMemories();
        }
    });
}

// --- Session Management ---
async function loadChatSessions() {
    var overlay = document.getElementById('ai-session-overlay');
    if (!overlay) return;
    overlay.style.display = 'flex';
    overlay.innerHTML = '
Loading sessions...
';
    try {
        var data = await apiCall('ai_chat_sessions', { limit: 20 });
        var sessions = data.sessions || [];
        if (sessions.length === 0) {
            overlay.innerHTML = '

No saved sessions
<button onclick="closeSessionOverlay()" style="margin-top:10px;background:#2d2d4e;color:#94a3b8;border:none;border-radius:6px;padding:5px 12px;font-size:0.75em;cursor:pointer;">Close</button>
';
            return;
        }
        var agentIcons = {}; Object.values(AI_AGENTS).forEach(function(a) { agentIcons[a.id] = a.icon; });
        overlay.innerHTML =
            '
' +
                'Chat History' +
                '<button onclick="closeSessionOverlay()" style="background:none;border:none;color:#94a3b8;cursor:pointer;font-size:1.1em;">\u2715</button>' +
            '
' +
            '
' +
                sessions.map(function(s) {
                    return '
' +
                        '
' +
                            '
' +
                                (agentIcons[s.agent] || '\u{1F4AC}') + ' ' + escapeHtml(s.title) +
                            '
' +
                            '
' + s.message_count + ' messages ' + (s.contact_name ? '\u00B7 ' + escapeHtml(s.contact_name) : '') + '
' +
                        '
' +
                        '
' +
                            '' + (s.updated_at ? s.updated_at.substring(0,10) : '') + '' +
                            '<button onclick="event.stopPropagation();deleteChatSession(\'' + s.session_id + '\')" style="background:none;border:none;color:#f87171;cursor:pointer;font-size:0.8em;" title="Delete">\u{1F5D1}</button>' +
                        '
' +
                    '
';
                }).join('') +
            '
';
    } catch (err) {
        overlay.innerHTML = '
Error: ' + escapeHtml(err.message) + '
';
    }
}

function closeSessionOverlay() {
    var overlay = document.getElementById('ai-session-overlay');
    if (overlay) overlay.style.display = 'none';
}

async function loadChatSession(sessionId) {
    closeSessionOverlay();
    try {
        var data = await apiCall('ai_chat_session', { session_id: sessionId });
        var session = data.session;
        if (!session) return;

        // Restore state
        aiChat.sessionId = session.session_id;
        aiChat.agent = session.agent || 'general';
        aiChat.contactId = session.contact_id || null;
        aiChat.contactName = session.contact_name || null;
        aiChat.contextThreads = (session.context_thread_ids || []).map(function(tid) { return { thread_id: tid, subject: '', email_count: 0, contact_name: session.contact_name || '' }; });
        aiChat.history = [];

        // Restore provider/model
        if (session.provider) {
            var ps = document.getElementById('ai-chat-provider');
            if (ps) { ps.value = session.provider; updateAiModelDropdown(); }
        }
        if (session.model) {
            var ms = document.getElementById('ai-chat-model');
            if (ms) ms.value = session.model;
        }

        // Restore agent button
        selectAgent(aiChat.agent);

        // Render messages
        var msgContainer = document.getElementById('ai-chat-messages');
        msgContainer.innerHTML = '';
        (session.messages || []).forEach(function(m) {
            if (m.role === 'user' || m.role === 'assistant') {
                appendAiChatMessage(m.role, m.content, m.model || null);
                aiChat.history.push({ role: m.role, content: m.content });
            }
        });

        updateContextCart();
        updateAiChatContextLabel();
        renderQuickPrompts();
        if (!aiChat.isOpen) toggleAiChat();
    } catch (err) {
        console.error('Failed to load session:', err);
    }
}

function startNewSession() {
    aiChat.sessionId = null;
    aiChat.history = [];
    aiChat.contextThreads = [];
    aiChat.contextContact = null;
    aiChat.contactMemories = [];
    aiChat._availableThreads = [];
    aiChat.threadId = null;
    aiChat.contactId = null;
    aiChat.emailId = null;
    aiChat.agent = 'general';
    selectAgent('general');
    clearAiChat();
    var picker = document.getElementById('ai-context-thread-picker');
    if (picker) { picker.style.display = 'none'; picker.innerHTML = ''; }
    var cart = document.getElementById('ai-context-cart');
    if (cart) cart.style.display = 'none';
    var memDiv = document.getElementById('ai-context-memories');
    if (memDiv) memDiv.style.display = 'none';
    updateAiChatContextLabel();
    renderQuickPrompts();
}

async function deleteChatSession(sessionId) {
    try {
        await fetch('api.php?action=ai_chat_session_delete', {
            method: 'POST', headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ session_id: sessionId })
        });
        loadChatSessions(); // refresh list
    } catch (e) { console.error(e); }
}

// --- Send AI Chat (enhanced) ---
async function sendAiChat() {
    var input = document.getElementById('ai-chat-input');
    var message = input.value.trim();
    if (!message) return;
    var model = document.getElementById('ai-chat-model').value;
    var providerSelect = document.getElementById('ai-chat-provider');
    var provider = providerSelect ? providerSelect.value : 'openai';
    var sendBtn = document.getElementById('ai-chat-send-btn');

    appendAiChatMessage('user', message);
    input.value = '';
    sendBtn.disabled = true; sendBtn.style.opacity = '0.5';
    aiChat.history.push({ role: 'user', content: message });
    var typingId = appendAiChatTyping();

    try {
        var payload = {
            message: message, model: model, provider: provider,
            mode: aiChat.mode,
            agent: aiChat.agent !== 'general' ? aiChat.agent : null,
            history: aiChat.history.slice(-10),
            session_id: aiChat.sessionId
        };

        // Multi-thread context
        if (aiChat.contextThreads.length > 0) {
            payload.thread_ids = aiChat.contextThreads.map(function(t) { return t.thread_id; });
        } else if (aiChat.threadId) {
            payload.thread_id = aiChat.threadId;
        }

        if (aiChat.contactId) payload.contact_id = aiChat.contactId;
        if (aiChat.emailId) payload.email_id = aiChat.emailId;

        var resp = await fetch('api.php?action=ai_chat', {
            method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload)
        });
        var data = await resp.json();
        removeAiChatTyping(typingId);

        if (data.success && data.answer) {
            // Store session ID from server
            if (data.session_id) aiChat.sessionId = data.session_id;

            aiChat.history.push({ role: 'assistant', content: data.answer });
            appendAiChatMessage('assistant', data.answer, data.model);

            // Show context stats if truncated
            if (data.context_stats && data.context_stats.truncated) {
                appendAiChatMessage('error', 'Note: Context was trimmed to fit model token limit (' + data.context_stats.estimated_tokens + ' tokens used)');
            }

            // Show extracted memories
            if (data.extracted_memories && data.extracted_memories.length > 0) {
                data.extracted_memories.forEach(function(m) { aiChat.contactMemories.push({ id: 'new_' + Date.now(), fact: m, source: 'auto' }); });
                renderContactMemories();
            }
        } else {
            appendAiChatMessage('error', (data.message || data.error || 'Unknown error'));
        }
    } catch (err) {
        removeAiChatTyping(typingId);
        appendAiChatMessage('error', 'Network error: ' + err.message);
    } finally {
        sendBtn.disabled = false; sendBtn.style.opacity = '1';
    }
}

function appendAiChatMessage(role, content, model) {
    var container = document.getElementById('ai-chat-messages');
    var isUser = role === 'user', isError = role === 'error';
    var wrapper = document.createElement('div');
    wrapper.style.cssText = 'display:flex;flex-direction:column;align-items:' + (isUser ? 'flex-end' : 'flex-start') + ';gap:4px;';
    var bubble = document.createElement('div');
    bubble.style.cssText = 'max-width:88%;padding:10px 13px;border-radius:' + (isUser ? '14px 14px 4px 14px' : '14px 14px 14px 4px') + ';font-size:0.82em;line-height:1.5;word-break:break-word;background:' + (isUser ? 'linear-gradient(135deg,#6366f1,#8b5cf6)' : isError ? '#3d1515' : '#252540') + ';color:' + (isUser ? '#fff' : isError ? '#fca5a5' : '#e2e8f0') + ';' + (isError ? 'border:1px solid #7f1d1d;' : '');
    if (!isUser && !isError) bubble.innerHTML = renderAiMarkdown(content);
    else bubble.textContent = content;
    wrapper.appendChild(bubble);

    if (!isUser && !isError) {
        var meta = document.createElement('div');
        meta.style.cssText = 'display:flex;gap:6px;align-items:center;';
        if (model) {
            var badge = document.createElement('span');
            badge.style.cssText = 'font-size:0.65em;color:#4a4a6a;background:#1e1e2e;padding:2px 6px;border-radius:4px;';
            badge.textContent = model; meta.appendChild(badge);
        }
        var copyBtn = document.createElement('button');
        copyBtn.style.cssText = 'font-size:0.65em;color:#6366f1;background:none;border:none;cursor:pointer;padding:2px 4px;';
        copyBtn.textContent = 'Copy';
        copyBtn.onclick = function() { navigator.clipboard.writeText(content).then(function() { copyBtn.textContent = 'Copied!'; setTimeout(function() { copyBtn.textContent = 'Copy'; }, 2000); }); };
        meta.appendChild(copyBtn);
        wrapper.appendChild(meta);
    }
    container.appendChild(wrapper);
    container.scrollTop = container.scrollHeight;
    return wrapper;
}

function appendAiChatTyping() {
    var container = document.getElementById('ai-chat-messages');
    var id = 'typing-' + Date.now();
    var el = document.createElement('div');
    el.id = id;
    el.innerHTML = '
...
';
    if (!document.getElementById('ai-chat-style')) {
        var s = document.createElement('style'); s.id = 'ai-chat-style';
        s.textContent = '@keyframes aiBounce{0%,80%,100%{opacity:0.3;transform:translateY(0)}40%{opacity:1;transform:translateY(-4px)}}';
        document.head.appendChild(s);
    }
    container.appendChild(el); container.scrollTop = container.scrollHeight;
    return id;
}

function removeAiChatTyping(id) { var el = document.getElementById(id); if (el) el.remove(); }

function renderAiMarkdown(text) {
    return text
        .replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
        .replace(/```([\s\S]*?)```/g, '
$1
')
        .replace(/`([^`]+)`/g, '$1')
        .replace(/\*\*([^*]+)\*\*/g, '$1').replace(/\*([^*]+)\*/g, '$1')
        .replace(/^### (.+)$/gm, '
$1
')
        .replace(/^## (.+)$/gm, '
$1
')
        .replace(/^# (.+)$/gm, '
$1
')
        .replace(/^[-*] (.+)$/gm, '
. $1
')
        .replace(/\n/g, '
');
}

function clearAiChat() {
    aiChat.history = [];
    document.getElementById('ai-chat-messages').innerHTML = '

AI

Chat cleared. Ask me anything!

';
}

// Draggable panel + initialization
document.addEventListener('DOMContentLoaded', function() {
    initAiProviderDropdown();
    var header = document.getElementById('ai-chat-header');
    var panel = document.getElementById('ai-chat-panel');
    if (!header || !panel) return;
    header.addEventListener('mousedown', function(e) {
        if (e.target.tagName === 'BUTTON') return;
        aiChat.isDragging = true;
        var rect = panel.getBoundingClientRect();
        aiChat.dragOffsetX = e.clientX - rect.left;
        aiChat.dragOffsetY = e.clientY - rect.top;
        panel.style.transition = 'none';
    });
    document.addEventListener('mousemove', function(e) {
        if (!aiChat.isDragging) return;
        panel.style.right = 'auto'; panel.style.bottom = 'auto';
        panel.style.left = Math.max(0, Math.min(e.clientX - aiChat.dragOffsetX, window.innerWidth - panel.offsetWidth)) + 'px';
        panel.style.top = Math.max(0, Math.min(e.clientY - aiChat.dragOffsetY, window.innerHeight - panel.offsetHeight)) + 'px';
    });
    document.addEventListener('mouseup', function() { aiChat.isDragging = false; });
});