{% extends "base.html" %}

{% block title %}{{ page_title }}{% endblock %}

{% block extra_styles %}{% endblock %}

{% block content %}
<div class="swarm-container py-3">

  <div class="swarm-header-row">
    <div class="swarm-title">LIVE SWARM</div>
    <span class="badge badge-success" id="connection-status">Connecting...</span>
  </div>

  <div class="grid grid-3" style="margin-bottom: 16px;">
    <div class="stat">
      <div class="stat-value" id="stat-agents">-</div>
      <div class="stat-label">Total Agents</div>
    </div>
    <div class="stat">
      <div class="stat-value" id="stat-active">-</div>
      <div class="stat-label">Active</div>
    </div>
    <div class="stat">
      <div class="stat-value" id="stat-tasks">-</div>
      <div class="stat-label">Active Tasks</div>
    </div>
  </div>

  <div class="grid grid-2" style="margin-bottom: 16px;">
    <div class="card mc-panel">
      <div class="card-header mc-panel-header">// AGENTS</div>
      <div class="card-body" id="agents-list">
        <p style="color: var(--text-dim); font-size: 12px;">Loading agents...</p>
      </div>
    </div>
    <div class="card mc-panel">
      <div class="card-header mc-panel-header">// ACTIVE AUCTIONS</div>
      <div class="card-body" id="auctions-list">
        <p style="color: var(--text-dim); font-size: 12px;">Loading auctions...</p>
      </div>
    </div>
  </div>

  <!-- Activity Feed Panel -->
  <div class="card mc-panel activity-feed-panel">
    <div class="card-header mc-panel-header">
      // LIVE ACTIVITY FEED
      <span class="activity-badge" id="activity-badge"></span>
    </div>
    <div class="card-body p-0">
      <div class="activity-feed" id="activity-feed">
        <div class="activity-empty">Waiting for events...</div>
      </div>
    </div>
  </div>

  <div class="card mc-panel">
    <div class="card-header mc-panel-header">// SWARM LOG</div>
    <div class="card-body p-0">
      <div class="swarm-log-box" id="swarm-log">
        <div style="color: var(--text-dim);">Waiting for updates...</div>
      </div>
    </div>
  </div>

</div>

<script>
let ws = null;
let reconnectInterval = 1000;
const maxReconnectInterval = 30000;

function connect() {
    const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
    ws = new WebSocket(protocol + '//' + window.location.host + '/swarm/live');

    ws.onopen = function() {
        console.log('WebSocket connected');
        document.getElementById('connection-status').textContent = 'Live';
        document.getElementById('connection-status').className = 'badge badge-success';
        reconnectInterval = 1000;
        addLog('Connected to swarm', 'success');
    };

    ws.onmessage = function(event) {
        var message = JSON.parse(event.data);
        handleMessage(message);
    };

    ws.onclose = function() {
        console.log('WebSocket disconnected');
        document.getElementById('connection-status').textContent = 'Reconnecting...';
        document.getElementById('connection-status').className = 'badge badge-warning';
        addLog('Disconnected, reconnecting...', 'warning');
        setTimeout(connect, reconnectInterval);
        reconnectInterval = Math.min(reconnectInterval * 2, maxReconnectInterval);
    };

    ws.onerror = function(error) {
        console.error('WebSocket error:', error);
        addLog('Connection error', 'error');
    };
}

