/* Wissenstests: Gebiete mit Stufen, Test im Dialog, Kurator gibt Fragen frei.
   Lädt nach app.js und trägt sich dort ein. Bewertet wird auf dem Dienst;
   hier stehen nie Lösungen. */
"use strict";

S.wissen = { skills: [], test: null, offen: {} };
OHNE_PROJEKT.push("wissen");
TITEL.wissen = "Wissenstests";
UNTERTITEL.wissen = "Fähigkeiten nachweisen – Stufen erscheinen im Profil und auf der Börse";

async function wissenLaden() {
  S.wissen.skills = await api("/api/wissen/skills");
}

function stufenPille(stufe) {
  return el("span", "pill" + (stufe ? " pill--stufe" : ""),
            stufe ? `Stufe ${stufe}` : "noch nicht nachgewiesen");
}

function zeichneWissen(ziel) {
  const leiste = el("div", "toolbar");
  const name = el("input");
  name.type = "text";
  name.placeholder = "Neues Wissensgebiet, z. B. Python";
  name.maxLength = 80;
  name.style.width = "240px";
  const text = el("input");
  text.type = "text";
  text.placeholder = "Worum geht es? (freiwillig)";
  text.maxLength = 2000;
  text.style.width = "300px";
  const neu = knopf("btn btn--primary", "plus", "Gebiet anlegen");
  neu.onclick = async () => {
    if (name.value.trim().length < 2) { meldung("Bitte einen Namen angeben.", true); return; }
    try {
      await jsonRuf("/api/wissen/skills", "POST", { name: name.value.trim(), beschreibung: text.value.trim() });
      meldung(`„${name.value.trim()}“ angelegt – du bist Kurator und gibst die Fragen frei`);
      await wissenLaden();
      zeichnen();
    } catch (e) { meldung(e.message, true); }
  };
  leiste.append(el("h2", "", "Wissensgebiete"), el("div", "spacer"), name, text, neu);
  ziel.append(leiste);
  if (!S.wissen.skills.length) {
    const leer = el("div", "empty");
    leer.append(ico("graduation-cap", "solid", "gross"), document.createTextNode(
      "Noch kein Wissensgebiet. Wer eines anlegt, ist Kurator: schreibt Fragen oder lässt "
      + "sie vom lokalen Modell erzeugen und gibt sie frei. Drei Stufen, zehn Fragen je Test, "
      + "70 % bestehen, ein Versuch je Tag."));
    ziel.append(leer);
    return;
  }
  S.wissen.skills.forEach((sk) => ziel.append(skillKarte(sk)));
}

function skillKarte(sk) {
  const karte = el("div", "karte");
  const kopf = el("div", "toolbar");
  kopf.style.marginBottom = "6px";
  kopf.append(Object.assign(el("h3", "", sk.name), { style: "margin:0" }), stufenPille(sk.meine_stufe),
              el("div", "spacer"));
  const naechste = sk.meine_stufe + 1;
  if (naechste <= 3) {
    const start = knopf("btn btn--primary", "play", `Test starten (Stufe ${naechste})`);
    const frei = sk.frei[String(naechste)] || 0;
    if (frei < 10) {
      start.disabled = true;
      start.title = `Noch nicht genug freigegebene Fragen für Stufe ${naechste} (${frei} von 10)`;
    }
    start.onclick = () => testStarten(sk, naechste);
    kopf.append(start);
  } else {
    kopf.append(el("span", "pill pill--stufe", "höchste Stufe erreicht"));
  }
  karte.append(kopf);
  if (sk.beschreibung) karte.append(el("p", "", sk.beschreibung));
  karte.append(el("div", "muted",
    `Freigegebene Fragen – Stufe 1: ${sk.frei["1"]} · Stufe 2: ${sk.frei["2"]} · Stufe 3: ${sk.frei["3"]}`
    + (sk.kurator ? ` · Kurator: ${sk.kurator.name}` : "")));

  if (sk.bin_kurator) {
    const strip = el("div", "toolbar");
    strip.style.marginTop = "10px";
    const stufe = el("select");
    stufe.style.width = "auto";
    fuelleAuswahl(stufe, [["1", "Stufe 1"], ["2", "Stufe 2"], ["3", "Stufe 3"]], "1");
    const anzahl = el("input");
    anzahl.type = "number";
    anzahl.min = 1; anzahl.max = 20; anzahl.value = 10;
    anzahl.style.width = "80px";
    const erzeugen = knopf("btn", "wand-magic-sparkles", "Fragen erzeugen");
    erzeugen.onclick = async () => {
      erzeugen.disabled = true;
      try {
        const job = await jsonRuf(`/api/wissen/skills/${sk.id}/generieren`, "POST",
                                  { stufe: Number(stufe.value), anzahl: Number(anzahl.value || 10) });
        meldung(`Das Modell erstellt Fragen (Auftrag ${job.id}) – ein bis drei Minuten`);
        aufJob(job.id, async (fertig) => {
          if (fertig.status === "done") {
            meldung(`${fertig.result.gespeichert} Frage(n) warten auf deine Freigabe`);
            await wissenLaden();
            if (S.ansicht === "wissen") zeichnen();
          } else meldung("Fragen: " + (letzteLogzeile(fertig) || fertig.status), true);
        });
      } catch (e) { meldung(e.message, true); } finally { erzeugen.disabled = false; }
    };
    const pruefen = knopf("btn", "list-check", `Prüfen (${sk.offen} offen)`);
    pruefen.onclick = () => {
      S.wissen.offen[sk.id] = !S.wissen.offen[sk.id];
      zeichnen();
    };
    const neueFrage = knopf("btn btn--ghost", "plus", "Neue Frage");
    neueFrage.onclick = () => {
      S.wissen.offen[sk.id] = true;
      S.wissen.neu = sk.id;
      zeichnen();
    };
    strip.append(el("span", "muted", "Kurator:"), stufe, anzahl, erzeugen, pruefen, neueFrage);
    karte.append(strip);
    if (S.wissen.offen[sk.id]) {
      const box = el("div");
      box.style.marginTop = "10px";
      karte.append(box);
      zeichneFreigabe(box, sk);
    }
  }
  return karte;
}

