// overview.js — Dashboard (v3): Klartext-Urteil, Metrik-Kacheln, System-Gesundheit,
// geführter Schnellstart, "Dein Stack". Speist sich aus /api/status + /api/system/stream.

import { api } from "../core/api.js";
import { $, esc, icon, toast, fmtBytes, confirmModal } from "../core/ui.js";

let S = null;    // letzter Status
let SYS = null;  // letzte System-Metriken

const RUNNING = new Set(["running", "ready", "loading", "starting"]);

function models() { return S?.models || []; }
function activeModel() { return models().find(m => RUNNING.has(m.state)); }

// ---- Aktionen (geführt) ----
function go(view) { document.querySelector(`.nav-item[data-view="${view}"]`)?.click(); }
async function freeMemory() {
  const ok = await confirmModal({
    title: "Speicher freigeben?",
    body: "Alle aktuell geladenen Modelle werden aus dem Grafikspeicher geworfen. " +
          "Beim nächsten Aufruf lädt das jeweilige Modell einfach neu — es geht nichts verloren.",
    confirmLabel: "Speicher freigeben",
  });
  if (!ok) return;
  try { await api("/api/unload", { method: "POST" }); toast("Speicher freigegeben."); setTimeout(() => document.dispatchEvent(new Event("mc:refresh")), 600); }
  catch (e) { toast(e.message, true); }
}
window.mcOv = { go, freeMemory };

// ---- Hero (menschliches Urteil) ----
function renderHero() {
  let title = "Verbinde…", sub = "";
  if (S) {
    const total = models().length, act = activeModel();
    if (!S.swap_ok) { title = "LLM-Engine offline"; sub = "Der llama-swap-Dienst antwortet gerade nicht."; }
    else if (SYS && SYS.ram.percent >= 90) { title = "Achtung: Speicher wird knapp."; sub = `Arbeitsspeicher bei ${Math.round(SYS.ram.percent)} % — eventuell Speicher freigeben.`; }
    else {
      title = "Alles läuft rund.";
      sub = `${total} ${total === 1 ? "Modell" : "Modelle"} bereit · ${act ? `„${act.name}" geladen` : "keins geladen"} · keine Warnungen.`;
    }
  }
  $("#ov-hero").innerHTML = `<div class="pagehead"><div>
      <h1>${esc(title)}</h1><div class="sub">${esc(sub)}</div></div></div>`;
}

// ---- Metrik-Kacheln ----
function tile(label, valueHtml, sub, vCls = "", sCls = "") {
  return `<div class="tile"><div class="t-l">${label}</div>
    <div class="t-v ${vCls}">${valueHtml}</div><div class="t-s ${sCls}">${sub}</div></div>`;
}
function tempWord(t) { return t == null ? "" : t < 55 ? "kühl & gesund" : t < 72 ? "normal" : "läuft heiß"; }
function renderTiles() {
  const act = activeModel();
  const swap = S?.swap_ok;
  let engine = tile("LLM-Engine", swap ? "Online" : "Offline", "llama-swap", swap ? "ok" : "bad");
  let model = tile("Aktives Modell", act ? esc(act.name) : "Keins",
                   act ? "im Grafikspeicher" : "nichts geladen");
  let temp, mem;
  if (SYS) {
    const t = SYS.gpu_temp ?? SYS.cpu.temp;
    temp = tile("GPU-Temperatur", t != null ? `${Math.round(t)}°` : "–", tempWord(t),
                "", t != null && t < 72 ? "ok" : "");
    const free = SYS.ram.total - SYS.ram.used;
    mem = tile("Freier Speicher", `${(free / 1024 ** 3).toFixed(0)}<small> GB</small>`,
               `von ${(SYS.ram.total / 1024 ** 3).toFixed(0)} GB`);
  } else {
    temp = tile("GPU-Temperatur", "–", "messe…");
    mem = tile("Freier Speicher", "–", "messe…");
  }
  $("#ov-tiles").innerHTML = engine + model + temp + mem;
}

// ---- System-Gesundheit ----
function meter(label, pct) {
  const p = Math.max(0, Math.min(100, pct || 0));
  const cls = p >= 90 ? "bad" : p >= 75 ? "warn" : "";
  return `<div class="meter"><div class="meter-h"><span class="mk">${label}</span>
      <span class="mv">${Math.round(p)} %</span></div>
    <div class="bar ${cls}"><i style="width:${Math.max(2, p)}%"></i></div></div>`;
}
function renderHealth() {
  const head = `<div class="card-h"><h3>System-Gesundheit</h3></div>
    <div class="card-sub">So ausgelastet ist dein Mini-PC gerade.</div>`;
  if (!SYS) { $("#ov-health").innerHTML = head + `<div class="empty">Warte auf Messwerte…</div>`; return; }
  let gpuPct = 0;
  const g = SYS.gpu;
  if (g && (g.vram.total + g.gtt.total) > 0)
    gpuPct = ((g.vram.used + g.gtt.used) / (g.vram.total + g.gtt.total)) * 100;
  $("#ov-health").innerHTML = head +
    meter("Prozessor (CPU)", SYS.cpu.percent) +
    meter("Arbeitsspeicher (RAM)", SYS.ram.percent) +
    meter("Grafikspeicher (VRAM)", gpuPct);
}

