<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>服务日志</title>
    <style>
        * { box-sizing: border-box; margin: 0; padding: 0; }
        html, body { height: 100%; overflow: hidden; }
        body { font-family: -apple-system, BlinkMacSystemFont, sans-serif; background: #1e1e1e; color: #ccc; }
        
        #app { display: flex; flex-direction: column; height: 100vh; }
        .toolbar {
            flex-shrink: 0;
            display: flex; align-items: center; gap: 8px; padding: 8px 12px;
            background: #2d2d2d; border-bottom: 1px solid #404040;
            flex-wrap: wrap;
        }
        .service-name { color: #58a6ff; font-weight: 500; margin-right: 8px; }
        .scope-badge { font-size: 11px; padding: 2px 6px; border-radius: 4px; background: #3c3c3c; color: #888; margin-right: 8px; }
        select, input, button {
            padding: 5px 10px; border-radius: 4px; border: 1px solid #404040;
            background: #3c3c3c; color: #ccc; font-size: 12px;
        }
        input[type="text"] { flex: 0 0 80px; min-width: 80px; }
        button { cursor: pointer; background: #0e639c; color: #fff; border: none; }
        button:hover { background: #1177bb; }
        button.active { background: #1e7f1e; }
        
        .logs { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 0; font-family: 'Consolas', monospace; font-size: 12px; }
        .log-item { display: flex; align-items: flex-start; padding: 2px 8px; border-bottom: 1px solid #2d2d2d; min-height: 20px; }
        .log-item:hover { background: #2d2d2d; }
        .log-err { color: #f14c4c; }
        .log-warn { color: #e3b341; }
        .log-info { color: #58a6ff; }
        .log-debug { color: #8b949e; }
        .log-time { color: #666; margin-right: 8px; white-space: nowrap; flex-shrink: 0; font-size: 11px; }
        .log-msg { word-break: break-all; white-space: pre-wrap; }
        
        .status { padding: 6px 16px; background: #007acc; color: #fff; font-size: 12px; display: flex; justify-content: space-between; }
        .status.error { background: #c72e0f; }
        .status.success { background: #1e7f1e; }
    </style>
</head>
<body>
    <div id="app">
        <div class="toolbar">
            <span class="service-name" id="serviceDisplay"></span>
            <span class="scope-badge" id="scopeBadge"></span>
            <input type="text" id="keyword" placeholder="搜索...">
            <button onclick="loadLogs()">刷新</button>
            <button onclick="toggleTail()" id="tailBtn" class="active">实时</button>
        </div>
        <div id="logs" class="logs"></div>
        <div id="status" class="status" style="display:none;"></div>
    </div>

    <script>
    let tailing = true;
    let tailInterval;
    
    // 从 URL 获取服务名称
    function getServiceFromUrl() {
        const params = new URLSearchParams(window.location.search);
        return params.get('service') || '';
    }
    
    // 从 URL 获取 scope
    function getScopeFromUrl() {
        const params = new URLSearchParams(window.location.search);
        return params.get('scope') || 'user';
    }
    
    // 去掉 .service 后缀
    function formatServiceName(name) {
        return name.replace(/\.service$/, '');
    }
    
    function showStatus(msg, type) {
        const el = document.getElementById('status');
        el.textContent = msg;
        el.className = 'status ' + (type || '');
        el.style.display = 'flex';
    }
    
    function getLevelClass(level) {
        if (level.includes('ERR') || level.includes('ERROR')) return 'log-err';
        if (level.includes('WARN')) return 'log-warn';
        if (level.includes('DEBUG')) return 'log-debug';
        return 'log-info';
    }
    
    function renderLogs(logs) {
        const container = document.getElementById('logs');
        // 检查是否在底部附近（在50px以内视为在底部）
        const isAtBottom = container.scrollHeight - container.scrollTop - container.clientHeight < 50;
        
        container.innerHTML = logs.map(log => {
            const raw = log.raw || log.message || '';
            const timeMatch = raw.match(/^(\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2})/);
            const time = timeMatch ? timeMatch[1] : '';
            let msg = raw;
            msg = msg.replace(/^\d+\s+\w+\s+\d+:\d{2}:\d+\s+\S+\s+\w+\[\d+\]:\s*/, '');
            msg = msg.replace(/^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}[.\d+Z+]?\s*/i, '');
            msg = msg.replace(/^\[[^\]]+\]\s*/i, '');
            msg = msg.replace(/^\w+\s*:/, '');
            return `<div class="log-item ${getLevelClass(log.priority || '')}">
                <span class="log-time">${time}</span>
                <span class="log-msg">${msg.replace(/</g, '&lt;')}</span>
            </div>`;
        }).join('');
        
        // 仅当之前在底部时才滚动到底部
        if (isAtBottom) {
            container.scrollTop = container.scrollHeight;
        }
    }
    
    async function loadLogs() {
        const service = getServiceFromUrl();
        const scope = getScopeFromUrl();
        const keyword = document.getElementById('keyword').value;
        
        try {
            const params = new URLSearchParams({service, scope, keyword, lines: '200'});
            const r = await fetch('/api/log/journal?' + params);
            const data = await r.json();
            
            if (data.success) {
                renderLogs((data.data && data.data.logs) || []);
                showStatus(`已加载 ${(data.data && data.data.logs)?.length || 0} 条日志 (${scope})`, 'success');
            } else {
                showStatus(data.error || '加载失败', 'error');
            }
        } catch (e) {
            showStatus(e.message, 'error');
        }
    }
    
    function toggleTail() {
        tailing = !tailing;
        const btn = document.getElementById('tailBtn');
        btn.classList.toggle('active', tailing);
        btn.textContent = tailing ? '实时' : '暂停';
        
        if (tailing) {
            showStatus('实时模式已开启', 'success');
            tailInterval = setInterval(loadLogs, 3000);
        } else {
            showStatus('', '');
            clearInterval(tailInterval);
        }
    }
    
    // 初始化
    const service = getServiceFromUrl();
    const scope = getScopeFromUrl();
    if (service) {
        document.getElementById('serviceDisplay').textContent = formatServiceName(service);
        document.getElementById('scopeBadge').textContent = scope === 'user' ? 'User' : 'System';
        document.title = formatServiceName(service) + ' - 日志';
    }
    
    document.getElementById('keyword').addEventListener('keyup', e => e.key === 'Enter' && loadLogs());
    
    // 默认开启实时模式
    tailInterval = setInterval(loadLogs, 3000);
    loadLogs();
    </script>
</body>
</html>