function handleMessage(message) {
    // Handle activity feed events (from event_log broadcaster)
    if (message.type === 'event' && message.payload) {
        addActivityEvent(message.payload);
        // Also add to log
        var evt = message.payload;
        var logMsg = evt.event_type + ': ' + (evt.source || '');
        addLog(logMsg, 'info');
        return;
    }
    
    if (message.type === 'initial_state' || message.type === 'state_update') {
        var data = message.data;
        document.getElementById('stat-agents').textContent = data.agents.total;
        document.getElementById('stat-active').textContent = data.agents.active;
        document.getElementById('stat-tasks').textContent = data.tasks.active;
        updateAgentsList(data.agents.list);
        updateAuctionsList(data.auctions.list);
        return;
    }

    var evt = message.event || message.type || '';
    var data = message.data || message;

    if (evt === 'agent_joined') {
        addLog('Agent joined: ' + (data.name || data.agent_id || ''), 'success');
        refreshStats();
    } else if (evt === 'agent_left') {
        addLog('Agent left: ' + (data.name || data.agent_id || ''), 'warning');
        refreshStats();
    } else if (evt === 'task_posted') {
        addLog('Task posted: ' + (data.description || data.task_id || '').slice(0, 60), 'info');
        refreshStats();
    } else if (evt === 'bid_submitted') {
        addLog('Bid: ' + (data.agent_id || '').slice(0, 8) + ' bid ' + (data.bid_sats || '?') + ' sats', 'info');
    } else if (evt === 'task_assigned') {
        addLog('Task assigned to ' + (data.agent_id || '').slice(0, 8), 'success');
        refreshStats();
    } else if (evt === 'task_completed') {
        addLog('Task completed by ' + (data.agent_id || '').slice(0, 8), 'success');
        refreshStats();
    }
}

// Activity Feed Functions
const EVENT_ICONS = {
    'task.created': '📝',
    'task.bidding': '⏳',
    'task.assigned': '👤',
    'task.started': '▶️',
    'task.completed': '✅',
    'task.failed': '❌',
    'agent.joined': '🟢',
    'agent.left': '🔴',
    'bid.submitted': '💰',
    'auction.closed': '🏁',
    'tool.called': '🔧',
    'system.error': '⚠️',
};

const EVENT_LABELS = {
    'task.created': 'New task',
    'task.assigned': 'Task assigned',
    'task.completed': 'Task completed',
    'task.failed': 'Task failed',
    'agent.joined': 'Agent joined',
    'agent.left': 'Agent left',
    'bid.submitted': 'Bid submitted',
};

function addActivityEvent(evt) {
    var container = document.getElementById('activity-feed');
    
    // Remove empty message if present
    var empty = container.querySelector('.activity-empty');
    if (empty) empty.remove();
    
    // Create activity item
    var item = document.createElement('div');
    item.className = 'activity-item';
    
    var icon = EVENT_ICONS[evt.event_type] || '•';
    var label = EVENT_LABELS[evt.event_type] || evt.event_type;
    var time = evt.timestamp ? evt.timestamp.split('T')[1].slice(0, 8) : '--:--:--';
    
    // Build description from data
    var desc = '';
    if (evt.data) {
        try {
            var data = typeof evt.data === 'string' ? JSON.parse(evt.data) : evt.data;
            if (data.description) desc = data.description.slice(0, 50);
            else if (data.reason) desc = data.reason.slice(0, 50);
        } catch(e) {}
    }
    
    // Build DOM safely using createElement and textContent
    var iconDiv = document.createElement('div');
    iconDiv.className = 'activity-icon';
    iconDiv.textContent = icon;
    
    var contentDiv = document.createElement('div');
    contentDiv.className = 'activity-content';
    
    var labelDiv = document.createElement('div');
    labelDiv.className = 'activity-label';
    labelDiv.textContent = label;
    contentDiv.appendChild(labelDiv);
    
    if (desc) {
        var descDiv = document.createElement('div');
        descDiv.className = 'activity-desc';
        descDiv.textContent = desc;
        contentDiv.appendChild(descDiv);
    }
    
    var metaDiv = document.createElement('div');
    metaDiv.className = 'activity-meta';
    
    var timeSpan = document.createElement('span');
    timeSpan.className = 'activity-time';
    timeSpan.textContent = time;
    
    var sourceSpan = document.createElement('span');
    sourceSpan.className = 'activity-source';
    sourceSpan.textContent = evt.source || 'system';
    
    metaDiv.appendChild(timeSpan);
    metaDiv.appendChild(sourceSpan);
    contentDiv.appendChild(metaDiv);
    
    item.appendChild(iconDiv);
    item.appendChild(contentDiv);
    
    // Add to top
    container.insertBefore(item, container.firstChild);
    
    // Keep only last 50 items
    while (container.children.length > 50) {
        container.removeChild(container.lastChild);
    }
    
    // Update badge
    var badge = document.getElementById('activity-badge');
    if (badge) {
        badge.style.background = '#28a745';
        setTimeout(() => {
            badge.style.background = '';
        }, 500);
    }
}

