// models.js — "Modelle"-Ansicht (v3): Schnelltest-Chat, Modell-Tabelle, Kontext-Konfiguration.

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

const CTX_HELP = "Kontext = das Kurzzeitgedächtnis des Modells. Größer = merkt sich mehr (längere Dateien/Chats), braucht aber mehr Speicher und wird etwas langsamer.";

let ALL = [];
function refreshSoon() { document.dispatchEvent(new Event("mc:refresh")); }

function capTags(caps) {
  if (!caps?.length) return "–";
  return caps.map(c =>
    c === "Code" ? `<span class="tag code">Code</span>`
      : c === "Bild" ? `<span class="tag img">Bild</span>`
        : `<span class="tag text">Text</span>`).join(" ");
}
function details(meta) {
  if (!meta) return "–";
  const q = meta.quant || "?";
  const c = meta.ctx ? Math.round(meta.ctx / 1024) + "K" : "?";
  const s = meta.size_bytes ? (meta.size_bytes / 1024 ** 3).toFixed(1) + " GB" : "?";
  return `<span class="mono-sm">${esc(q)} · ${c} · ${s}</span>`;
}

function mount() {
  $("#m-head").innerHTML = `<div class="pagehead"><div>
    <h1>Modelle</h1>
    <div class="sub">Deine konfigurierten Modelle — testen, Kontext anpassen oder aus dem Speicher werfen.</div></div></div>`;

  $("#m-chat").innerHTML = `
    <div class="card-h"><h3>Schnelltest</h3></div>
    <div class="card-sub">Schreib eine Nachricht — das gewählte Modell wird automatisch geweckt.</div>
    <label>Modell</label>
    <select id="chat-model"></select>
    <label>Nachricht</label>
    <textarea id="chat-msg" placeholder="z.B. „Erklär mir kurz, was du kannst."></textarea>
    <button class="primary" id="chat-btn">Senden</button>
    <div id="chat-reply" class="reply" style="display:none"></div>`;

  $("#m-table").innerHTML = `
    <div class="card-h"><h3>Modelle &amp; Ports</h3><span class="meta" id="m-count"></span></div>
    <div class="card-sub">Modelle laden automatisch, sobald eine Anfrage kommt — du musst nichts manuell starten.</div>
    <table>
      <thead><tr><th>Modell</th><th>Kann</th><th>Details</th><th>Status</th><th>Port</th><th style="text-align:right">Aktionen</th></tr></thead>
      <tbody id="models"></tbody>
    </table>
    <div id="models-empty" class="empty-c" style="display:none">
      <div class="e-t">Noch keine Modelle konfiguriert</div>
      <div class="e-s">Hol dir unter „Cookbook" ein passendes Modell.</div>
    </div>

    <div id="cfg-modal" class="modal-overlay" style="display:none">
      <div class="modal-card">
        <button id="cfg-close" class="ghost" style="position:absolute;top:14px;right:14px">Schließen</button>
        <h3>Modell konfigurieren</h3>
        <p class="mono-sm" id="cfg-model-name" style="margin:-4px 0 16px"></p>
        <label>Kontext-Größe (Tokens) ${infoDot(CTX_HELP)}</label>
        <input id="cfg-ctx" type="number" value="8192">
        <div class="tile" id="cfg-rec" style="display:none;margin:8px 0 10px;justify-content:space-between;align-items:center" >
          <div style="flex:1"><div style="font-size:13px">Empfohlen für deine Hardware</div>
            <div class="hint" id="cfg-rec-note" style="margin:4px 0 0"></div></div>
          <button class="ghost" id="cfg-rec-apply">Optimal übernehmen</button>
        </div>
        <div class="hint" style="margin-bottom:14px">Es läuft immer nur <b>ein</b> Modell gleichzeitig — ein größerer Kontext hier beeinflusst deine anderen Modelle nicht.</div>
        <button class="primary" id="cfg-save" style="width:100%;margin-top:6px">Speichern</button>
      </div>
    </div>`;

  $("#chat-btn").addEventListener("click", sendChat);
  $("#cfg-close").addEventListener("click", () => $("#cfg-modal").style.display = "none");
  $("#cfg-modal").addEventListener("click", e => { if (e.target.id === "cfg-modal") $("#cfg-modal").style.display = "none"; });
  $("#cfg-save").addEventListener("click", saveConfig);
}

