/**
 * 群组聊天模块
 * 彩蛋功能:通过控制台开启
 */

import {dialog} from '../dialog.js';
import {outPutInfo, outPutError, outPutSuccess} from '../console-logger.js';
import {canvasChat} from './canvas-chat.js';

class GroupChat {
    constructor() {
        this.connection = null;
        this.isOpen = false;
        this.currentUserId = null;
        this.loadedPageIndex = 0;
        this.hasMoreHistory = true;
        this.isLoadingHistory = false;
        this.maxHistoryCount = 1000;
        this.loadedHistoryCount = 0;
        this.MOBILE_BREAKPOINT = 768;
        this.CHAT_HASH = '#group-chat';
        this.init();
        this.initMobileViewport();
        this.initHashListener();
    }

    init() {
        // 创建触发按钮(隐藏,通过控制台显示)
        this.createTriggerButton();

        // 监听控制台命令
        this.setupConsoleCommand();
    }

    initHashListener() {
        // 监听 hash 变化(浏览器前进后退)
        window.addEventListener('hashchange', () => {
            if (this.isMobile() && this.isOpen && window.location.hash !== this.CHAT_HASH) {
                // 移动端:hash被清除,关闭群聊
                this.close();
            }
        });
    }

    isMobile() {
        return window.innerWidth <= this.MOBILE_BREAKPOINT;
    }

    disableBodyScroll() {
        if (this.isMobile()) {
            document.body.style.overflow = 'hidden';
            document.body.style.position = 'fixed';
            document.body.style.width = '100%';
            document.body.style.top = `-${window.scrollY}px`;
            this.scrollPosition = window.scrollY;
        }
    }

    enableBodyScroll() {
        if (this.isMobile()) {
            document.body.style.overflow = '';
            document.body.style.position = '';
            document.body.style.width = '';
            document.body.style.top = '';
            if (this.scrollPosition !== undefined) {
                window.scrollTo(0, this.scrollPosition);
                this.scrollPosition = undefined;
            }
        }
    }

    initMobileViewport() {
        // 设置 CSS 自定义属性来处理移动端视口高度
        const setViewportHeight = () => {
            // 获取真实视口高度(不包括地址栏等)
            const vh = window.innerHeight * 0.01;
            document.documentElement.style.setProperty('--vh', `${vh}px`);
        };

        // 初始设置
        setViewportHeight();

        // 监听窗口大小变化和方向变化
        window.addEventListener('resize', setViewportHeight);
        window.addEventListener('orientationchange', () => {
            setTimeout(setViewportHeight, 100);
        });

        // iOS Safari 特殊处理:监听滚动事件来调整视口
        if (/iPhone|iPad|iPod/.test(navigator.userAgent)) {
            let lastScrollTop = 0;
            window.addEventListener('scroll', () => {
                const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
                if (scrollTop !== lastScrollTop) {
                    setViewportHeight();
                    lastScrollTop = scrollTop;
                }
            }, { passive: true });
        }

        // 监听视口变化(Visual Viewport API,如果支持)
        if (window.visualViewport) {
            window.visualViewport.addEventListener('resize', setViewportHeight);
            window.visualViewport.addEventListener('scroll', setViewportHeight);
        }
    }

    createTriggerButton() {
        const trigger = document.createElement('button');
        trigger.className = 'group-chat__trigger';
        trigger.innerHTML = '💬';
        trigger.setAttribute('aria-label', '打开群组聊天');
        trigger.style.display = 'none';
        trigger.addEventListener('click', () => this.open());
        document.body.appendChild(trigger);
        this.triggerButton = trigger;
    }

    setupConsoleCommand() {
        // 在控制台输入 window.openGroupChat() 来开启
        window.openGroupChat = () => {
            if (!this.isOpen) {
                this.open().then(() => outPutSuccess('群组聊天已打开'));
            } else {
                outPutInfo('群组聊天已经打开');
            }
        };

        // 显示提示
        outPutInfo('💬 群组聊天');
        outPutInfo('输入 window.openGroupChat() 来开启群组聊天');
    }

    async open() {
        if (this.isOpen) return;

        this.isOpen = true;
        
        // 移动端:添加 hash 和禁用滚动
        if (this.isMobile()) {
            // 避免触发 hashchange 事件导致立即关闭
            if (window.location.hash !== this.CHAT_HASH) {
                window.location.hash = this.CHAT_HASH;
            }
            this.disableBodyScroll();
        }
        
        this.createUI();
        await this.connect();
    }

