<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web Terminal 管理系统</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.5/xterm.min.css" />
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
            color: #fff;
        }

        .container {
            max-width: 1400px;
            margin: 0 auto;
            background: white;
            border-radius: 15px;
            box-shadow: 0 20px 40px rgba(0,0,0,0.1);
            overflow: hidden;
            display: flex;
            flex-direction: column;
            height: calc(100vh - 40px);
        }

        .header {
            background: #2c3e50;
            color: white;
            padding: 20px 30px;
            text-align: center;
        }

        .header h1 {
            margin-bottom: 10px;
            font-size: 2.2em;
        }

        .header p {
            opacity: 0.9;
            font-size: 1.1em;
        }

        .main-content {
            display: flex;
            flex: 1;
            overflow: hidden;
        }

        .clients-panel {
            background: #34495e;
            color: white;
            padding: 20px;
            width: 300px;
            display: flex;
            flex-direction: column;
            overflow: hidden;
        }

        .terminal-panel {
            background: #1a1a1a;
            padding: 20px;
            display: flex;
            flex-direction: column;
            flex: 1;
            overflow: hidden;
        }

        .panel-title {
            font-size: 1.2em;
            margin-bottom: 15px;
            padding-bottom: 10px;
            border-bottom: 2px solid #3498db;
            display: flex;
            align-items: center;
        }

        .clients-container {
            flex: 1;
        }

        .client-list {
            list-style: none;
        }

        .client-item {
            padding: 12px 15px;
            margin: 8px 0;
            background: rgba(255,255,255,0.1);
            border-radius: 8px;
            cursor: pointer;
            transition: all 0.3s ease;
            border-left: 4px solid #3498db;
        }

        .client-item:hover {
            background: rgba(255,255,255,0.2);
            transform: translateX(5px);
        }

        .client-item.active {
            background: #3498db;
            border-left-color: #2980b9;
        }

        .client-name {
            font-weight: bold;
            margin-bottom: 5px;
            display: flex;
            align-items: center;
        }

        .client-status {
            display: inline-block;
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background: #2ecc71;
            margin-right: 8px;
        }

        .client-info {
            font-size: 0.8em;
            opacity: 0.8;
            margin-bottom: 2px;
        }

        .terminal-container {
            flex: 1;
            background: #000;
            border-radius: 8px;
            overflow: hidden;
            position: relative;
            border: 1px solid #333;
        }

        #terminal {
            height: 100%;
            width: 100%;
            padding: 10px;
        }

        .terminal-controls {
            margin-top: 15px;
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
        }

        .btn {
            background: #3498db;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 5px;
            cursor: pointer;
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            gap: 5px;
            font-size: 0.9em;
        }

        .btn:hover {
            background: #2980b9;
            transform: translateY(-2px);
        }

        .btn:disabled {
            background: #7f8c8d;
            cursor: not-allowed;
            transform: none;
        }

        .btn-success {
            background: #27ae60;
        }

        .btn-success:hover {
            background: #219653;
        }

        .btn-warning {
            background: #e67e22;
        }

        .btn-warning:hover {
            background: #d35400;
        }

        .btn-danger {
            background: #e74c3c;
        }

        .btn-danger:hover {
            background: #c0392b;
        }

        .status-bar {
            background: #2c3e50;
            color: white;
            padding: 10px 20px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            font-size: 0.9em;
        }

        .connection-status {
            display: flex;
            align-items: center;
        }

        .status-indicator {
            width: 10px;
            height: 10px;
            border-radius: 50%;
            margin-right: 8px;
            transition: background 0.3s ease;
        }

        .connected {
            background: #2ecc71;
            box-shadow: 0 0 8px #2ecc71;
        }

        .disconnected {
            background: #e74c3c;
        }

        .waiting {
            background: #f39c12;
            animation: pulse 1.5s infinite;
        }

        @keyframes pulse {
            0% { opacity: 1; }
            50% { opacity: 0.5; }
            100% { opacity: 1; }
        }

        .empty-state {
            padding: 30px 20px;
            text-align: center;
            opacity: 0.7;
        }

        .terminal-status {
            padding: 8px 12px;
            background: rgba(255,255,255,0.1);
            border-radius: 4px;
            font-size: 0.9em;
            margin-top: 10px;
        }

        .client-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
        }

        .refresh-btn {
            background: transparent;
            border: 1px solid rgba(255,255,255,0.3);
            color: white;
            padding: 5px 10px;
            border-radius: 4px;
            cursor: pointer;
            transition: all 0.3s ease;
        }

        .refresh-btn:hover {
            background: rgba(255,255,255,0.1);
        }
    </style>
