{% extends "base.html" %}
{% block title %}Overview — CoderAI{% endblock %}

{% block content %}
<div class="page-header">
  <div>
    <h1>Overview</h1>
    <p>System status</p>
  </div>
  <div class="header-actions">
    <span class="live" id="live-label">Live</span>
  </div>
</div>

<div class="stat-grid">
  <div class="stat">
    <div class="stat-label">Status</div>
    <div class="stat-value small" id="sys-status" style="font-size:1.125rem">—</div>
    <div class="stat-sub" id="sys-backend">loading…</div>
  </div>
  <div class="stat">
    <div class="stat-label">Models Loaded</div>
    <div class="stat-value" id="models-count">—</div>
    <div class="stat-sub" id="models-mode">—</div>
  </div>
  <div class="stat">
    <div class="stat-label">Requests</div>
    <div class="stat-value" id="req-total">0</div>
    <div class="stat-sub"><span id="req-active">0</span> active</div>
  </div>
  <div class="stat" id="vram-card" style="display:none">
    <div class="stat-label">VRAM</div>
    <div class="stat-value" id="vram-pct" style="font-size:2rem">—</div>
    <div class="progress" style="margin-top:.625rem">
      <div class="progress-fill" id="vram-bar" style="width:0%"></div>
    </div>
    <div class="progress-labels" style="color:var(--text-1);font-size:12px;margin-top:.4rem">
      <span id="vram-used">—</span><span id="vram-free">—</span>
    </div>
    <div style="font-size:11.5px;color:var(--text-2);margin-top:.2rem;font-family:var(--mono)" id="vram-total-line"></div>
    <div class="stat-sub" id="vram-gpu" style="margin-top:.25rem"></div>
  </div>

  <div class="stat" id="ram-card" style="display:none">
    <div class="stat-label">RAM</div>
    <div class="stat-value" id="ram-pct" style="font-size:2rem">—</div>
    <div class="progress" style="margin-top:.625rem">
      <div class="progress-fill" id="ram-bar" style="width:0%"></div>
    </div>
    <div class="progress-labels" style="color:var(--text-1);font-size:12px;margin-top:.4rem">
      <span id="ram-used">—</span><span id="ram-free">—</span>
    </div>
    <div style="font-size:11.5px;color:var(--text-2);margin-top:.2rem;font-family:var(--mono)" id="ram-total-line"></div>
    <div class="stat-sub" id="ram-cap" style="margin-top:.25rem"></div>
    <div class="stat-sub" id="ram-leak" style="margin-top:.25rem;color:var(--danger,#e5484d);font-weight:600;display:none">⚠ RAM leak suspected</div>
  </div>
</div>

<div class="card" style="margin-bottom:1rem">
  <div class="card-title">Models</div>
  <div id="active-models"><span class="muted small">No models loaded</span></div>
  {% if is_admin %}
  <div style="margin-top:.875rem">
    <a href="{{ root_path }}/admin/models" class="btn btn-ghost btn-sm">Manage models</a>
  </div>
  {% endif %}
</div>

<div class="card mb-0">
  <div class="card-title">Recent Activity</div>
  <div class="table-wrap" style="border:none">
    <table>
      <thead><tr><th>Time</th><th>Model</th><th>Type</th><th>Status</th><th>Duration</th></tr></thead>
      <tbody id="activity-body">
        <tr class="empty-row"><td colspan="5">No recent activity</td></tr>
      </tbody>
    </table>
  </div>
</div>
{% endblock %}