function refreshStats() {
    fetch('/swarm').then(function(r) { return r.json(); }).then(function(data) {
        document.getElementById('stat-agents').textContent = data.agents || 0;
        document.getElementById('stat-active').textContent = data.agents_busy || 0;
        document.getElementById('stat-tasks').textContent = (data.tasks_pending || 0) + (data.tasks_running || 0);
    }).catch(function() {});
}

function _t(el, text) { el.textContent = text; return el; }
function _el(tag, cls) { var e = document.createElement(tag); if (cls) e.className = cls; return e; }

function updateAgentsList(agents) {
    var container = document.getElementById('agents-list');
    container.innerHTML = '';

    if (!agents || agents.length === 0) {
        var p = _el('p'); p.style.color = 'var(--text-dim)';
        _t(p, 'No agents registered');
        container.appendChild(p);
        return;
    }

    agents.forEach(function(agent) {
        var card = _el('div', 'agent-card');
        var avatar = _el('div', 'agent-avatar');
        _t(avatar, (agent.name || '?').charAt(0).toUpperCase());
        var info = _el('div', 'agent-info');
        var name = _el('div', 'agent-name');
        _t(name, agent.name || '');
        var desc = _el('div', 'agent-meta');
        _t(desc, agent.description || 'No description');
        var meta = _el('div', 'agent-meta');
        var badge = _el('span', 'badge badge-' + (agent.status === 'active' ? 'success' : agent.status === 'busy' ? 'warning' : 'danger'));
        _t(badge, agent.status || '');
        var stats = _el('span');
        stats.style.marginLeft = '6px';
        _t(stats, (agent.min_bid || 0) + ' sats min | ' + (agent.tasks_completed || 0) + ' tasks | ' + (agent.total_earned || 0) + ' earned');
        meta.appendChild(badge);
        meta.appendChild(stats);
        info.appendChild(name);
        info.appendChild(desc);
        info.appendChild(meta);
        card.appendChild(avatar);
        card.appendChild(info);
        container.appendChild(card);
    });
}

function updateAuctionsList(auctions) {
    var container = document.getElementById('auctions-list');
    container.innerHTML = '';

    if (!auctions || auctions.length === 0) {
        var p = _el('p'); p.style.color = 'var(--text-dim)';
        _t(p, 'No active auctions');
        container.appendChild(p);
        return;
    }

    auctions.forEach(function(auction) {
        var card = _el('div', 'agent-card');
        var info = _el('div', 'agent-info');
        var name = _el('div', 'agent-name');
        _t(name, 'Task ' + String(auction.task_id || '').slice(0, 8));
        var meta = _el('div', 'agent-meta');
        _t(meta, Math.round(auction.time_remaining || 0) + 's remaining | ' + (auction.bid_count || 0) + ' bids');
        info.appendChild(name);
        info.appendChild(meta);
        card.appendChild(info);
        container.appendChild(card);
    });
}

function addLog(message, type) {
    type = type || 'info';
    var log = document.getElementById('swarm-log');
    var timestamp = new Date().toLocaleTimeString();
    var color = type === 'error' ? 'var(--red)' : type === 'warning' ? 'var(--amber)' : type === 'success' ? 'var(--green)' : 'var(--text-dim)';

    var entry = document.createElement('div');
    entry.style.marginBottom = '4px';
    var tsSpan = _el('span');
    tsSpan.style.color = 'var(--text-dim)';
    _t(tsSpan, '[' + timestamp + '] ');
    var msgSpan = _el('span');
    msgSpan.style.color = color;
    _t(msgSpan, message);
    entry.appendChild(tsSpan);
    entry.appendChild(msgSpan);

    log.appendChild(entry);
    log.scrollTop = log.scrollHeight;
}

connect();

// HTMX fallback: load initial data via REST if WebSocket is slow
setTimeout(function() {
    if (document.getElementById('stat-agents').textContent === '-') {
        refreshStats();
        fetch('/swarm/agents').then(function(r) { return r.json(); }).then(function(data) {
            if (data.agents && data.agents.length > 0) {
                updateAgentsList(data.agents);
            }
        }).catch(function() {});
    }
}, 2000);
</script>
{% endblock %}
