import test from "node:test";
import assert from "node:assert/strict";
import { allQuestions, chapters, questionsById } from "./question-bank.js";
import { createRunQuestionIds } from "./game.js";

test("Fragenbank enthält zehn Kapitel mit je zehn eindeutigen Fragen", () => {
  assert.equal(chapters.length, 10);
  assert.equal(allQuestions.length, 100);
  assert.equal(new Set(allQuestions.map((question) => question.id)).size, 100);
  assert.deepEqual(
    chapters.map((chapter) => chapter.questions.length),
    Array(10).fill(10)
  );
});

test("jedes Kapitel besitzt einen kurzen Lernerfolg für die Belohnungsmeldung", () => {
  for (const chapter of chapters) {
    assert.ok(chapter.success?.headline, `${chapter.id}: Erfolgsheadline fehlt`);
    assert.ok(chapter.success?.summary, `${chapter.id}: Zusammenfassung fehlt`);
    assert.equal(
      chapter.success?.skills?.length,
      3,
      `${chapter.id}: genau drei Lernpunkte nötig`
    );
  }
});

test("jede Frage ist vollständig und passend zu ihrem Typ definiert", () => {
  for (const question of allQuestions) {
    for (const field of [
      "id",
      "chapterId",
      "objective",
      "title",
      "briefing",
      "prompt",
      "signal",
      "tool",
      "decision",
      "risk",
      "hint"
    ]) {
      assert.ok(question[field], `${question.id}: ${field} fehlt`);
    }
    assert.ok(["choice", "terminal", "sequence"].includes(question.type));

    if (question.type === "choice") {
      assert.ok(question.choices.length >= 3, `${question.id}: zu wenig Auswahl`);
      assert.equal(
        question.choices.filter((choice) => choice.correct).length,
        1,
        `${question.id}: genau eine richtige Auswahl nötig`
      );
    }

    if (question.type === "terminal") {
      assert.ok(question.acceptedAnswers.length > 0);
    }

    if (question.type === "sequence") {
      const available = new Map();
      for (const token of question.tokens) {
        available.set(token, (available.get(token) ?? 0) + 1);
      }
      for (const token of question.answer) {
        const remaining = available.get(token) ?? 0;
        assert.ok(remaining > 0, `${question.id}: Antworttoken ${token} fehlt`);
        available.set(token, remaining - 1);
      }
    }
  }
});

test("Kurslauf wählt drei je Kapitel, Lernmodus alle 100", () => {
  const courseRun = createRunQuestionIds(chapters, "course", () => 0.42);
  const learningRun = createRunQuestionIds(chapters, "learning", () => 0.42);

  assert.equal(courseRun.length, 30);
  assert.equal(new Set(courseRun).size, 30);
  assert.equal(learningRun.length, 100);
  assert.equal(new Set(learningRun).size, 100);

  for (const chapter of chapters) {
    assert.equal(
      courseRun.filter(
        (id) => questionsById[id].chapterId === chapter.id
      ).length,
      3
    );
  }
});
