<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>RouteWatch Status</title>
    <style>
        * {
            box-sizing: border-box;
        }
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            margin: 0;
            padding: 0;
            background: #f5f5f5;
        }

        /* Navbar styles */
        .navbar {
            background: #2c3e50;
            padding: 0 20px;
            display: flex;
            align-items: center;
            justify-content: space-between;
            height: 56px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .navbar-brand {
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 18px;
            font-weight: 600;
        }
        .navbar-brand a {
            color: white;
            text-decoration: none;
        }
        .navbar-brand a:hover {
            color: #ecf0f1;
        }
        .navbar-brand .by {
            font-weight: normal;
            color: #95a5a6;
            font-size: 14px;
        }
        .navbar-brand .author {
            color: #3498db;
            font-weight: normal;
        }
        .navbar-brand .author:hover {
            text-decoration: underline;
        }
        .navbar-links {
            display: flex;
            gap: 20px;
        }
        .navbar-links a {
            color: #ecf0f1;
            text-decoration: none;
            font-size: 14px;
            padding: 8px 12px;
            border-radius: 4px;
            transition: background-color 0.2s;
        }
        .navbar-links a:hover {
            background: rgba(255,255,255,0.1);
        }
        .navbar-links a.active {
            background: rgba(255,255,255,0.15);
        }

        /* Main content */
        .main-content {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }
        h1 {
            color: #333;
            margin-bottom: 30px;
        }
        .status-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
            gap: 20px;
            margin-bottom: 30px;
        }
        .status-card {
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .status-card h2 {
            margin: 0 0 15px 0;
            font-size: 18px;
            color: #666;
        }
        .metric {
            display: flex;
            justify-content: space-between;
            padding: 8px 0;
            border-bottom: 1px solid #eee;
        }
        .metric:last-child {
            border-bottom: none;
        }
        .metric-label {
            color: #666;
        }
        .metric-value {
            font-family: 'SF Mono', Monaco, 'Cascadia Mono', 'Roboto Mono', Consolas, 'Courier New', monospace;
            color: #333;
        }
        .metric-value.metric-link {
            text-decoration: underline;
            text-decoration-style: dashed;
            text-underline-offset: 2px;
            cursor: pointer;
        }
        .metric-value.metric-link:hover {
            color: #0066cc;
            text-decoration-style: solid;
        }
        .connected {
            color: #22c55e;
        }
        .disconnected {
            color: #ef4444;
        }
        .error {
            background: #fee;
            color: #c00;
            padding: 10px;
            border-radius: 4px;
            margin-top: 20px;
        }
        .footer {
            margin-top: 40px;
            padding: 20px;
            background: white;
            border-radius: 8px;
            box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
            text-align: center;
            color: #666;
            font-size: 14px;
        }
        .footer a {
            color: #0066cc;
            text-decoration: none;
        }
        .footer a:hover {
            text-decoration: underline;
        }
        .footer .separator {
            margin: 0 10px;
            color: #ccc;
        }
    </style>
</head>
<body>
    <nav class="navbar">
        <div class="navbar-brand">
            <a href="/">routewatch</a>
            <span class="by">by</span>
            <a href="https://sneak.berlin" class="author">@sneak</a>
        </div>
        <div class="navbar-links">
            <a href="/">Home</a>
            <a href="/status" class="active">Status</a>
        </div>
    </nav>

    <main class="main-content">
    <div id="error" class="error" style="display: none;"></div>
    <div class="status-grid">
        <div class="status-card">
            <h2>RouteWatch</h2>
            <div class="metric">
                <span class="metric-label">Status</span>
                <span class="metric-value" id="connected">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Uptime</span>
                <span class="metric-value" id="uptime">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Go Version</span>
                <span class="metric-value" id="go_version">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Goroutines</span>
                <span class="metric-value" id="goroutines">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Memory Usage</span>
                <span class="metric-value" id="memory_usage">-</span>
            </div>
        </div>
        
        <div class="status-card">
            <h2>Stream Statistics</h2>
            <div class="metric">
                <span class="metric-label">Connection Duration</span>
                <span class="metric-value" id="connection_duration">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Reconnections</span>
                <span class="metric-value" id="reconnect_count">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">BGP Peers</span>
                <span class="metric-value" id="bgp_peer_count">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Total Messages</span>
                <span class="metric-value" id="total_messages">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Messages/sec</span>
                <span class="metric-value" id="messages_per_sec">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Announcements</span>
                <span class="metric-value" id="announcements">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Withdrawals</span>
                <span class="metric-value" id="withdrawals">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Route Churn/sec</span>
                <span class="metric-value" id="route_churn_per_sec">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Total Data</span>
                <span class="metric-value" id="total_wire_bytes">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Throughput</span>
                <span class="metric-value" id="wire_mbits_per_sec">-</span>
            </div>
        </div>

        <div class="status-card">
            <h2>GC Statistics</h2>
            <div class="metric">
                <span class="metric-label">GC Runs</span>
                <span class="metric-value" id="gc_num">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Total Pause</span>
                <span class="metric-value" id="gc_total_pause">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Last Pause</span>
                <span class="metric-value" id="gc_last_pause">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Heap Alloc</span>
                <span class="metric-value" id="gc_heap_alloc">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Heap Sys</span>
                <span class="metric-value" id="gc_heap_sys">-</span>
            </div>
        </div>
        
        <div class="status-card">
            <h2>Database Statistics</h2>
            <div class="metric">
                <span class="metric-label">ASNs</span>
                <span class="metric-value" id="asns">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Total Prefixes</span>
                <span class="metric-value" id="prefixes">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Peerings</span>
                <span class="metric-value" id="peerings">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Peers</span>
                <span class="metric-value" id="peers">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Database Size</span>
                <span class="metric-value" id="database_size">-</span>
            </div>
        </div>
        
        <div class="status-card">
            <h2>Routing Table</h2>
            <div class="metric">
                <span class="metric-label">Live Routes</span>
                <span class="metric-value" id="live_routes">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">IPv4 Prefixes</span>
                <span class="metric-value" id="ipv4_prefixes">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">IPv6 Prefixes</span>
                <span class="metric-value" id="ipv6_prefixes">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">IPv4 Routes</span>
                <span class="metric-value" id="ipv4_routes">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">IPv6 Routes</span>
                <span class="metric-value" id="ipv6_routes">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">IPv4 Updates/sec</span>
                <span class="metric-value" id="ipv4_updates_per_sec">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">IPv6 Updates/sec</span>
                <span class="metric-value" id="ipv6_updates_per_sec">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Oldest Route</span>
                <span class="metric-value" id="oldest_route">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Newest Route</span>
                <span class="metric-value" id="newest_route">-</span>
            </div>
        </div>

        <div class="status-card">
            <h2>WHOIS Fetcher</h2>
            <div class="metric">
                <span class="metric-label">Fresh ASNs</span>
                <span class="metric-value" id="whois_fresh">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Stale ASNs</span>
                <span class="metric-value" id="whois_stale">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Never Fetched</span>
                <span class="metric-value" id="whois_never">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Fresh %</span>
                <span class="metric-value" id="whois_percent">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Successes (1h)</span>
                <span class="metric-value" id="whois_successes">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Errors (1h)</span>
                <span class="metric-value" id="whois_errors">-</span>
            </div>
            <div class="metric">
                <span class="metric-label">Current Interval</span>
                <span class="metric-value" id="whois_interval">-</span>
            </div>
        </div>
    </div>

    <div class="status-grid">
        <div class="status-card">
            <h2>IPv4 Prefix Distribution</h2>
            <div id="ipv4-prefix-distribution">
                <!-- Will be populated dynamically -->
            </div>
        </div>
        
        <div class="status-card">
            <h2>IPv6 Prefix Distribution</h2>
            <div id="ipv6-prefix-distribution">
                <!-- Will be populated dynamically -->
            </div>
        </div>
    </div>
    
    <div id="handler-stats-container" class="status-grid">
        <!-- Handler stats will be dynamically added here -->
    </div>
    
    <script>
        function formatBytes(bytes) {
            if (bytes === 0) return '0 B';
            const k = 1024;
            const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }
        
        function formatNumber(num) {
            return num.toLocaleString();
        }
        
        function formatProcessingTime(ms) {
            if (ms < 0.001) {
                return (ms * 1000).toFixed(0) + ' µs';
            } else if (ms < 0.01) {
                return (ms * 1000).toFixed(1) + ' µs';
            } else if (ms < 1) {
                return ms.toFixed(3) + ' ms';
            } else {
                return ms.toFixed(2) + ' ms';
            }
        }

        function formatRelativeTime(isoString) {
            if (!isoString) return '-';
            const date = new Date(isoString);
            const now = new Date();
            const diffMs = now - date;
            const diffSec = Math.floor(diffMs / 1000);
            const diffMin = Math.floor(diffSec / 60);
            const diffHour = Math.floor(diffMin / 60);
            const diffDay = Math.floor(diffHour / 24);

            if (diffSec < 60) return diffSec + 's ago';
            if (diffMin < 60) return diffMin + 'm ago';
            if (diffHour < 24) return diffHour + 'h ' + (diffMin % 60) + 'm ago';
            return diffDay + 'd ' + (diffHour % 24) + 'h ago';
        }

        function updatePrefixDistribution(elementId, distribution) {
            const container = document.getElementById(elementId);
            container.innerHTML = '';
            
            if (!distribution || distribution.length === 0) {
                container.innerHTML = '<div class="metric"><span class="metric-label">No data</span></div>';
                return;
            }
            
            // Sort by mask length
            distribution.sort((a, b) => a.mask_length - b.mask_length);
            
            // Determine the URL path based on whether this is IPv4 or IPv6
            const isIPv6 = elementId.includes('ipv6');
            const urlPath = isIPv6 ? '/prefixlength6/' : '/prefixlength/';
            
            distribution.forEach(item => {
                const metric = document.createElement('div');
                metric.className = 'metric';
                metric.innerHTML = `
                    <span class="metric-label">/${item.mask_length}</span>
                    <a href="${urlPath}${item.mask_length}" class="metric-value metric-link">${formatNumber(item.count)}</a>
                `;
                container.appendChild(metric);
            });
        }
        
        function updateHandlerStats(handlerStats) {
            const container = document.getElementById('handler-stats-container');
            container.innerHTML = '';
            
            handlerStats.forEach(handler => {
                const card = document.createElement('div');
                card.className = 'status-card';
                
                // Extract handler name (remove package prefix)
                const handlerName = handler.name.split('.').pop();
                
                card.innerHTML = `
                    <h2>${handlerName}</h2>
                    <div class="metric">
                        <span class="metric-label">Queue</span>
                        <span class="metric-value">${handler.queue_length}/${handler.queue_capacity}</span>
                    </div>
                    <div class="metric">
                        <span class="metric-label">High Water Mark</span>
                        <span class="metric-value">${handler.queue_high_water_mark}/${handler.queue_capacity} (${Math.round(handler.queue_high_water_mark * 100 / handler.queue_capacity)}%)</span>
                    </div>
                    <div class="metric">
                        <span class="metric-label">Processed</span>
                        <span class="metric-value">${formatNumber(handler.processed_count)}</span>
                    </div>
                    <div class="metric">
                        <span class="metric-label">Dropped</span>
                        <span class="metric-value ${handler.dropped_count > 0 ? 'disconnected' : ''}">${formatNumber(handler.dropped_count)}</span>
                    </div>
                    <div class="metric">
                        <span class="metric-label">Avg Time</span>
                        <span class="metric-value">${formatProcessingTime(handler.avg_process_time_ms)}</span>
                    </div>
                    <div class="metric">
                        <span class="metric-label">Min/Max Time</span>
                        <span class="metric-value">${formatProcessingTime(handler.min_process_time_ms)} / ${formatProcessingTime(handler.max_process_time_ms)}</span>
                    </div>
                `;
                
                container.appendChild(card);
            });
        }
        
        function resetAllFields() {
            // Reset all metric fields to '-'
            document.getElementById('connected').textContent = '-';
            document.getElementById('connected').className = 'metric-value';
            document.getElementById('uptime').textContent = '-';
            document.getElementById('go_version').textContent = '-';
            document.getElementById('goroutines').textContent = '-';
            document.getElementById('memory_usage').textContent = '-';
            document.getElementById('connection_duration').textContent = '-';
            document.getElementById('reconnect_count').textContent = '-';
            document.getElementById('bgp_peer_count').textContent = '-';
            document.getElementById('total_messages').textContent = '-';
            document.getElementById('messages_per_sec').textContent = '-';
            document.getElementById('announcements').textContent = '-';
            document.getElementById('withdrawals').textContent = '-';
            document.getElementById('route_churn_per_sec').textContent = '-';
            document.getElementById('total_wire_bytes').textContent = '-';
            document.getElementById('wire_mbits_per_sec').textContent = '-';
            document.getElementById('gc_num').textContent = '-';
            document.getElementById('gc_total_pause').textContent = '-';
            document.getElementById('gc_last_pause').textContent = '-';
            document.getElementById('gc_heap_alloc').textContent = '-';
            document.getElementById('gc_heap_sys').textContent = '-';
            document.getElementById('asns').textContent = '-';
            document.getElementById('prefixes').textContent = '-';
            document.getElementById('ipv4_prefixes').textContent = '-';
            document.getElementById('ipv6_prefixes').textContent = '-';
            document.getElementById('peerings').textContent = '-';
            document.getElementById('peers').textContent = '-';
            document.getElementById('database_size').textContent = '-';
            document.getElementById('live_routes').textContent = '-';
            document.getElementById('ipv4_routes').textContent = '-';
            document.getElementById('ipv6_routes').textContent = '-';
            document.getElementById('ipv4_updates_per_sec').textContent = '-';
            document.getElementById('ipv6_updates_per_sec').textContent = '-';
            document.getElementById('oldest_route').textContent = '-';
            document.getElementById('newest_route').textContent = '-';
            document.getElementById('whois_fresh').textContent = '-';
            document.getElementById('whois_stale').textContent = '-';
            document.getElementById('whois_never').textContent = '-';
            document.getElementById('whois_percent').textContent = '-';
            document.getElementById('whois_successes').textContent = '-';
            document.getElementById('whois_errors').textContent = '-';
            document.getElementById('whois_errors').className = 'metric-value';
            document.getElementById('whois_interval').textContent = '-';

            // Clear handler stats
            document.getElementById('handler-stats-container').innerHTML = '';
            
            // Clear prefix distributions
            document.getElementById('ipv4-prefix-distribution').innerHTML = '<div class="metric"><span class="metric-label">No data</span></div>';
            document.getElementById('ipv6-prefix-distribution').innerHTML = '<div class="metric"><span class="metric-label">No data</span></div>';
        }
        
        function updateStatus() {
            fetch('/api/v1/stats')
                .then(response => response.json())
                .then(response => {
                    // Check if response is an error
                    if (response.status === 'error') {
                        document.getElementById('error').textContent = 'Error: ' + response.error.msg;
                        document.getElementById('error').style.display = 'block';
                        resetAllFields();
                        return;
                    }
                    
                    // Extract data from successful response
                    const data = response.data;
                    
                    // Connection status
                    const connectedEl = document.getElementById('connected');
                    connectedEl.textContent = data.connected ? 'Connected' : 'Disconnected';
                    connectedEl.className = 'metric-value ' + (data.connected ? 'connected' : 'disconnected');
                    
                    // Update all metrics
                    document.getElementById('uptime').textContent = data.uptime;
                    document.getElementById('go_version').textContent = data.go_version;
                    document.getElementById('goroutines').textContent = formatNumber(data.goroutines);
                    document.getElementById('memory_usage').textContent = data.memory_usage;
                    document.getElementById('connection_duration').textContent = data.connection_duration;
                    document.getElementById('reconnect_count').textContent = formatNumber(data.reconnect_count);
                    document.getElementById('total_messages').textContent = formatNumber(data.total_messages);
                    document.getElementById('messages_per_sec').textContent = data.messages_per_sec.toFixed(1);
                    document.getElementById('total_wire_bytes').textContent = formatBytes(data.total_wire_bytes);
                    document.getElementById('wire_mbits_per_sec').textContent = data.wire_mbits_per_sec.toFixed(2) + ' Mbps';
                    document.getElementById('asns').textContent = formatNumber(data.asns);
                    document.getElementById('prefixes').textContent = formatNumber(data.prefixes);
                    document.getElementById('ipv4_prefixes').textContent = formatNumber(data.ipv4_prefixes);
                    document.getElementById('ipv6_prefixes').textContent = formatNumber(data.ipv6_prefixes);
                    document.getElementById('peerings').textContent = formatNumber(data.peerings);
                    document.getElementById('peers').textContent = formatNumber(data.peers);
                    document.getElementById('database_size').textContent = formatBytes(data.database_size_bytes);
                    document.getElementById('live_routes').textContent = formatNumber(data.live_routes);
                    document.getElementById('ipv4_routes').textContent = formatNumber(data.ipv4_routes);
                    document.getElementById('ipv6_routes').textContent = formatNumber(data.ipv6_routes);
                    document.getElementById('ipv4_updates_per_sec').textContent = data.ipv4_updates_per_sec.toFixed(1);
                    document.getElementById('ipv6_updates_per_sec').textContent = data.ipv6_updates_per_sec.toFixed(1);
                    document.getElementById('oldest_route').textContent = formatRelativeTime(data.oldest_route);
                    document.getElementById('newest_route').textContent = formatRelativeTime(data.newest_route);

                    // Update stream stats
                    if (data.stream) {
                        document.getElementById('bgp_peer_count').textContent = formatNumber(data.stream.bgp_peer_count);
                        document.getElementById('announcements').textContent = formatNumber(data.stream.announcements);
                        document.getElementById('withdrawals').textContent = formatNumber(data.stream.withdrawals);
                        document.getElementById('route_churn_per_sec').textContent = data.stream.route_churn_per_sec.toFixed(1);
                    }

                    // Update GC stats
                    if (data.gc) {
                        document.getElementById('gc_num').textContent = formatNumber(data.gc.num_gc);
                        document.getElementById('gc_total_pause').textContent = data.gc.total_pause_ms + ' ms';
                        document.getElementById('gc_last_pause').textContent = data.gc.last_pause_ms.toFixed(3) + ' ms';
                        document.getElementById('gc_heap_alloc').textContent = formatBytes(data.gc.heap_alloc_bytes);
                        document.getElementById('gc_heap_sys').textContent = formatBytes(data.gc.heap_sys_bytes);
                    }

                    // Update WHOIS stats
                    if (data.whois_stats) {
                        document.getElementById('whois_fresh').textContent = formatNumber(data.whois_stats.fresh_asns);
                        document.getElementById('whois_stale').textContent = formatNumber(data.whois_stats.stale_asns);
                        document.getElementById('whois_never').textContent = formatNumber(data.whois_stats.never_fetched);
                        document.getElementById('whois_percent').textContent = data.whois_stats.fresh_percent.toFixed(1) + '%';
                        document.getElementById('whois_successes').textContent = formatNumber(data.whois_stats.successes_last_hour);
                        const errorsEl = document.getElementById('whois_errors');
                        errorsEl.textContent = formatNumber(data.whois_stats.errors_last_hour);
                        errorsEl.className = 'metric-value' + (data.whois_stats.errors_last_hour > 0 ? ' disconnected' : '');
                        document.getElementById('whois_interval').textContent = data.whois_stats.current_interval;
                    }

                    // Update handler stats
                    updateHandlerStats(data.handler_stats || []);
                    
                    // Update prefix distribution
                    updatePrefixDistribution('ipv4-prefix-distribution', data.ipv4_prefix_distribution);
                    updatePrefixDistribution('ipv6-prefix-distribution', data.ipv6_prefix_distribution);
                    
                    // Clear any errors
                    document.getElementById('error').style.display = 'none';
                })
                .catch(error => {
                    document.getElementById('error').textContent = 'Error fetching status: ' + error;
                    document.getElementById('error').style.display = 'block';
                    resetAllFields();
                });
        }
        
        // Update immediately and then every 2 seconds
        updateStatus();
        setInterval(updateStatus, 2000);
    </script>
    </main>

    <footer class="footer">
        <span><a href="{{appRepoURL}}">{{appName}}</a> by <a href="{{appAuthorURL}}">{{appAuthor}}</a></span>
        <span class="separator">|</span>
        <span>{{appLicense}}</span>
        <span class="separator">|</span>
        <span><a href="{{appGitCommitURL}}">{{appGitRevision}}</a></span>
    </footer>
</body>
</html>