function onStatus(s) {
  ALL = s?.models || [];
  const tb = $("#models"); if (!tb) return;
  $("#models-empty").style.display = ALL.length ? "none" : "flex";
  $("#m-count").textContent = ALL.length ? ALL.length + " konfiguriert" : "";

  const sel = $("#chat-model"), cur = sel.value; sel.innerHTML = "";
  tb.innerHTML = ALL.map(m => {
    const fn = m.meta?.filename ? `<div class="li-sub mono-sm">${esc(m.meta.filename)}</div>` : "";
    return `<tr>
      <td class="mid" style="font-weight:500">${esc(m.name)}${fn}</td>
      <td>${capTags(m.meta?.caps)}</td>
      <td>${details(m.meta)}</td>
      <td>${badge(m.state)}</td>
      <td class="port">${m.port ?? "auto"}</td>
      <td style="text-align:right;white-space:nowrap">
        <button class="ghost" data-cfg="${esc(m.name)}">Konfigurieren</button>
        <button class="ghost" data-unload="${esc(m.name)}">Entladen</button>
      </td></tr>`;
  }).join("");
  for (const m of ALL) sel.insertAdjacentHTML("beforeend", `<option>${esc(m.name)}</option>`);
  if (cur) sel.value = cur;

  tb.querySelectorAll("[data-unload]").forEach(b => b.addEventListener("click", () => unloadOne(b.getAttribute("data-unload"))));
  tb.querySelectorAll("[data-cfg]").forEach(b => b.addEventListener("click", () => openConfig(b.getAttribute("data-cfg"))));
}

function openConfig(alias) {
  const m = ALL.find(x => x.name === alias); if (!m) return;
  $("#cfg-model-name").textContent = m.name;
  $("#cfg-ctx").value = m.meta?.ctx || 8192;
  const opt = m.meta?.optimal_ctx, rec = $("#cfg-rec");
  if (opt) {
    const cur = m.meta?.ctx || 0, peak = m.meta?.peak_ram_gb, peakOpt = m.meta?.peak_ram_optimal_gb;
    $("#cfg-rec-note").innerHTML =
      `Optimal ~${Math.round(opt / 1024)}k → ~${peakOpt} GB Spitzenbedarf.<br>` +
      `Aktuell ~${Math.round(cur / 1024)}k → ~${peak} GB.`;
    $("#cfg-rec-apply").onclick = () => { $("#cfg-ctx").value = opt; };
    rec.style.display = "flex";
  } else { rec.style.display = "none"; }
  $("#cfg-modal").style.display = "flex";
}
async function saveConfig() {
  const alias = $("#cfg-model-name").textContent, ctx = parseInt($("#cfg-ctx").value) || 8192;
  $("#cfg-save").disabled = true;
  try { await api("/api/update_model", { method: "POST", body: JSON.stringify({ alias, ctx }) }); toast("Gespeichert — aktiv beim nächsten Modell-Start."); $("#cfg-modal").style.display = "none"; refreshSoon(); }
  catch (e) { toast(e.message, true); }
  $("#cfg-save").disabled = false;
}

async function unloadOne(m) {
  if (!await confirmModal({ title: `„${m}" entladen?`, body: "Das Modell wird aus dem Grafikspeicher geworfen und lädt beim nächsten Aufruf automatisch neu.", confirmLabel: "Entladen" })) return;
  try { await api("/api/unload?model=" + encodeURIComponent(m), { method: "POST" }); toast("Entladen: " + m); setTimeout(refreshSoon, 600); }
  catch (e) { toast(e.message, true); }
}

async function sendChat() {
  const model = $("#chat-model").value, message = $("#chat-msg").value.trim();
  if (!model) return toast("Kein Modell vorhanden.", true);
  if (!message) return;
  const btn = $("#chat-btn"); btn.disabled = true; btn.textContent = "…";
  const box = $("#chat-reply"); box.style.display = "block"; box.textContent = "(wecke Modell, kann beim Laden kurz dauern…)";
  try { const r = await api("/api/chat", { method: "POST", body: JSON.stringify({ model, message }) }); box.textContent = r.reply; }
  catch (e) { box.textContent = "Fehler: " + e.message; }
  btn.disabled = false; btn.textContent = "Senden"; refreshSoon();
}

export default { id: "models", mount, onStatus };
