// messages.js — P2P Messaging panel (MsgState)
// Extracted from dashboard.html (lines 5329-5584)

// ── Email triage state ────────────────────────────
// ── Messages (Phase 8) ──
// _msgPollInterval — managed by PollManager('messages')
// MsgState.selectedPeer / .typingTimer / .peers / .meshState / .pickerOpen (namespaced above)

function _renderContactList(contacts) {
    return contacts.map(c => {
        const dotCls = c.online ? 'online' : 'offline';
        const activeCls = c.peer_id === MsgState.selectedPeer ? ' active' : '';
        const unread = c.unread_count > 0 ? `<span class="msg-contact-unread">${c.unread_count}</span>` : '';
        return `<div class="msg-contact-item${activeCls}" onclick="selectContact('${c.peer_id}', this)">
            <span class="msg-online-dot ${dotCls}"></span>
            <div class="msg-contact-info">
                <div class="msg-contact-name">${_esc(c.peer_name)}</div>
                <div class="msg-contact-preview">${_esc(c.last_message || '')}</div>
            </div>
            ${unread}
        </div>`;
    }).join('');
}

function _renderSmartEmpty(contacts, meshState) {
    if (!meshState || !meshState.active) {
        return '<div class="msg-empty">Mesh not active.<br><a onclick="loadPanel(\'mesh\')">Enable mesh networking</a> in the Mesh tab to chat with peers.</div>';
    }
    if (meshState.peer_count === 0) {
        return '<div class="msg-empty">No peers found on your network yet.<br>Peers on the same LAN are discovered automatically.</div>';
    }
    if (meshState.trusted_count === 0) {
        return '<div class="msg-empty">You have peers nearby!<br><a onclick="loadPanel(\'mesh\')">Approve them in the Mesh tab</a> to start chatting.</div>';
    }
    if (meshState.messageable_count === 0) {
        return '<div class="msg-empty">Grant messaging permission to trusted peers<br>in the <a onclick="loadPanel(\'mesh\')">Mesh tab</a>.</div>';
    }
    if (contacts.length === 0) {
        return '<div class="msg-empty">Start a conversation with a trusted peer.<br>Click the <b>+</b> button above.</div>';
    }
    return '';
}

function _renderNewPicker(peers) {
    const picker = document.getElementById('msg-new-picker');
    if (!picker) return;
    if (!MsgState.pickerOpen) { picker.style.display = 'none'; return; }
    picker.style.display = '';
    if (!peers || peers.length === 0) {
        picker.innerHTML = '<div class="msg-picker-empty">No new peers available. <a onclick="loadPanel(\'mesh\')">Mesh tab</a></div>';
        return;
    }
    picker.innerHTML = '<div class="msg-picker-section">Start new chat with:</div>' +
        peers.map(p => {
            const dotCls = p.online ? 'online' : 'offline';
            return `<div class="msg-picker-item" onclick="selectNewContact('${p.peer_id}','${_esc(p.peer_name)}')">
                <span class="msg-online-dot ${dotCls}"></span>
                <span>${_esc(p.peer_name)}</span>
            </div>`;
        }).join('');
}

function toggleNewConvPicker() {
    MsgState.pickerOpen = !MsgState.pickerOpen;
    _renderNewPicker(MsgState.peers);
}

async function loadMessages() {
    const list = document.getElementById('msg-contact-list');
    try {
        const res = await apiFetch('/api/messages/poll');
        const data = await res.json();
        const contacts = data.contacts || [];
        MsgState.peers = data.peers || [];
        MsgState.meshState = data.mesh_state || null;
        const emptyHtml = _renderSmartEmpty(contacts, MsgState.meshState);
        if (contacts.length === 0) {
            list.innerHTML = emptyHtml || '<div class="msg-empty">No conversations yet</div>';
        } else {
            list.innerHTML = _renderContactList(contacts);
        }
        updateMsgBadge(contacts);
        _renderNewPicker(MsgState.peers);
        // Tip if default name
        const hist = document.getElementById('msg-history');
        if (!MsgState.selectedPeer && hist) {
            let tip = '';
            const nodeName = MsgState.meshState ? '' : '';
            tip = '<div class="msg-empty"><i class="fas fa-comment-dots" style="font-size:2rem;opacity:0.3"></i>Select a conversation or start a new one</div>';
            hist.innerHTML = tip;
        }
    } catch(e) {
        list.innerHTML = '<div class="msg-empty">Could not load contacts</div>';
    }
    _startMsgPolling();
}

function _startMsgPolling() {
    PollManager.start('messages', pollMessages, APP_CONFIG.poll.messages);
}

function _stopMsgPolling() {
    PollManager.stop('messages');
}

async function pollMessages() {
    try {
        const res = await apiFetch('/api/messages/poll');
        const data = await res.json();
        const contacts = data.contacts || [];
        MsgState.peers = data.peers || [];
        MsgState.meshState = data.mesh_state || null;

        const list = document.getElementById('msg-contact-list');
        if (contacts.length > 0) {
            list.innerHTML = _renderContactList(contacts);
        } else {
            const emptyHtml = _renderSmartEmpty(contacts, MsgState.meshState);
            list.innerHTML = emptyHtml || '<div class="msg-empty">No conversations yet</div>';
        }
        updateMsgBadge(contacts);
        if (MsgState.pickerOpen) _renderNewPicker(MsgState.peers);

        // Typing indicator
        const typingEl = document.getElementById('msg-typing');
        const typing = data.typing || [];
        if (MsgState.selectedPeer && typing.includes(MsgState.selectedPeer)) {
            typingEl.style.display = '';
        } else {
            typingEl.style.display = 'none';
        }

        // Reload current conversation if there are new messages
        if (MsgState.selectedPeer) {
            const conv = contacts.find(c => c.peer_id === MsgState.selectedPeer);
            if (conv && conv.unread_count > 0) {
                await _loadChatHistory(MsgState.selectedPeer);
                apiFetch(`/api/messages/${MsgState.selectedPeer}/read`, {method:'POST'});
            }
        }
    } catch(e) {}
}