</head>
<body>
<div class="container">
    <div class="header">
        <h1>🚀 Web Terminal 管理系统</h1>
        <p>实时客户端管理与终端控制</p>
    </div>

    <div class="main-content">
        <!-- 客户端列表面板 -->
        <div class="clients-panel">
            <div class="client-header">
                <div class="panel-title">📡 已连接客户端</div>
                <button class="refresh-btn" id="refreshBtn" title="刷新客户端列表">⟳</button>
            </div>

            <div class="clients-container">
                <ul class="client-list" id="clientList">
                    <!-- 客户端列表将通过JavaScript动态填充 -->
                </ul>
            </div>

            <div class="terminal-status" id="terminalStatus">
                请选择一个客户端开始终端会话
            </div>
        </div>

        <!-- 终端面板 -->
        <div class="terminal-panel">
            <div class="panel-title">💻 终端控制台</div>
            <div class="terminal-container">
                <div id="terminal"></div>
            </div>
            <div class="terminal-controls">
                <button class="btn" id="connectBtn" disabled>
                    <span>🔗</span> 连接终端
                </button>
                <button class="btn btn-warning" id="disconnectBtn" disabled>
                    <span>🔌</span> 断开连接
                </button>
                <button class="btn" id="clearBtn">
                    <span>🧹</span> 清屏
                </button>
                <button class="btn" id="resizeBtn">
                    <span>📐</span> 调整终端大小
                </button>
                <button class="btn btn-danger" id="resetBtn">
                    <span>🔄</span> 重置终端
                </button>
            </div>
        </div>
    </div>

    <div class="status-bar">
        <div class="connection-status">
            <div class="status-indicator disconnected" id="statusIndicator"></div>
            <span id="statusText">未连接服务器</span>
        </div>
        <div id="clientCount">客户端: 0</div>
    </div>
</div>

<!-- 引入必要的JavaScript库 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.5/xterm.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.5/addons/fit/fit.min.js"></script>