    createUI() {
        // 创建聊天面板
        const chatPanel = document.createElement('div');
        chatPanel.className = 'group-chat';
        chatPanel.innerHTML = `
            <div class="group-chat__header">
                <h3 class="group-chat__title">群组聊天</h3>
                <button class="group-chat__close" aria-label="关闭">
                    <i class="fa fa-times"></i>
                </button>
            </div>
            <div class="group-chat__messages" id="group-chat-messages">
                <div class="group-chat__load-more" id="group-chat-load-more" style="display: none;">
                    <span>加载更多...</span>
                </div>
            </div>
            <div class="group-chat__input-area">
                <div class="group-chat__commands" id="group-chat-commands">
                    <div class="group-chat__command-item" data-command="/canvas">
                        <span class="group-chat__command-name">/canvas</span>
                        <span class="group-chat__command-desc">开启/加入 你画我猜</span>
                    </div>
                </div>
                <textarea 
                    class="group-chat__input" 
                    id="group-chat-input" 
                    placeholder="输入消息... (/ 显示命令)"
                    rows="1"
                ></textarea>
                <button class="group-chat__send-btn" id="group-chat-send">发送</button>
            </div>
        `;

        document.body.appendChild(chatPanel);
        this.chatPanel = chatPanel;
        this.messagesContainer = chatPanel.querySelector('#group-chat-messages');
        this.loadMoreBtn = chatPanel.querySelector('#group-chat-load-more');
        this.input = chatPanel.querySelector('#group-chat-input');
        this.sendBtn = chatPanel.querySelector('#group-chat-send');
        this.commandsPanel = chatPanel.querySelector('#group-chat-commands');

        // 绑定事件
        this.bindEvents();

        // 显示动画
        requestAnimationFrame(() => {
            chatPanel.classList.add('group-chat--visible');
            // 确保视口高度已更新
            const vh = window.innerHeight * 0.01;
            document.documentElement.style.setProperty('--vh', `${vh}px`);
        });

        // 隐藏触发按钮
        if (this.triggerButton) {
            this.triggerButton.style.display = 'none';
        }
    }

    bindEvents() {
        // 关闭按钮
        this.chatPanel.querySelector('.group-chat__close').addEventListener('click', async () => {
            await this.close();
        });

        // 发送按钮
        this.sendBtn.addEventListener('click', async () => {
            await this.handleSend();
        });

        // 输入框回车发送(Shift+Enter换行)
        this.input.addEventListener('keydown', async (e) => {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                await this.handleSend();
            }
        });

        // 自动调整输入框高度 & 命令提示
        this.input.addEventListener('input', () => {
            this.input.style.height = 'auto';
            this.input.style.height = `${Math.min(this.input.scrollHeight, 120)}px`;
            
            const val = this.input.value;
            if (val.startsWith('/')) {
                this.commandsPanel.classList.add('group-chat__commands--visible');
            } else {
                this.commandsPanel.classList.remove('group-chat__commands--visible');
            }
        });

        // 命令点击
        this.commandsPanel.querySelectorAll('.group-chat__command-item').forEach(item => {
            item.addEventListener('click', () => {
                const cmd = item.dataset.command;
                this.input.value = cmd;
                this.commandsPanel.classList.remove('group-chat__commands--visible');
                this.input.focus();
            });
        });

        // 加载更多
        this.loadMoreBtn.addEventListener('click', async () => {
            await this.loadMoreHistory();
        });