function selectContact(peerId, el) {
    MsgState.selectedPeer = peerId;
    MsgState.pickerOpen = false;
    _renderNewPicker(MsgState.peers);
    document.querySelectorAll('.msg-contact-item').forEach(e => e.classList.remove('active'));
    if (el) el.classList.add('active');
    document.getElementById('msg-chat-header').style.display = '';
    document.getElementById('msg-input-wrap').style.display = '';
    const nameEl = el ? el.querySelector('.msg-contact-name') : null;
    document.getElementById('msg-chat-name').textContent = nameEl ? nameEl.textContent : peerId.substring(0, 8);
    const dot = el ? el.querySelector('.msg-online-dot') : null;
    document.getElementById('msg-chat-status').textContent = dot && dot.classList.contains('online') ? 'online' : 'offline';
    _loadChatHistory(peerId);
    apiFetch(`/api/messages/${peerId}/read`, {method:'POST'});
    document.getElementById('msg-input').focus();
}

function selectNewContact(peerId, peerName) {
    MsgState.selectedPeer = peerId;
    MsgState.pickerOpen = false;
    _renderNewPicker(MsgState.peers);
    document.querySelectorAll('.msg-contact-item').forEach(e => e.classList.remove('active'));
    document.getElementById('msg-chat-header').style.display = '';
    document.getElementById('msg-input-wrap').style.display = '';
    document.getElementById('msg-chat-name').textContent = peerName;
    document.getElementById('msg-chat-status').textContent = '';
    document.getElementById('msg-history').innerHTML = '<div class="msg-empty">No messages yet. Say hello!</div>';
    document.getElementById('msg-input').focus();
}

async function _loadChatHistory(peerId) {
    const hist = document.getElementById('msg-history');
    try {
        const res = await apiFetch(`/api/messages/${peerId}?limit=50`);
        const data = await res.json();
        const msgs = data.messages || [];
        if (msgs.length === 0) {
            hist.innerHTML = '<div class="msg-empty">No messages yet</div>';
        } else {
            hist.innerHTML = msgs.map(renderMsgBubble).join('');
            hist.scrollTop = hist.scrollHeight;
        }
    } catch(e) {
        hist.innerHTML = '<div class="msg-empty">Failed to load messages</div>';
    }
}

function renderMsgBubble(msg) {
    const cls = msg.direction === 'outgoing' ? 'outgoing' : 'incoming';
    const t = msg.timestamp ? formatDate(msg.timestamp, 'time') : '';
    let statusIcon = '';
    if (msg.direction === 'outgoing') {
        switch(msg.status) {
            case 'queued': statusIcon = '<i class="fas fa-clock"></i>'; break;
            case 'sent': statusIcon = '<i class="fas fa-check"></i>'; break;
            case 'delivered': statusIcon = '<i class="fas fa-check-double"></i>'; break;
            case 'read': statusIcon = '<i class="fas fa-check-double" style="color:var(--success)"></i>'; break;
            case 'failed': statusIcon = '<i class="fas fa-exclamation-circle" style="color:var(--error-strong)"></i>'; break;
        }
    }
    return `<div class="msg-bubble ${cls}">
        ${_esc(msg.body)}
        <div class="msg-bubble-meta">${t} ${statusIcon}</div>
    </div>`;
}

async function sendPeerMsg(msgText) {
    if (!MsgState.selectedPeer) return;
    const inp = document.getElementById('msg-input');
    const body = msgText != null ? msgText.trim() : inp.value.trim();
    if (!body) return;
    inp.value = '';

    // Optimistic append
    const hist = document.getElementById('msg-history');
    const emptyMsg = hist.querySelector('.msg-empty');
    if (emptyMsg) emptyMsg.remove();
    const t = formatDate(new Date(), 'time');
    hist.insertAdjacentHTML('beforeend', `<div class="msg-bubble outgoing">${_esc(body)}<div class="msg-bubble-meta">${t} <i class="fas fa-clock"></i></div></div>`);
    hist.scrollTop = hist.scrollHeight;

    try {
        await apiFetch(`/api/messages/${MsgState.selectedPeer}/send`, {
            method: 'POST',
            headers: {'Content-Type':'application/json'},
            body: JSON.stringify({body})
        });
        // Reload to get real status
        await _loadChatHistory(MsgState.selectedPeer);
    } catch(e) {}
}

function updateMsgBadge(contacts) {
    const badge = document.getElementById('msg-badge');
    const total = (contacts || []).reduce((s, c) => s + (c.unread_count || 0), 0);
    if (total > 0) {
        badge.textContent = total > 99 ? '99+' : total;
        badge.style.display = '';
    } else {
        badge.style.display = 'none';
    }
}

// Typing indicator: debounced on keypress
document.addEventListener('DOMContentLoaded', () => {
    const msgInp = document.getElementById('msg-input');
    if (msgInp) {
        msgInp.addEventListener('input', () => {
            if (!MsgState.selectedPeer) return;
            if (MsgState.typingTimer) clearTimeout(MsgState.typingTimer);
            apiFetch(`/api/messages/${MsgState.selectedPeer}/typing`, {method:'POST'});
            MsgState.typingTimer = setTimeout(() => { MsgState.typingTimer = null; }, 3000);
        });
    }
});

