Now replace the `toggleAiChat` through `clearAiChat` and draggable panel code with the enhanced versions:


Edit

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;
    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 += ' · ' + aiChat.threadSubject.substring(0, 30);
    if (aiChat.mode === 'contact' && aiChat.contactName) ctx += ' · ' + aiChat.contactName;
    label.textContent = ctx;
}

function renderQuickPrompts() {
    const container = document.getElementById('ai-quick-prompts');
    if (!container) return;
    const prompts = AI_QUICK_PROMPTS[aiChat.mode] || AI_QUICK_PROMPTS.general;
    container.innerHTML = prompts.map(p =>
        `<button onclick="sendAiChatPrompt(${JSON.stringify(p)})" 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(); }
}

async function sendAiChat() {
    const input = document.getElementById('ai-chat-input');
    const message = input.value.trim();
    if (!message) return;
    const model = document.getElementById('ai-chat-model').value;
    const 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 });
    const typingId = appendAiChatTyping();

    try {
        const payload = { message, model, mode: aiChat.mode, history: aiChat.history.slice(-10) };
        if (aiChat.threadId) payload.thread_id = aiChat.threadId;
        if (aiChat.contactId) payload.contact_id = aiChat.contactId;
        if (aiChat.emailId) payload.email_id = aiChat.emailId;

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

        if (data.success && data.answer) {
            aiChat.history.push({ role: 'assistant', content: data.answer });
            appendAiChatMessage('assistant', data.answer, data.model);
        } 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 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
    let prompts;
    const 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(p =>
        `<button onclick="sendAiChatPrompt(${JSON.stringify(p)})" 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() {
    const providerSelect = document.getElementById('ai-chat-provider');
    if (!providerSelect) return;
    providerSelect.innerHTML = '';
    Object.keys(AI_PROVIDER_MODELS).forEach(code => {
        const opt = document.createElement('option');
        opt.value = code;
        opt.textContent = AI_PROVIDER_NAMES[code] || code;
        providerSelect.appendChild(opt);
    });
    providerSelect.value = 'claude';
    updateAiModelDropdown();
}

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

// --- Agent Selector ---
function selectAgent(agentId) {
    aiChat.agent = agentId;
    const agent = AI_AGENTS[agentId];
    // Highlight active agent button
    document.querySelectorAll('.ai-agent-btn').forEach(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) {
        const providerSelect = document.getElementById('ai-chat-provider');
        if (providerSelect) { providerSelect.value = agent.preferredProvider; updateAiModelDropdown(); }
        if (agent.preferredModel) {
            const modelSelect = document.getElementById('ai-chat-model');
            if (modelSelect) modelSelect.value = agent.preferredModel;
        }
    }
    updateAiChatContextLabel();
    renderQuickPrompts();
}

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

async function searchContextContacts() {
    const query = document.getElementById('ai-context-search-input').value.trim();
    if (!query) return;
    const resultsDiv = document.getElementById('ai-context-search-results');
    resultsDiv.innerHTML = '
Searching...
';
    try {
        const data = await apiCall('contacts', { search: query, limit: 5 });
        if (!data.contacts || data.contacts.length === 0) {
            resultsDiv.innerHTML = '
No contacts found
';
            return;
        }
        resultsDiv.innerHTML = data.contacts.map(c => `

                ${escapeHtml(c.name || c.email)} ${escapeHtml(c.email)}
                ${c.total_emails || 0} emails

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

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

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

    // Load contact memories
    loadContactMemories(contactId);

    try {
        const 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;
        let 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(t => {
            const isAdded = aiChat.contextThreads.some(ct => 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))}\`, ${t.email_count||0}, '${escapeHtml(name)}')"
                        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(t => t.thread_id === threadId)) return;
    aiChat.contextThreads.push({ thread_id: threadId, 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(t => t.thread_id !== threadId);
    updateContextCart();
    updateAiChatContextLabel();
    renderQuickPrompts();
}

function addAllContactThreads() {
    const threads = aiChat._availableThreads || [];
    threads.forEach(t => {
        if (!aiChat.contextThreads.some(ct => 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?.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();
    const picker = document.getElementById('ai-context-thread-picker');
    if (picker) picker.style.display = 'none';
    const memDiv = document.getElementById('ai-context-memories');
    if (memDiv) memDiv.style.display = 'none';
}

function updateContextCart() {
    const cartDiv = document.getElementById('ai-context-cart');
    if (!cartDiv) return;
    if (aiChat.contextThreads.length === 0) { cartDiv.style.display = 'none'; return; }
    cartDiv.style.display = 'block';
    const totalEmails = aiChat.contextThreads.reduce((sum, t) => 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(t => `

                    ${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) {
    const memDiv = document.getElementById('ai-context-memories');
    if (!memDiv) return;
    try {
        const data = await apiCall('ai_contact_memories', { contact_id: contactId });
        aiChat.contactMemories = data.memories || [];
        renderContactMemories();
    } catch (e) {
        aiChat.contactMemories = [];
    }
}

function renderContactMemories() {
    const 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(m => `

                    ${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() {
    const 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 })
    }).then(r => r.json()).then(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(r => r.json()).then(data => {
        if (data.success) {
            aiChat.contactMemories = aiChat.contactMemories.filter(m => m.id !== memoryId);
            renderContactMemories();
        }
    });
}

// --- Session Management ---
async function loadChatSessions() {
    const overlay = document.getElementById('ai-session-overlay');
    if (!overlay) return;
    overlay.style.display = 'flex';
    overlay.innerHTML = '
Loading sessions...
';
    try {
        const data = await apiCall('ai_chat_sessions', { limit: 20 });
        const 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;
        }
        const agentIcons = {}; Object.values(AI_AGENTS).forEach(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(s => `

                                ${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() {
    const overlay = document.getElementById('ai-session-overlay');
    if (overlay) overlay.style.display = 'none';
}

async function loadChatSession(sessionId) {
    closeSessionOverlay();
    try {
        const data = await apiCall('ai_chat_session', { session_id: sessionId });
        const 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(tid => ({ thread_id: tid, subject: '', email_count: 0, contact_name: session.contact_name || '' }));
        aiChat.history = [];

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

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

        // Render messages
        const msgContainer = document.getElementById('ai-chat-messages');
        msgContainer.innerHTML = '';
        (session.messages || []).forEach(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();
    const picker = document.getElementById('ai-context-thread-picker');
    if (picker) { picker.style.display = 'none'; picker.innerHTML = ''; }
    const cart = document.getElementById('ai-context-cart');
    if (cart) cart.style.display = 'none';
    const 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() {
    const input = document.getElementById('ai-chat-input');
    const message = input.value.trim();
    if (!message) return;
    const model = document.getElementById('ai-chat-model').value;
    const providerSelect = document.getElementById('ai-chat-provider');
    const provider = providerSelect ? providerSelect.value : 'openai';
    const 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 });
    const typingId = appendAiChatTyping();

    try {
        const payload = {
            message, model, 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(t => 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;

        const resp = await fetch('api.php?action=ai_chat', {
            method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload)
        });
        const 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(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';
    }
}