        // 滚动加载历史记录
        this.messagesContainer.addEventListener('scroll', async () => {
            if (this.messagesContainer.scrollTop === 0 &&
                this.hasMoreHistory &&
                !this.isLoadingHistory &&
                this.loadedHistoryCount < this.maxHistoryCount) {
                await this.loadMoreHistory();
            }
        });
    }

    async handleSend() {
        const content = this.input.value.trim();
        if (!content) return;

        if (content.startsWith('/')) {
            await this.handleCommand(content);
        } else {
            await this.sendMessage();
        }
    }

    async handleCommand(cmd) {
        if (cmd === '/canvas') {
            this.input.value = '';
            this.input.style.height = 'auto';
            this.commandsPanel.classList.remove('group-chat__commands--visible');
            
            canvasChat.open();
            if (!canvasChat.drawingUser) {
                 await canvasChat.requestAccess();
            }
        } else {
            // 未知命令,当做普通消息发送
            await this.sendMessage();
        }
    }

    async connect() {
        try {
            this.connection = new signalR
                .HubConnectionBuilder()
                .withUrl("/groupchat", {
                    skipNegotiation: true,
                    transport: signalR.HttpTransportType.WebSockets,
                })
                .withAutomaticReconnect()
                .build();

            // 注册客户端方法
            this.connection.on("OnMessageReceived", (message) => {
                this.addMessage(message, message.userId === this.currentUserId);
            });

            this.connection.on("OnUserJoined", (user) => {
                this.addSystemMessage(`${user.name} 加入了群组`);
            });

            this.connection.on("OnUserLeft", (user) => {
                this.addSystemMessage(`${user.name} 离开了群组`);
            });

            this.connection.on("OnHistoryLoaded", (messages, hasMore) => {
                this.handleHistoryLoaded(messages, hasMore);
            });

            this.connection.on("OnError", (error) => {
                dialog.toast(error, 'error');
            });

            // 连接
            await this.connection.start();

            // 加入群组
            const currentUser = await this.connection.invoke("JoinGroup",null);
            if (currentUser) {
                this.currentUserId = currentUser.id;
                canvasChat.setUserId(this.currentUserId);
            }
            
            canvasChat.init(this.connection);

            // 加载历史记录
            await this.loadInitialHistory();

            outPutSuccess('已连接到群组聊天');
            dialog.toast('已连接到群组聊天', 'success');
        } catch (error) {
            outPutError(`连接群组聊天失败: ${error.message || error}`);
            dialog.toast('连接失败,请刷新页面重试', 'error');
        }
    }

    async loadInitialHistory() {
        this.loadedPageIndex = 1;
        this.loadedHistoryCount = 0;
        this.hasMoreHistory = true;

        // 先加载第一页
        await this.connection.invoke("GetHistory", 1, 50);
    }

    async loadMoreHistory() {
        if (this.isLoadingHistory || !this.hasMoreHistory ||
            this.loadedHistoryCount >= this.maxHistoryCount) {
            return;
        }

        this.isLoadingHistory = true;
        this.loadMoreBtn.style.display = 'block';
        this.loadMoreBtn.classList.add('group-chat__load-more--loading');
        this.loadMoreBtn.querySelector('span').textContent = '加载中...';

        try {
            const nextPage = this.loadedPageIndex + 1;
            const scrollHeight = this.messagesContainer.scrollHeight;
            const scrollTop = this.messagesContainer.scrollTop;

            await this.connection.invoke("GetHistory", nextPage, 50);

            // 恢复滚动位置
            requestAnimationFrame(() => {
                const newScrollHeight = this.messagesContainer.scrollHeight;
                this.messagesContainer.scrollTop = newScrollHeight - scrollHeight + scrollTop;
            });
        } catch (error) {
            outPutError(`加载历史记录失败: ${error.message || error}`);
            dialog.toast('加载历史记录失败', 'error');
        } finally {
            this.isLoadingHistory = false;
            this.loadMoreBtn.classList.remove('group-chat__load-more--loading');
        }
    }

    handleHistoryLoaded(messages, hasMore) {
        this.hasMoreHistory = hasMore;
        this.loadedPageIndex++;
        this.loadedHistoryCount += messages.length;

        // 如果已加载超过1000条,隐藏加载更多按钮
        if (this.loadedHistoryCount >= this.maxHistoryCount) {
            this.hasMoreHistory = false;
            this.loadMoreBtn.style.display = 'none';
        } else if (!hasMore) {
            this.loadMoreBtn.style.display = 'none';
        } else {
            this.loadMoreBtn.style.display = 'block';
            this.loadMoreBtn.querySelector('span').textContent = '加载更多...';
        }

        // 插入到顶部(历史记录是倒序的,最新的在最后)
        const fragment = document.createDocumentFragment();
        messages.forEach(msg => {
            const isOwn = msg.userId === this.currentUserId;
            const messageEl = this.createMessageElement(msg, isOwn);
            fragment.insertBefore(messageEl, fragment.firstChild);
        });

        // 如果这是第一次加载,插入到容器顶部
        if (this.loadedPageIndex === 2) {
            this.messagesContainer.insertBefore(fragment, this.loadMoreBtn.nextSibling);
            // 滚动到底部
            this.scrollToBottom();
        } else {
            this.messagesContainer.insertBefore(fragment, this.loadMoreBtn.nextSibling);
        }
    }

    async sendMessage() {
        const message = this.input.value.trim();
        if (!message || !this.connection) return;

        // 禁用发送按钮
        this.sendBtn.disabled = true;
        this.input.disabled = true;

        try {
            await this.connection.invoke("SendMessage", message);
            this.input.value = '';
            this.input.style.height = 'auto';
        } catch (error) {
            outPutError(`发送消息失败: ${error.message || error}`);
            dialog.toast('发送失败,请重试', 'error');
        } finally {
            this.sendBtn.disabled = false;
            this.input.disabled = false;
            this.input.focus();
        }
    }

    addMessage(message, isOwn = false) {
        // 如果是自己的消息,更新currentUserId
        if (isOwn && !this.currentUserId) {
            this.currentUserId = message.userId;
        }

        const messageEl = this.createMessageElement(message, isOwn);
        this.messagesContainer.appendChild(messageEl);
        this.scrollToBottom();
    }

    createMessageElement(message, isOwn = false) {
        const messageDiv = document.createElement('div');
        messageDiv.className = `group-chat__message${isOwn ? ' group-chat__message--own' : ''}`;

        const avatar = document.createElement('img');
        avatar.className = 'group-chat__avatar';
        avatar.src = message.avatar;
        avatar.alt = message.userName;

        const contentDiv = document.createElement('div');
        contentDiv.className = 'group-chat__message-content';

        const username = document.createElement('div');
        username.className = 'group-chat__username';
        username.textContent = message.userName;

        const bubble = document.createElement('div');
        bubble.className = 'group-chat__bubble';
        bubble.textContent = message.message;

        const timestamp = document.createElement('div');
        timestamp.className = 'group-chat__timestamp';
        timestamp.textContent = this.formatTime(message.sendTime);

        contentDiv.appendChild(username);
        contentDiv.appendChild(bubble);
        contentDiv.appendChild(timestamp);

        messageDiv.appendChild(avatar);
        messageDiv.appendChild(contentDiv);

        return messageDiv;
    }

    addSystemMessage(text) {
        const systemDiv = document.createElement('div');
        systemDiv.className = 'group-chat__system-message';
        systemDiv.textContent = text;
        this.messagesContainer.appendChild(systemDiv);
        this.scrollToBottom();
    }

    formatTime(dateTime) {
        const date = new Date(dateTime);
        const now = new Date();
        const diff = (now - date) / 1000; // 秒

        if (diff < 60) {
            return '刚刚';
        } else if (diff < 3600) {
            return `${Math.floor(diff / 60)}分钟前`;
        } else if (diff < 86400) {
            return `${Math.floor(diff / 3600)}小时前`;
        } else {
            return date.toLocaleDateString('zh-CN', {
                month: '2-digit',
                day: '2-digit',
                hour: '2-digit',
                minute: '2-digit'
            });
        }
    }

    scrollToBottom() {
        requestAnimationFrame(() => {
            this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;
        });
    }

    async close() {
        if (!this.isOpen) return;
        
        if (this.connection) {
            try {
                await this.connection.stop();
            } catch (error) {
                outPutError(`断开连接失败: ${error.message || error}`);
            }
        }

        if (this.chatPanel) {
            this.chatPanel.classList.remove('group-chat--visible');
            setTimeout(() => {
                if (this.chatPanel.parentNode) {
                    this.chatPanel.parentNode.removeChild(this.chatPanel);
                }
            }, 300);
        }

        this.isOpen = false;
        this.connection = null;
        this.currentUserId = null;
        this.loadedPageIndex = 0;
        this.hasMoreHistory = true;
        this.isLoadingHistory = false;
        this.loadedHistoryCount = 0;

        // 移动端:清除 hash 和恢复滚动
        if (this.isMobile()) {
            this.enableBodyScroll();
            // 清除 hash,但不添加历史记录
            if (window.location.hash === this.CHAT_HASH) {
                history.replaceState(null, '', window.location.pathname + window.location.search);
            }
        }

        // 显示触发按钮
        if (this.triggerButton) {
            this.triggerButton.style.display = 'flex';
        }
    }
}

// 导出单例
export const groupChat = new GroupChat();

评论加载中...