{% block scripts %}
<script>
async function poll() {
  try {
    const d = await fetch(ROOT_PATH + '/admin/api/status').then(r => r.json());
    const ok = d.status === 'ok';
    document.getElementById('sys-status').textContent = ok ? 'Online' : 'Error';
    document.getElementById('sys-status').className = 'stat-value small ' + (ok ? 'text-green' : 'text-red');
    document.getElementById('sys-backend').textContent = d.backend || d.load_mode || '—';
    document.getElementById('models-count').textContent = d.models_loaded ?? '—';
    document.getElementById('models-mode').textContent = d.load_mode ? d.load_mode + ' mode' : '';

    const loaded = d.loaded_models || [];
    const enabled = d.enabled_models || [];
    const aliases = d.enabled_aliases || {};
    const loadedSet = new Set(loaded);
    const notLoaded = enabled.filter(m => !loadedSet.has(m));
    let html = '';
    if(loaded.length) html += loaded.map(m => `<span class="badge badge-admin" style="margin:.125rem" title="Loaded">● ${m}</span>`).join('');
    if(notLoaded.length) html += notLoaded.map(m => `<span class="badge" style="margin:.125rem;opacity:.55" title="Enabled, not loaded">○ ${m}</span>`).join('');
    const aliasEntries = Object.entries(aliases);
    if(aliasEntries.length) {
      html += aliasEntries.map(([alias, ids]) => {
        const tip = ids.length > 1 ? `Round-robin alias → ${ids.join(', ')}` : `Alias → ${ids[0] || ''}`;
        return `<span class="badge" style="margin:.125rem;background:var(--bg);border:1px solid var(--border);color:var(--text-2)" title="${tip}">⇄ ${alias}</span>`;
      }).join('');
    }
    document.getElementById('active-models').innerHTML = html || '<span class="muted small">No models loaded</span>';

    if (d.vram) {
      document.getElementById('vram-card').style.display = '';
      if (d.vram.free != null && d.vram.total) {
        const usedPct = Math.round(d.vram.used / d.vram.total * 100);
        document.getElementById('vram-pct').textContent = usedPct + '%';
        document.getElementById('vram-bar').style.width = usedPct + '%';
        document.getElementById('vram-used').textContent = d.vram.used.toFixed(1) + ' GB used';
        document.getElementById('vram-free').textContent = d.vram.free.toFixed(1) + ' GB free';
        document.getElementById('vram-total-line').textContent = d.vram.total.toFixed(1) + ' GB total';
      } else {
        document.getElementById('vram-pct').textContent = d.vram.total ? d.vram.total.toFixed(1) + ' GB' : '—';
        document.getElementById('vram-bar').style.width = '0%';
        document.getElementById('vram-used').textContent = '';
        document.getElementById('vram-free').textContent = '';
        document.getElementById('vram-total-line').textContent = '';
      }
      const gpuName = d.vram.gpu || '';
      document.getElementById('vram-gpu').textContent = gpuName.length > 32 ? gpuName.slice(0, 32) + '…' : gpuName;
    } else {
      document.getElementById('vram-card').style.display = 'none';
    }

    if (d.ram && d.ram.total) {
      document.getElementById('ram-card').style.display = '';
      const w = d.ram.watch || {};
      // When a cap is set, show RSS-vs-cap; otherwise system used-vs-total.
      const cap = w.cap_gb || null;
      if (cap && w.rss_gb != null) {
        const pct = Math.min(100, Math.round(w.rss_gb / cap * 100));
        document.getElementById('ram-pct').textContent = pct + '%';
        document.getElementById('ram-bar').style.width = pct + '%';
        document.getElementById('ram-used').textContent = w.rss_gb.toFixed(1) + ' GB server';
        document.getElementById('ram-free').textContent = (d.ram.free != null ? d.ram.free.toFixed(1) + ' GB free' : '');
        document.getElementById('ram-total-line').textContent = cap.toFixed(1) + ' GB cap · ' + d.ram.total.toFixed(1) + ' GB total';
        document.getElementById('ram-cap').textContent = w.last_action ? ('last: ' + w.last_action) : '';
      } else {
        const pct = Math.round(d.ram.used / d.ram.total * 100);
        document.getElementById('ram-pct').textContent = pct + '%';
        document.getElementById('ram-bar').style.width = pct + '%';
        document.getElementById('ram-used').textContent = d.ram.used.toFixed(1) + ' GB used';
        document.getElementById('ram-free').textContent = d.ram.free.toFixed(1) + ' GB free';
        document.getElementById('ram-total-line').textContent = d.ram.total.toFixed(1) + ' GB total (no cap)';
        document.getElementById('ram-cap').textContent = '';
      }
      document.getElementById('ram-leak').style.display = w.leak_suspected ? '' : 'none';
    } else {
      document.getElementById('ram-card').style.display = 'none';
    }

    if (d.requests) {
      document.getElementById('req-total').textContent = d.requests.total ?? 0;
      document.getElementById('req-active').textContent = d.requests.active ?? 0;
    }

    const rows = d.recent_activity || [];
    const tbody = document.getElementById('activity-body');
    if (rows.length === 0) {
      tbody.innerHTML = '<tr class="empty-row"><td colspan="5">No recent activity</td></tr>';
    } else {
      tbody.innerHTML = rows.map(r => {
        const t = new Date(r.time * 1000).toLocaleTimeString();
        const ok = r.status >= 200 && r.status < 300;
        const badge = ok ? 'badge-admin' : 'badge-danger';
        return `<tr>
          <td>${t}</td>
          <td class="small">${r.model}</td>
          <td>${r.type}</td>
          <td><span class="badge ${badge}">${r.status}</span></td>
          <td>${r.duration}s</td>
        </tr>`;
      }).join('');
    }
  } catch {
    document.getElementById('sys-status').textContent = 'Offline';
    document.getElementById('sys-status').className = 'stat-value small text-red';
  }
}
poll();
setInterval(poll, 7000);
</script>
{% endblock %}