<script>
    class TerminalManager {
        constructor() {
            this.socket = null;
            this.terminal = null;
            this.currentClient = null;
            this.isConnected = false;
            this.terminalConnected = false;
            this.autoRefresh = true;

            // 初始化顺序很重要
            this.initializeSocket();
            this.initializeTerminal();
            this.setupEventListeners();

            // 自动刷新客户端列表
            this.refreshInterval = setInterval(() => {
                if (this.autoRefresh && this.isConnected) {
                    this.loadClients();
                }
            }, 3000);
        }

        initializeTerminal() {
            try {
                // 初始化xterm.js终端
                this.terminal = new Terminal({
                    cursorBlink: true,
                    convertEol: true,  // 启用 EOL 转换
                    fontSize: 14,
                    fontFamily: "'Courier New', monospace",
                    theme: {
                        background: '#1a1a1a',
                        foreground: '#ffffff',
                        cursor: '#ffffff',
                        selection: '#555555'
                    }
                });

                this.terminal.open(document.getElementById('terminal'));

                // 修复：检查 fit 插件是否可用
                if (typeof Terminal.fit === 'function') {
                    Terminal.fit(this.terminal);
                } else {
                    console.warn('Terminal.fit 插件不可用，使用备用调整大小方法');
                    this.fitTerminalManual();
                }

                // 显示欢迎信息
                this.terminal.writeln('\x1b[1;36m欢迎使用 Web Terminal 管理系统\x1b[0m');
                this.terminal.writeln('\x1b[33m请从左侧选择一个客户端开始终端会话\x1b[0m');
                this.terminal.writeln('');

                // 处理终端输入
                this.terminal.onData(data => {
                    if (this.currentClientOS === 'nt') {
                        this.terminal.write(data);
                    }
                    if (this.currentClient && this.terminalConnected) {
                        this.socket.emit('terminal_input', {
                            client_id: this.currentClient,
                            data: data
                        });
                    }
                });
            } catch (error) {
                console.error('初始化终端时出错:', error);
                // 备用方案：创建简单的终端显示
                this.createFallbackTerminal();
            }
        }

        fitTerminalManual() {
            // 手动调整终端大小
            try {
                const terminalElement = document.getElementById('terminal');
                const cols = Math.floor(terminalElement.clientWidth / 9);
                const rows = Math.floor(terminalElement.clientHeight / 17);

                if (cols > 0 && rows > 0) {
                    this.terminal.resize(cols, rows);
                }
            } catch (error) {
                console.warn('手动调整终端大小失败:', error);
            }
        }

        createFallbackTerminal() {
            // 创建备用的简单终端显示
            const terminalElement = document.getElementById('terminal');
            terminalElement.innerHTML = `
                    <div style="color: white; padding: 20px;">
                        <h3>终端初始化失败</h3>
                        <p>错误信息: 无法加载 xterm.js 终端</p>
                        <p>请检查网络连接或刷新页面重试</p>
                    </div>
                `;
        }

        initializeSocket() {
            try {
                // 连接Socket.IO服务器
                this.socket = io();

                this.socket.on('connect', () => {
                    console.log("Connected to server");
                    this.updateStatus(true, '已连接服务器');
                    this.socket.emit('frontend_connect');
                    this.loadClients();
                });

                this.socket.on('disconnect', () => {
                    console.log("Disconnected from server");
                    this.updateStatus(false, '未连接服务器');
                    this.terminalConnected = false;
                    this.updateTerminalStatus('与服务器断开连接', 'error');
                });

                this.socket.on('connect_error', (error) => {
                    console.error("Connection error:", error);
                    this.updateStatus(false, '连接服务器失败');
                });

                this.socket.on('clients_updated', () => {
                    console.log("Clients list updated");
                    if (this.autoRefresh) {
                        this.loadClients();
                    }
                });

                this.socket.on('terminal_output', (data) => {
                    if (this.terminal && data.client_id === this.currentClient) {
                        this.terminal.write(data.data);
                    }
                });

                this.socket.on('terminal_started', (data) => {
                    if (data.client_id === this.currentClient) {
                        this.terminalConnected = true;
                        this.terminal.write('\r\n\x1b[1;32m✓ 终端会话已建立\x1b[0m\r\n');
                        this.updateConnectButton(true);
                        this.updateTerminalStatus('终端会话已建立', 'success');

                        // 连接成功后自动发送回车命令刷新提示符
                        setTimeout(() => {
                            console.log("终端连接成功，发送回车命令");
                            if (this.currentClient && this.terminalConnected) {
                                console.log("自动刷新终端显示");
                                // 发送回车命令获取最新提示符
                                this.socket.emit('terminal_input', {
                                    client_id: this.currentClient,
                                    data: '\r'
                                });
                            }
                        }, 200);
                    }
                });

                this.socket.on('terminal_status', (data) => {
                    if (data.client_id === this.currentClient) {
                        if (data.status === 'waiting') {
                            this.terminal.write(`\r\n\x1b[33m⏳ ${data.message}\x1b[0m\r\n`);
                            this.updateConnectButton(false);
                            this.updateTerminalStatus('等待客户端连接...', 'waiting');
                        } else if (data.status === 'connected') {
                            this.terminalConnected = true;
                            this.terminal.write(`\r\n\x1b[32m✓ ${data.message}\x1b[0m\r\n`);
                            this.updateConnectButton(true);
                            this.updateTerminalStatus('终端连接已建立', 'success');
                        }
                    }
                });

                this.socket.on('terminal_error', (data) => {
                    this.terminal.write(`\r\n\x1b[1;31m✗ 错误: ${data.error}\x1b[0m\r\n`);
                    this.terminalConnected = false;
                    this.updateConnectButton(false);
                    this.updateTerminalStatus(`错误: ${data.error}`, 'error');
                });
            } catch (error) {
                console.error('初始化Socket.IO时出错:', error);
                this.updateStatus(false, '连接初始化失败');
            }
        }

        setupEventListeners() {
            document.getElementById('connectBtn').addEventListener('click', () => {
                this.connectToTerminal();
            });

            document.getElementById('disconnectBtn').addEventListener('click', () => {
                this.disconnectTerminal();
            });

            document.getElementById('clearBtn').addEventListener('click', () => {
                if (this.terminal && this.terminal.clear) {
                    this.terminal.clear();
                    this.terminal.write('\x1b[1;36m终端已清空\x1b[0m\r\n');
                }
            });

            document.getElementById('resizeBtn').addEventListener('click', () => {
                this.resizeTerminal();
            });

            document.getElementById('resetBtn').addEventListener('click', () => {
                this.resetTerminal();
            });

            document.getElementById('refreshBtn').addEventListener('click', () => {
                this.loadClients();
                if (this.terminal && this.terminal.write) {
                    this.terminal.write('\x1b[33m客户端列表已刷新\x1b[0m\r\n');
                }
            });

            window.addEventListener('resize', () => {
                this.resizeTerminal();
            });
        }

        resizeTerminal() {
            // 安全的调整终端大小方法
            try {
                if (typeof Terminal.fit === 'function') {
                    Terminal.fit(this.terminal);
                } else {
                    this.fitTerminalManual();
                }
                if (this.terminal && this.terminal.write) {
                    this.terminal.write('\x1b[33m终端大小已调整\x1b[0m\r\n');
                }
            } catch (error) {
                console.warn('调整终端大小时出错:', error);
            }
        }

        async loadClients() {
            try {
                const response = await fetch('/clients');
                if (!response.ok) {
                    throw new Error(`HTTP error! status: ${response.status}`);
                }
                const clients = await response.json();

                const clientList = document.getElementById('clientList');
                clientList.innerHTML = '';

                if (clients.length === 0) {
                    clientList.innerHTML = `
                            <div class="empty-state">
                                <div>📭</div>
                                <div>暂无客户端连接</div>
                            </div>
                        `;
                } else {
                    clients.forEach(client => {
                        const li = document.createElement('li');
                        li.className = 'client-item';
                        if (this.currentClient === client.id) {
                            li.classList.add('active');
                        }
                        li.innerHTML = `
                                <div class="client-name">
                                    <span class="client-status"></span>
                                    [${client.os}] ${client.name}
                                </div>
                                <div class="client-info">ID: ${client.id.substring(0, 8)}...</div>
                                <div class="client-info">连接时间: ${new Date(client.connected_at).toLocaleTimeString()}</div>
                            `;

                        li.addEventListener('click', () => {
                            this.selectClient(client, li);
                        });

                        clientList.appendChild(li);
                    });
                }

                document.getElementById('clientCount').textContent = `客户端: ${clients.length}`;
            } catch (error) {
                console.error('加载客户端列表失败:', error);
                const clientList = document.getElementById('clientList');
                clientList.innerHTML = `
                        <div class="empty-state">
                            <div>❌</div>
                            <div>加载客户端列表失败</div>
                        </div>
                    `;
            }
        }

        selectClient(client, element) {
            // 移除其他活跃状态
            document.querySelectorAll('.client-item').forEach(item => {
                item.classList.remove('active');
            });

            // 添加当前活跃状态
            element.classList.add('active');

            this.currentClient = client.id;
            this.currentClientOS = client.os;

            // 启用连接按钮
            document.getElementById('connectBtn').disabled = false;
            document.getElementById('disconnectBtn').disabled = false;

            // 更新终端状态
            this.updateTerminalStatus(`已选择客户端: ${client.name}`, 'info');

            // 显示选中信息
            if (this.terminal && this.terminal.write) {
                this.terminal.write(`\r\n\x1b[1;36m已选择客户端: ${client.name}\x1b[0m\r\n`);
                this.terminal.write(`\x1b[90m客户端ID: ${client.id}\x1b[0m\r\n`);
                this.terminal.write(`\x1b[90m连接时间: ${new Date(client.connected_at).toLocaleString()}\x1b[0m\r\n`);
                this.terminal.write('\x1b[33m点击"连接终端"按钮开始会话\x1b[0m\r\n');
            }
        }

        connectToTerminal() {
            if (!this.currentClient) {
                this.updateTerminalStatus('错误: 请先选择一个客户端', 'error');
                return;
            }

            if (this.terminal && this.terminal.clear) {
                this.terminal.clear();
                this.terminal.write('\x1b[1;33m正在启动终端会话...\x1b[0m\r\n');
            }

            this.socket.emit('start_terminal', {
                client_id: this.currentClient
            });

            this.updateTerminalStatus('正在连接终端...', 'waiting');
        }

        disconnectTerminal() {
            if (this.currentClient) {
                if (this.terminal && this.terminal.write) {
                    this.terminal.write('\r\n\x1b[33m终端会话已断开\x1b[0m\r\n');
                }
                this.terminalConnected = false;
                this.updateConnectButton(false);
                this.updateTerminalStatus('终端会话已断开', 'info');

                // 移除活跃状态但保持选中
                document.querySelectorAll('.client-item').forEach(item => {
                    if (item.classList.contains('active')) {
                        item.classList.remove('active');
                    }
                });
            }
        }

        resetTerminal() {
            if (this.terminal && this.terminal.reset) {
                this.terminal.reset();
                this.terminal.write('\x1b[1;36m终端已重置\x1b[0m\r\n');
                this.updateTerminalStatus('终端已重置', 'info');
            }
        }

        updateConnectButton(connected) {
            const connectBtn = document.getElementById('connectBtn');
            if (connected) {
                connectBtn.innerHTML = '<span>🔗</span> 已连接';
                connectBtn.disabled = true;
                connectBtn.classList.add('btn-success');
            } else {
                connectBtn.innerHTML = '<span>🔗</span> 连接终端';
                connectBtn.disabled = false;
                connectBtn.classList.remove('btn-success');
            }
        }

        updateStatus(connected, message) {
            this.isConnected = connected;
            const indicator = document.getElementById('statusIndicator');
            const statusText = document.getElementById('statusText');

            indicator.className = 'status-indicator';
            if (connected) {
                indicator.classList.add('connected');
            } else {
                indicator.classList.add('disconnected');
            }

            statusText.textContent = message;
        }

        updateTerminalStatus(message, type) {
            const statusElement = document.getElementById('terminalStatus');
            statusElement.textContent = message;

            // 移除之前的类
            statusElement.classList.remove('info', 'success', 'error', 'waiting');

            // 添加新类
            if (type === 'success') {
                statusElement.style.color = '#2ecc71';
            } else if (type === 'error') {
                statusElement.style.color = '#e74c3c';
            } else if (type === 'waiting') {
                statusElement.style.color = '#f39c12';
            } else {
                statusElement.style.color = 'white';
            }
        }

        destroy() {
            if (this.refreshInterval) {
                clearInterval(this.refreshInterval);
            }
            if (this.socket) {
                this.socket.disconnect();
            }
            if (this.terminal) {
                this.terminal.dispose();
            }
        }
    }

    // 页面加载完成后初始化
    document.addEventListener('DOMContentLoaded', () => {
        // 添加错误处理
        window.addEventListener('error', (event) => {
            console.error('全局错误:', event.error);
        });

        try {
            const terminalManager = new TerminalManager();
            window.terminalManager = terminalManager;

            // 在页面关闭前清理资源
            window.addEventListener('beforeunload', () => {
                if (terminalManager) {
                    terminalManager.destroy();
                }
            });
        } catch (error) {
            console.error('初始化 TerminalManager 时出错:', error);
            // 显示错误信息
            document.getElementById('terminalStatus').textContent = '系统初始化失败，请刷新页面';
            document.getElementById('statusText').textContent = '初始化错误';
        }
    });
</script>
</body>
</html>