async function zeichneFreigabe(box, sk) {
  let fragen = [];
  try { fragen = await api(`/api/wissen/skills/${sk.id}/fragen?freigegeben=0`); }
  catch (e) { meldung(e.message, true); return; }
  box.replaceChildren();
  if (S.wissen.neu === sk.id) {
    box.append(frageFormular(sk, null));
    S.wissen.neu = null;
  }
  if (!fragen.length) box.append(el("div", "muted", "Keine Fragen warten auf Freigabe."));
  fragen.forEach((f) => box.append(frageFormular(sk, f)));
}

/** Eine Frage bearbeiten oder anlegen - dieselbe Form für beides. */
function frageFormular(sk, f) {
  const form = el("form", "frage");
  const text = el("textarea");
  text.rows = 2;
  text.maxLength = 500;
  text.placeholder = "Fragetext";
  text.value = f ? f.text : "";
  form.append(text);
  const optionen = [];
  const raster = el("div", "frage__optionen");
  for (let i = 0; i < 4; i++) {
    const zeile = el("label", "frage__option");
    const radio = el("input");
    radio.type = "radio";
    radio.name = `richtig-${f ? f.id : "neu"}-${sk.id}`;
    radio.value = String(i);
    radio.checked = f ? f.richtig === i : i === 0;
    const eingabe = el("input");
    eingabe.type = "text";
    eingabe.maxLength = 200;
    eingabe.placeholder = `Antwort ${i + 1}`;
    eingabe.value = f ? (f.optionen[i] || "") : "";
    zeile.append(radio, eingabe);
    raster.append(zeile);
    optionen.push({ radio, eingabe });
  }
  form.append(raster);
  const fuss = el("div", "toolbar");
  const stufe = el("select");
  stufe.style.width = "auto";
  fuelleAuswahl(stufe, [["1", "Stufe 1"], ["2", "Stufe 2"], ["3", "Stufe 3"]], String(f ? f.stufe : 1));
  fuss.append(el("span", "muted", "richtige Antwort markieren ·"), stufe, el("div", "spacer"));
  const koerper = () => ({
    text: text.value.trim(), optionen: optionen.map((o) => o.eingabe.value.trim()),
    richtig: Number((optionen.find((o) => o.radio.checked) || optionen[0]).radio.value),
    stufe: Number(stufe.value),
  });
  const nachher = async () => { await wissenLaden(); zeichnen(); };
  if (f) {
    const speichern = knopf("btn", "floppy-disk", "Speichern");
    speichern.onclick = async () => {
      try { await jsonRuf(`/api/wissen/fragen/${f.id}`, "PATCH", koerper()); meldung("Frage gespeichert"); }
      catch (e) { meldung(e.message, true); }
    };
    const frei = knopf("btn btn--primary", "check", "Freigeben");
    frei.onclick = async () => {
      try {
        await jsonRuf(`/api/wissen/fragen/${f.id}`, "PATCH", { ...koerper(), freigegeben: true });
        meldung("Frage freigegeben");
        await nachher();
      } catch (e) { meldung(e.message, true); }
    };
    const weg = knopf("btn btn--ghost", "trash", "");
    weg.onclick = async () => {
      if (!confirm("Frage löschen?")) return;
      try { await api(`/api/wissen/fragen/${f.id}`, { method: "DELETE" }); await nachher(); }
      catch (e) { meldung(e.message, true); }
    };
    fuss.append(weg, speichern, frei);
  } else {
    const anlegen = knopf("btn btn--primary", "plus", "Frage freigeben");
    anlegen.onclick = async () => {
      try {
        await jsonRuf(`/api/wissen/skills/${sk.id}/fragen`, "POST", { ...koerper(), freigegeben: true });
        meldung("Frage angelegt und freigegeben");
        await nachher();
      } catch (e) { meldung(e.message, true); }
    };
    fuss.append(anlegen);
  }
  form.append(fuss);
  form.onsubmit = (e) => e.preventDefault();
  return form;
}

