<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>在线设备与在线 IP</title>
    <style>
        :root {
            --bg: #f3f0e8;
            --card: rgba(255, 252, 246, 0.94);
            --line: #d8ccb6;
            --text: #2f261a;
            --muted: #786b58;
            --accent: #1f7a5a;
            --accent-soft: #d9efe5;
            --warning: #8f4c2d;
            --shadow: 0 18px 50px rgba(77, 56, 27, 0.12);
        }

        * {
            box-sizing: border-box;
        }

        body {
            margin: 0;
            min-height: 100vh;
            font-family: Georgia, "Times New Roman", serif;
            color: var(--text);
            background:
                radial-gradient(circle at top left, rgba(255, 255, 255, 0.75), transparent 34%),
                linear-gradient(135deg, #efe4d0 0%, #f9f5ee 45%, #e6dccb 100%);
        }

        .wrap {
            max-width: 1120px;
            margin: 0 auto;
            padding: 32px 20px 48px;
        }

        .hero {
            display: grid;
            gap: 18px;
            margin-bottom: 24px;
        }

        .eyebrow {
            letter-spacing: 0.12em;
            text-transform: uppercase;
            font-size: 12px;
            color: var(--muted);
        }

        h1 {
            margin: 0;
            font-size: clamp(30px, 5vw, 54px);
            line-height: 1;
        }

        .subtitle {
            max-width: 720px;
            font-size: 16px;
            line-height: 1.7;
            color: var(--muted);
        }

        .summary {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
            gap: 16px;
            margin-bottom: 24px;
        }

        .card {
            background: var(--card);
            border: 1px solid rgba(216, 204, 182, 0.8);
            border-radius: 24px;
            box-shadow: var(--shadow);
            backdrop-filter: blur(10px);
        }

        .stat {
            padding: 22px;
        }

        .stat-label {
            font-size: 13px;
            color: var(--muted);
            text-transform: uppercase;
            letter-spacing: 0.08em;
        }

        .stat-value {
            margin-top: 12px;
            font-size: 36px;
            font-weight: 700;
        }

        .stat-note {
            margin-top: 10px;
            font-size: 14px;
            color: var(--muted);
        }

        .grid {
            display: grid;
            grid-template-columns: 1.2fr 0.8fr;
            gap: 18px;
        }

        .panel {
            padding: 22px;
        }

        .panel h2 {
            margin: 0 0 16px;
            font-size: 24px;
        }

        .panel-head {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 12px;
            margin-bottom: 16px;
        }

        .badge {
            padding: 8px 12px;
            border-radius: 999px;
            background: var(--accent-soft);
            color: var(--accent);
            font-size: 13px;
            white-space: nowrap;
        }

        .device-list,
        .session-list {
            display: grid;
            gap: 12px;
        }

        .row {
            padding: 16px;
            border-radius: 18px;
            background: rgba(255, 255, 255, 0.65);
            border: 1px solid rgba(216, 204, 182, 0.7);
        }

        .row-top {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 10px;
        }

        .row-title {
            font-size: 17px;
            font-weight: 700;
        }

        .row-meta {
            margin-top: 8px;
            color: var(--muted);
            font-size: 14px;
            line-height: 1.6;
            word-break: break-all;
        }

        .empty {
            padding: 28px 20px;
            border: 1px dashed var(--line);
            border-radius: 18px;
            color: var(--muted);
            text-align: center;
            background: rgba(255, 255, 255, 0.48);
        }

        .footer-note {
            margin-top: 18px;
            color: var(--warning);
            font-size: 14px;
            line-height: 1.7;
        }

        @media (max-width: 860px) {
            .grid {
                grid-template-columns: 1fr;
            }
        }
    </style>
</head>

<body>
    <div class="wrap">
        <section class="hero">
            <div class="eyebrow">Xboard Plugin Dashboard</div>
            <h1>在线设备与在线 IP</h1>
            <div class="subtitle">
                当前页面由 User Online Devices 插件生成，会自动刷新并显示该账号最近上报到 Xboard 的在线 IP 列表。
            </div>
        </section>

        <section class="summary">
            <article class="card stat">
                <div class="stat-label">账号</div>
                <div class="stat-value" id="user-email">{{ $payload['user']['email'] }}</div>
                <div class="stat-note">用户 ID: <span id="user-id">{{ $payload['user']['id'] }}</span></div>
            </article>
            <article class="card stat">
                <div class="stat-label">在线设备数</div>
                <div class="stat-value" id="online-count">{{ $payload['user']['online_count'] }}</div>
                <div class="stat-note">按实时在线 IP 去重统计</div>
            </article>
            <article class="card stat">
                <div class="stat-label">最后活跃</div>
                <div class="stat-value" id="last-online">{{ $payload['user']['last_online_at'] ? date('Y-m-d H:i:s', $payload['user']['last_online_at']) : '暂无记录' }}</div>
                <div class="stat-note">数据来源于 Xboard 设备状态服务</div>
            </article>
        </section>

        <section class="grid">
            <article class="card panel">
                <div class="panel-head">
                    <h2>在线 IP 列表</h2>
                    <div class="badge">每 {{ $refreshInterval }} 秒刷新</div>
                </div>
                <div class="device-list" id="device-list"></div>
                <div class="footer-note">
                    说明：这里展示的是节点最近上报的在线 IP，Xboard 本体按 IP 去重，所以“在线设备”本质上是“当前唯一在线 IP 数”。
                </div>
            </article>

            <article class="card panel">
                <div class="panel-head">
                    <h2>登录会话</h2>
                    <div class="badge" id="session-badge">{{ $payload['meta']['show_active_sessions'] ? '已开启' : '已关闭' }}</div>
                </div>
                <div class="session-list" id="session-list"></div>
            </article>
        </section>
    </div>

    <script>
        const snapshotUrl = @json($snapshotUrl);
        const refreshInterval = {{ (int) $refreshInterval }};
        const initialPayload = @json($payload);

        function formatTime(timestamp) {
            if (!timestamp) return '暂无记录';
            const date = new Date(timestamp * 1000);
            const pad = (value) => String(value).padStart(2, '0');
            return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
        }

        function createEmpty(message) {
            const div = document.createElement('div');
            div.className = 'empty';
            div.textContent = message;
            return div;
        }

        function renderDevices(devices) {
            const root = document.getElementById('device-list');
            root.innerHTML = '';

            if (!devices.length) {
                root.appendChild(createEmpty('当前没有检测到在线设备。'));
                return;
            }

            devices.forEach((device) => {
                const row = document.createElement('div');
                row.className = 'row';
                row.innerHTML = `
                    <div class="row-top">
                        <div class="row-title">${device.name}</div>
                        <div class="badge">在线</div>
                    </div>
                    <div class="row-meta">IP: ${device.ip}</div>
                `;
                root.appendChild(row);
            });
        }

        function renderSessions(sessions, enabled) {
            const root = document.getElementById('session-list');
            root.innerHTML = '';

            if (!enabled) {
                root.appendChild(createEmpty('管理员已关闭登录会话展示。'));
                return;
            }

            if (!sessions.length) {
                root.appendChild(createEmpty('当前没有可展示的登录会话。'));
                return;
            }

            sessions.forEach((session) => {
                const row = document.createElement('div');
                row.className = 'row';
                row.innerHTML = `
                    <div class="row-top">
                        <div class="row-title">${session.device}</div>
                        <div class="badge">#${session.id}</div>
                    </div>
                    <div class="row-meta">
                        最近使用: ${formatTime(session.last_used_at)}<br>
                        创建时间: ${formatTime(session.created_at)}<br>
                        过期时间: ${formatTime(session.expires_at)}
                    </div>
                `;
                root.appendChild(row);
            });
        }

        function render(payload) {
            document.getElementById('user-email').textContent = payload.user.email;
            document.getElementById('user-id').textContent = payload.user.id;
            document.getElementById('online-count').textContent = payload.user.online_count;
            document.getElementById('last-online').textContent = formatTime(payload.user.last_online_at);
            document.getElementById('session-badge').textContent = payload.meta.show_active_sessions ? '已开启' : '已关闭';
            renderDevices(payload.online_devices || []);
            renderSessions(payload.active_sessions || [], payload.meta.show_active_sessions);
        }

        async function refresh() {
            try {
                const response = await fetch(snapshotUrl, {
                    method: 'GET',
                    credentials: 'same-origin',
                    headers: {
                        'Accept': 'application/json'
                    }
                });
                if (!response.ok) return;
                const result = await response.json();
                if (result && result.data) {
                    render(result.data);
                }
            } catch (error) {
                console.error('Failed to refresh online devices snapshot.', error);
            }
        }

        render(initialPayload);
        window.setInterval(refresh, refreshInterval * 1000);
    </script>
</body>

</html>
