/*
 * 用户会话脚本：负责单会话消息轮询、发送和可爱状态文案。
 * 作者: @ccfork
 */
(() => {
    const config = window.CHAT_CONFIG || {};
    const apiUrl = config.apiUrl || 'chat_api.php';
    const sessionId = config.sessionId || '';

    let lastMessageId = 0;
    let lastClearSeq = Number(localStorage.getItem(`chat_clear_seq_${sessionId}`) || 0);
    let lastRecallSeq = Number(localStorage.getItem(`chat_recall_seq_${sessionId}`) || 0);
    let pollingInterval = null;
    let renderedMessageIds = new Set();
    let emojiPanel = null;
    let messageActions = null;
    let toastTimer = null;
    let typingTimer = null;

    const els = {};

    function $(id) {
        return document.getElementById(id);
    }

    function initElements() {
        [
            'currentSessionStatus',
            'messagesContainer',
            'messageInput',
            'sendBtn',
            'refreshBtn',
            'questionnaireBtn',
            'emojiToggle',
            'imageBtn',
            'imageInput',
            'imageUploadProgress',
            'emojiPanelHost',
            'toast'
        ].forEach((id) => {
            els[id] = $(id);
        });
    }

    function escapeHtml(text) {
        const div = document.createElement('div');
        div.textContent = text == null ? '' : String(text);
        return div.innerHTML;
    }

    function showToast(message) {
        if (!els.toast) return;
        els.toast.textContent = message;
        els.toast.hidden = false;
        clearTimeout(toastTimer);
        toastTimer = setTimeout(() => {
            els.toast.hidden = true;
        }, 2200);
    }

    function messagePreview(msg) {
        return window.MessageActions?.previewMessage(msg) || String(msg?.message || '').slice(0, 80);
    }

    function replyHtml(msg) {
        return window.MessageActions?.renderReplyBlock(msg.reply, { selfSender: 'user' }) || '';
    }

    function timeHtml(msg) {
        if (msg.recalled) {
            return `<div class="message-time"><span class="message-recall-label">已撤回</span><span>${escapeHtml(msg.time || '')}</span></div>`;
        }
        return `<div class="message-time">${escapeHtml(msg.time || '')}</div>`;
    }

    function buildApiUrl(action, params = {}) {
        const query = new URLSearchParams({ action, ...params });
        return `${apiUrl}?${query.toString()}`;
    }

    async function registerSession() {
        if (!sessionId) return;
        try {
            await fetch(apiUrl, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ action: 'register_session', session_id: sessionId })
            });
        } catch (error) {
            console.error('注册会话失败:', error);
        }
    }

    async function updatePresence(options = {}) {
        if (!sessionId) return;
        try {
            await fetch(apiUrl, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    action: 'update_presence',
                    session_id: sessionId,
                    seen_admin_id: options.seenAdminId,
                    typing: !!options.typing
                })
            });
        } catch (error) {
            console.error('状态同步失败:', error);
        }
    }

    function renderEmptyState(title = '还没有小纸条', subtitle = '想说的话，可以慢慢写在这里～') {
        els.messagesContainer.innerHTML = `
            <div class="empty-state">
                <i class="fas fa-heart"></i>
                <strong>${escapeHtml(title)}</strong>
                <span>${escapeHtml(subtitle)}</span>
            </div>
        `;
    }

    function appendMessages(messages) {
        const fragment = document.createDocumentFragment();
        const stickerPacks = emojiPanel?.getStickerPacks() || [];
        let maxAdminMessageId = Number(localStorage.getItem(`chat_seen_admin_${sessionId}`) || 0);

        messages.forEach((msg) => {
            if (renderedMessageIds.has(msg.id)) return;
            renderedMessageIds.add(msg.id);
            if (msg.sender === 'admin') {
                maxAdminMessageId = Math.max(maxAdminMessageId, Number(msg.id || 0));
            }

            const group = document.createElement('article');
            const sender = msg.sender === 'admin' ? 'admin' : 'user';
            const avatar = sender === 'user' ? '<i class="fas fa-user"></i>' : '💌';
            const isImage = msg.type === 'image' && msg.image && msg.image.url;
            const content = isImage ? null : window.ChatEmoji.renderMessageContent(msg.message, stickerPacks);
            group.className = `message-group ${sender}`;
            if (msg.recalled) group.classList.add('recalled');
            group.dataset.messageId = String(msg.id || 0);
            group.dataset.sender = msg.sender === 'admin' ? 'admin' : 'user';
            group.dataset.type = isImage ? 'image' : 'text';
            group.dataset.preview = messagePreview(msg);
            group.dataset.recalled = msg.recalled ? '1' : '0';
            if (msg.recalled) {
                group.innerHTML = `
                    <div class="message-avatar">${avatar}</div>
                    <div class="message-body">
                        <div class="message-bubble recalled-bubble">这条小纸条已经撤回啦～</div>
                        ${timeHtml(msg)}
                    </div>
                `;
                fragment.appendChild(group);
                return;
            }
            group.innerHTML = isImage ? `
                <div class="message-avatar">${avatar}</div>
                <div class="message-body">
                    <div class="message-bubble image-bubble">${replyHtml(msg)}<img class="message-image" src="${escapeHtml(msg.image.url)}" alt="图片消息"></div>
                    ${timeHtml(msg)}
                </div>
            ` : `
                <div class="message-avatar">${avatar}</div>
                <div class="message-body">
                    <div class="message-bubble">${replyHtml(msg)}<div class="message-text">${content.html}</div></div>
                    ${timeHtml(msg)}
                </div>
            `;
            if (!isImage && content.hasSoloSticker) {
                group.querySelector('.message-bubble')?.classList.add('has-sticker');
            }
            fragment.appendChild(group);
        });

        if (!fragment.childNodes.length) return;
        if (els.messagesContainer.querySelector('.empty-state')) {
            els.messagesContainer.innerHTML = '';
        }
        els.messagesContainer.appendChild(fragment);
        els.messagesContainer.scrollTop = els.messagesContainer.scrollHeight;
        if (maxAdminMessageId > 0) {
            localStorage.setItem(`chat_seen_admin_${sessionId}`, String(maxAdminMessageId));
            updatePresence({ seenAdminId: maxAdminMessageId, typing: false });
        }
    }

    async function loadMessages(options = {}) {
        if (!sessionId) return;
        const shouldReset = options.reset === true;
        if (shouldReset) {
            lastMessageId = 0;
            renderedMessageIds = new Set();
            els.messagesContainer.innerHTML = `
                <div class="state-block">
                    <span>🍬 正在打开小纸条...</span>
                </div>
            `;
        }

        try {
            const response = await fetch(buildApiUrl('get_messages', {
                session_id: sessionId,
                last_id: String(lastMessageId)
            }), { cache: 'no-store' });
            const data = await response.json();
            if (!data.success) return;
            const messages = data.messages || [];
            const clearSeq = Number(data.clear_seq || 0);
            const recallSeq = Number(data.recall_seq || 0);
            if (clearSeq > lastClearSeq) {
                lastClearSeq = clearSeq;
                localStorage.setItem(`chat_clear_seq_${sessionId}`, String(clearSeq));
                localStorage.setItem(`chat_seen_admin_${sessionId}`, String(data.clear_after_id || 0));
                lastMessageId = Number(data.clear_after_id || 0);
                renderedMessageIds = new Set();
                renderEmptyState();
                els.currentSessionStatus.textContent = '小纸条信箱已经整理好啦～';
                if (!messages.length) return;
            }
            if (!shouldReset && recallSeq > lastRecallSeq) {
                lastRecallSeq = recallSeq;
                localStorage.setItem(`chat_recall_seq_${sessionId}`, String(recallSeq));
                await loadMessages({ reset: true });
                return;
            }
            if (recallSeq > lastRecallSeq) {
                lastRecallSeq = recallSeq;
                localStorage.setItem(`chat_recall_seq_${sessionId}`, String(recallSeq));
            }

            if (shouldReset) {
                els.messagesContainer.innerHTML = '';
            }
            if (messages.length) {
                appendMessages(messages);
                lastMessageId = messages[messages.length - 1].id;
                els.currentSessionStatus.textContent = '小纸条已经放进信箱啦～';
            } else if (shouldReset) {
                renderEmptyState();
                els.currentSessionStatus.textContent = '写点悄悄话也可以～';
            }
        } catch (error) {
            console.error('加载消息失败:', error);
            if (shouldReset) renderEmptyState('加载失败', '稍后再刷新一次～');
            els.currentSessionStatus.textContent = '信箱有点卡，等一下下～';
        }
    }

    async function postMessage(message, reply = null) {
        if (!message || !sessionId) return false;
        try {
            const response = await fetch(apiUrl, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    action: 'send_message',
                    session_id: sessionId,
                    message,
                    sender: 'user',
                    reply
                })
            });
            const data = await response.json();
            if (!data.success) {
                showToast(data.error || '发送失败');
                return false;
            }
            return true;
        } catch (error) {
            console.error('发送失败:', error);
            showToast('发送失败，请重试～');
            return false;
        }
    }

    async function recallMessage(message) {
        if (!message?.id || !sessionId) return;
        try {
            const response = await fetch(apiUrl, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    action: 'recall_message',
                    session_id: sessionId,
                    message_id: message.id,
                    sender: 'user'
                })
            });
            const data = await response.json();
            if (!data.success) {
                showToast(data.error || '撤回失败');
                return;
            }
            await loadMessages({ reset: true });
        } catch (error) {
            console.error('撤回失败:', error);
            showToast('撤回失败，请重试～');
        }
    }

    async function postImage(file) {
        if (!file || !sessionId) return false;
        if (file.size > 5 * 1024 * 1024) {
            showToast('图片最大 5MB');
            return false;
        }
        const form = new FormData();
        form.append('action', 'send_image');
        form.append('session_id', sessionId);
        form.append('sender', 'user');
        const reply = messageActions?.getReply();
        if (reply) form.append('reply', JSON.stringify(reply));
        form.append('image', file);
        return await uploadImageForm(form);
    }

    function updateUploadProgress(percent, text = '图片发送中') {
        if (!els.imageUploadProgress) return;
        const value = Math.max(0, Math.min(100, Number(percent || 0)));
        els.imageUploadProgress.hidden = false;
        els.imageUploadProgress.querySelector('.upload-progress-bar span').style.width = `${value}%`;
        els.imageUploadProgress.querySelector('p').textContent = `${text} ${value}%`;
    }

    function hideUploadProgress() {
        if (!els.imageUploadProgress) return;
        els.imageUploadProgress.hidden = true;
        els.imageUploadProgress.querySelector('.upload-progress-bar span').style.width = '0%';
        els.imageUploadProgress.querySelector('p').textContent = '图片发送中 0%';
    }

    async function uploadImageForm(form) {
        updateUploadProgress(0);
        try {
            const data = await new Promise((resolve, reject) => {
                const xhr = new XMLHttpRequest();
                xhr.open('POST', apiUrl);
                xhr.upload.onprogress = (event) => {
                    if (event.lengthComputable) updateUploadProgress(Math.round((event.loaded / event.total) * 100));
                };
                xhr.onload = () => {
                    try {
                        resolve(JSON.parse(xhr.responseText || '{}'));
                    } catch (error) {
                        reject(error);
                    }
                };
                xhr.onerror = () => reject(new Error('图片上传失败'));
                xhr.send(form);
            });
            if (!data.success) {
                showToast(data.error || '图片发送失败');
                return false;
            }
            updateUploadProgress(100, '图片已发送');
            return true;
        } catch (error) {
            console.error('图片发送失败:', error);
            showToast('图片发送失败，请重试～');
            return false;
        } finally {
            setTimeout(hideUploadProgress, 600);
        }
    }

    async function sendImage(file) {
        els.imageBtn.disabled = true;
        const success = await postImage(file);
        if (success) {
            messageActions?.clearReply();
            await loadMessages({ reset: true });
        }
        els.imageBtn.disabled = false;
        els.imageInput.value = '';
    }

    async function sendMessage() {
        const message = window.ChatEmoji.convertEmoji(els.messageInput.value.trim());
        if (!message || !sessionId) return;

        emojiPanel?.close();
        els.sendBtn.disabled = true;
        const success = await postMessage(message, messageActions?.getReply() || null);
        if (success) {
            els.messageInput.value = '';
            messageActions?.clearReply();
            resizeInput();
            await loadMessages({ reset: true });
        }
        els.sendBtn.disabled = false;
        els.messageInput.focus();
    }

    function resizeInput() {
        const input = els.messageInput;
        input.style.height = 'auto';
        input.style.height = `${Math.min(input.scrollHeight, 128)}px`;
    }

    function markTyping() {
        updatePresence({ typing: true });
        clearTimeout(typingTimer);
        typingTimer = setTimeout(() => updatePresence({ typing: false }), 1800);
    }

    function bindEvents() {
        els.sendBtn.addEventListener('click', sendMessage);
        els.imageBtn.addEventListener('click', () => els.imageInput.click());
        els.imageInput.addEventListener('change', () => sendImage(els.imageInput.files?.[0]));
        els.refreshBtn.addEventListener('click', () => loadMessages({ reset: true }));
        els.questionnaireBtn.addEventListener('click', () => {
            window.location.href = `index.php?session_id=${encodeURIComponent(sessionId)}`;
        });
        els.messageInput.addEventListener('input', () => {
            resizeInput();
            markTyping();
        });
        els.messageInput.addEventListener('keydown', (event) => {
            if (event.key === 'Enter' && !event.shiftKey) {
                event.preventDefault();
                sendMessage();
            }
        });
        document.addEventListener('keydown', (event) => {
            if (event.key === 'Escape') {
                emojiPanel?.close();
                messageActions?.closeMenu();
            }
        });
    }

    async function init() {
        initElements();
        bindEvents();
        emojiPanel = window.ChatEmoji.createPanel({
            host: els.emojiPanelHost,
            trigger: els.emojiToggle,
            input: els.messageInput,
            apiUrl
        });
        await emojiPanel.init();
        messageActions = window.MessageActions?.bindMessageActions({
            container: els.messagesContainer,
            input: els.messageInput,
            draftHost: els.emojiPanelHost,
            selfSender: 'user',
            canRecall: (message) => message.sender === 'user' && !message.recalled,
            onRecall: recallMessage
        });
        await registerSession();
        await loadMessages({ reset: true });
        pollingInterval = setInterval(() => loadMessages(), 1800);
    }

    window.addEventListener('beforeunload', () => {
        if (pollingInterval) clearInterval(pollingInterval);
        if (typingTimer) clearTimeout(typingTimer);
        updatePresence({ typing: false });
    });
    document.addEventListener('DOMContentLoaded', init);
})();