/* -- Test im Dialog ---------------------------------------------------------- */
async function testStarten(sk, stufe) {
  let t;
  try { t = await jsonRuf(`/api/wissen/skills/${sk.id}/tests`, "POST", { stufe }); }
  catch (e) { meldung(e.message, true); return; }
  S.wissen.test = t;
  titelSetzen("#test-titel", "graduation-cap", `${sk.name} – Stufe ${stufe}`);
  const box = $("#test-inhalt");
  box.replaceChildren(el("p", "sub", `${t.fragen.length} Fragen, ${Math.ceil(t.fragen.length * 0.7)} müssen stimmen. `
    + "Ein Versuch je Tag – auch wenn du den Dialog schließt."));
  t.fragen.forEach((f, i) => {
    const block = el("div", "frage");
    block.append(el("b", "", `${i + 1}. ${f.text}`));
    f.optionen.forEach((o, j) => {
      const zeile = el("label", "frage__option");
      const radio = el("input");
      radio.type = "radio";
      radio.name = `antwort-${i}`;
      radio.value = String(j);
      zeile.append(radio, el("span", "", o));
      block.append(zeile);
    });
    box.append(block);
  });
  $("#test-abgeben").hidden = false;
  $("#dlg-test").showModal();
}

async function testAbgeben() {
  const t = S.wissen.test;
  if (!t) { $("#dlg-test").close(); return; }
  const antworten = t.fragen.map((f, i) => {
    const gewaehlt = document.querySelector(`input[name="antwort-${i}"]:checked`);
    return gewaehlt ? Number(gewaehlt.value) : null;
  });
  if (antworten.some((a) => a === null) && !confirm("Nicht alle Fragen beantwortet – trotzdem abgeben?")) return;
  try {
    const r = await jsonRuf(`/api/wissen/tests/${t.id}`, "POST", { antworten });
    S.wissen.test = null;
    const box = $("#test-inhalt");
    box.replaceChildren();
    const kopf = el("h3", "", r.bestanden ? `Bestanden – Stufe ${r.stufe}` : "Nicht bestanden");
    kopf.style.color = r.bestanden ? "var(--done)" : "var(--critical)";
    box.append(kopf, el("p", "", `${r.punkte} von ${r.gesamt} richtig.`
      + (r.bestanden ? " Die Stufe steht ab jetzt in deinem Profil."
                     : " Morgen gibt es einen neuen Versuch.")));
    const liste = el("div", "chips");
    liste.style.border = "0";
    liste.style.padding = "0";
    (r.ergebnis || []).forEach((ok, i) => liste.append(
      el("span", "pill" + (ok ? " pill--done" : " pill--failed"), `${i + 1}`)));
    box.append(liste);
    $("#test-abgeben").hidden = true;
    S.me = await api("/api/me");
    await wissenLaden();
    if (S.ansicht === "wissen") zeichnen();
  } catch (e) { meldung(e.message, true); }
}

document.addEventListener("DOMContentLoaded", () => {
  $("#dlg-test form").onsubmit = (e) => { e.preventDefault(); testAbgeben(); };
});

/* -- Profil: nachgewiesene Stufen ------------------------------------------- */
document.addEventListener("profil-geoeffnet", (ev) => {
  const p = ev.detail.person;
  if (!p.stufen || !p.stufen.length) return;
  const box = $("#pr-inhalt");
  box.append(el("label", "", "Nachgewiesen (Wissenstests)"));
  const chips = el("div", "chips");
  chips.style.border = "0";
  chips.style.padding = "0";
  p.stufen.forEach((s) => chips.append(el("span", "pill pill--stufe", `${s.name} · Stufe ${s.stufe}`)));
  box.append(chips);
});

/* -- Eintragen -------------------------------------------------------------- */
ZEICHNER.wissen = zeichneWissen;
LADER.wissen = wissenLaden;
