// main.js — App-Boot: Panels mounten, Nav starten, Topbar/Alert pflegen, Polling fahren.
// Panel-Vertrag: { id, mount?(), onStatus?(s), onJobs?(jobs) }.

import { api, getToken, setToken, getHfToken, setHfToken } from "./core/api.js";
import { $ } from "./core/ui.js";
import { initNav } from "./core/nav.js";

import overview from "./panels/overview.js";
import models from "./panels/models.js";
import server from "./panels/server.js";
import jobs from "./panels/jobs.js";
import cookbook from "./panels/cookbook.js";
import connect from "./panels/connect.js";
import news from "./panels/news.js";
import guides from "./panels/guides.js";

const panels = [overview, models, server, jobs, cookbook, connect, news, guides];

let lastJobs = [];
let lastSystem = null;

// ---- Topbar / Alert aus dem Status ableiten ----
function applyStatus(s) {
  const dot = $("#swdot"), label = $("#swlabel"), alert = $("#alert");

  if (!s) {
    dot.className = "dot off";
    label.textContent = "Backend nicht erreichbar";
    $("#top-active-text").textContent = "Backend offline";
    showAlert("Backend nicht erreichbar – läuft uvicorn?", false);
  } else {
    const host = s.swap_url.replace(/^https?:\/\//, "");
    dot.className = "dot " + (s.swap_ok ? "on" : "off");
    label.textContent = (s.swap_ok ? "LLM-Engine: Online – " : "LLM-Engine: Offline – ") + host;
    
    const active = (s.models || []).find(m => m.state === "running");
    if (active) {
       $("#top-active-text").innerHTML = `Geladen: <b style="color:var(--teal)">${active.name}</b>`;
    } else {
       $("#top-active-text").innerHTML = "Kein Modell im VRAM";
    }
    
    if (s.swap_ok) hideAlert();
    else showAlert(`LLM-Engine nicht erreichbar unter <b>${host}</b> – läuft der llama-swap Dienst?`, true);
  }
  setSecChip(s);
  for (const p of panels) p.onStatus?.(s);
}

// Security-Chip: ehrlich anzeigen, ob ein Zugangs-Token aktiv ist.
function setSecChip(s) {
  const chip = $("#sec-chip"), tx = $("#sec-chip-tx");
  if (!chip || !tx) return;
  const secured = !!s?.secured;
  chip.classList.toggle("ok", secured);
  tx.textContent = secured ? "Geschützt · Heimnetz" : "Nur im Heimnetz (offen)";
}

function applyJobs(jobs) {
  lastJobs = jobs || [];
  for (const p of panels) p.onJobs?.(lastJobs);
}

function applySystem(sys) {
  lastSystem = sys;
  for (const p of panels) p.onSystem?.(sys);
}

function showAlert(html, warn) {
  const a = $("#alert");
  a.className = "alert" + (warn ? " warn" : "");
  a.innerHTML = `<span class="a-dot"></span><span>${html}</span>`;
  a.style.display = "flex";
}
function hideAlert() { $("#alert").style.display = "none"; }

// ---- Toolbar: ausstehende Updates anzeigen ----
const goView = v => document.querySelector(`.nav-item[data-view="${v}"]`)?.click();
function badge(text, cls, view) {
  const s = document.createElement("span");
  s.className = "upd-badge" + (cls ? " " + cls : "");
  s.textContent = text; s.onclick = () => goView(view);
  return s;
}
async function pollUpdates() {
  try {
    const u = await api("/api/updates");
    const el = $("#update-badges"); if (!el) return;
    el.innerHTML = "";
    el.appendChild(badge(u.os > 0 ? `OS: ${u.os} Updates` : "OS: aktuell", u.os > 0 ? "warn" : "ok", "server"));
    el.appendChild(badge(u.engine > 0 ? "Engine: Update" : "Engine: aktuell", u.engine > 0 ? "warn" : "ok", "server"));
    el.appendChild(badge(u.models > 0 ? `Modelle: ${u.models}` : "Modelle: aktuell", u.models > 0 ? "warn" : "ok", "news"));
  } catch { /* still */ }
}

// ---- Polling ----
async function pollStatus() {
  try { applyStatus(await api("/api/status")); }
  catch { applyStatus(null); }
}
async function pollJobs() {
  try { applyJobs(await api("/api/jobs")); }
  catch { /* still */ }
}

function connectSystemStream() {
  const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
  const wsUrl = `${protocol}//${window.location.host}/api/system/stream`;
  const ws = new WebSocket(wsUrl);
  
  ws.onmessage = (e) => {
    try {
      const data = JSON.parse(e.data);
      applySystem(data);
    } catch (err) {}
  };
  
  ws.onclose = () => {
    // Bei Verbindungsabbruch nach 3 Sekunden erneut versuchen
    setTimeout(connectSystemStream, 3000);
  };
  
  ws.onerror = () => ws.close();
}

// ---- Boot ----
function bootToken() {
  const i = $("#token");
  if (i) {
    i.value = getToken();
    i.addEventListener("change", e => { setToken(e.target.value); pollStatus(); });
  }

  const hf = $("#hf-token");
  if (hf) { hf.value = getHfToken(); hf.addEventListener("change", e => setHfToken(e.target.value)); }

  const sbtn = $("#nav-settings");
  const smod = $("#settings-modal");
  const scls = $("#sm-close");
  if (sbtn && smod && scls) {
    sbtn.addEventListener("click", () => smod.style.display = "flex");
    scls.addEventListener("click", () => smod.style.display = "none");
  }
}
function tickClock() {
  const c = $("#clock");
  if (c) c.textContent = new Date().toTimeString().slice(0, 5);
}

for (const p of panels) p.mount?.();
initNav("overview");
bootToken();
tickClock();
document.addEventListener("mc:refresh", pollStatus);

pollStatus();
pollJobs();
connectSystemStream();

setInterval(tickClock, 1000);
setInterval(pollStatus, 3000);
setInterval(pollJobs, 1500);
pollUpdates();
setInterval(pollUpdates, 60000);