// ---- Schnellstart ----
function qa(ic, tone, title, sub, onclick) {
  return `<button class="qa" onclick="${onclick}">
    <span class="qa-ic ${tone}">${icon(ic)}</span>
    <span class="qa-main"><span class="qa-t">${title}</span><span class="qa-s">${sub}</span></span>
    <span class="qa-arrow">${icon("chevron")}</span></button>`;
}
function renderQuickstart() {
  $("#ov-quickstart").innerHTML =
    `<div class="card-h"><h3>Schnellstart</h3></div>
     <div class="card-sub">Die häufigsten Aufgaben — ein Klick.</div>` +
    qa("search", "teal", "Modell finden", "Passend zu deiner Hardware", "window.mcOv.go('cookbook')") +
    qa("refresh", "amber", "Speicher freigeben", "Modelle entladen · fragt vorher nach", "window.mcOv.freeMemory()") +
    qa("file", "blue", "Logs ansehen", "Live mitlesen, was läuft", "window.mcOv.go('server')");
}

// ---- Dein Stack ----
function capTag(caps) {
  if (!caps) return "";
  if (caps.includes("Bild")) return `<span class="tag img">Bild</span>`;
  if (caps.includes("Code")) return `<span class="tag code">Code</span>`;
  return `<span class="tag text">Text</span>`;
}
function stackRow(m) {
  const on = RUNNING.has(m.state);
  const dot = m.state === "loading" || m.state === "starting" ? "load" : on ? "on" : "";
  const status = on ? (m.state === "loading" ? "lädt…" : "geladen") : "bereit";
  const file = m.meta?.filename ? `<div class="li-sub mono-sm">${esc(m.meta.filename)}</div>` : "";
  return `<div class="li"><span class="li-dot ${dot}"></span>
    <div class="li-main">
      <div class="flex items-center gap-2"><span class="li-id">${esc(m.name)}</span>${capTag(m.meta?.caps)}</div>${file}</div>
    <span class="li-meta" style="white-space:nowrap">${status}</span></div>`;
}

async function renderNews() {
  const el = $("#ov-news"); if (!el) return;
  const head = `<div class="card-h"><h3>Top-News</h3><span class="meta" style="cursor:pointer" onclick="window.mcOv.go('news')">Alle →</span></div>`;
  el.innerHTML = head + `<div class="empty" style="text-align:center;padding:20px">Lade…</div>`;
  try {
    const items = ((await api("/api/news")).items || []).slice(0, 4);
    el.innerHTML = head + (items.length
      ? `<div class="list">${items.map(n => `<a class="li" href="${esc(n.link)}" target="_blank" rel="noopener" style="text-decoration:none;color:inherit">
           <div class="li-main"><div style="font-size:13px;line-height:1.4">${esc(n.title)}</div>
           <div class="li-sub">${esc(n.source)}</div></div></a>`).join("")}</div>`
      : `<div class="empty">Keine News.</div>`);
  } catch { el.innerHTML = head + `<div class="empty">News gerade nicht ladbar.</div>`; }
}
function renderStack() {
  const ms = models();
  $("#ov-stack").innerHTML =
    `<div class="card-h"><h3>Dein Stack</h3><span class="meta">${ms.length ? ms.length + " konfiguriert" : ""}</span></div>` +
    (ms.length
      ? `<div class="list">${ms.map(stackRow).join("")}</div>`
      : `<div class="empty-c"><div class="e-t">Noch keine Modelle</div>
           <div class="e-s">Hol dir unter „Cookbook" ein Modell, das auf deine Hardware passt.</div></div>`);
}

function renderAll() { renderHero(); renderTiles(); renderHealth(); renderQuickstart(); renderStack(); }

function mount() { renderQuickstart(); renderAll(); renderNews(); }
function onStatus(s) { S = s; renderHero(); renderTiles(); renderStack(); }
function onSystem(sys) { SYS = sys; renderHero(); renderTiles(); renderHealth(); }

export default { id: "overview", mount, onStatus, onSystem };
