/**
 * Auswertung einer Antwort – reine Funktionen, ohne React und ohne IPC.
 *
 * Die eigentliche Prüfungslogik liegt in `src/shared/katalog.ts`
 * ({@link bewerteAuswahl}). Hier kommt nur hinzu, was die Oberfläche zusätzlich
 * braucht: die Unterscheidung „unvollständig“ gegenüber „falsch“ und die
 * deutschen Texte für Anzeige und Live-Region.
 */

import { bewerteAuswahl, type Frage } from '../../../shared/katalog';
import type { Bewertung } from '../../../shared/lernstand';

/**
 * Nur eine vollständig und ausschließlich richtige Auswahl gilt als richtig.
 * „Unvollständig“ ist deshalb kein Teilerfolg, sondern eine eigene Rückmeldung
 * für eine falsche Antwort – hilfreich beim Lernen, ohne die Bewertung zu
 * beschönigen.
 */
export type ErgebnisArt = 'richtig' | 'unvollstaendig' | 'falsch';

export interface McErgebnis {
  readonly art: ErgebnisArt;
  /** Zählt für den Lernstand: nur `art === 'richtig'` ist wahr. */
  readonly richtig: boolean;
  /** Richtige Optionen, die nicht gewählt wurden. */
  readonly fehlend: readonly string[];
  /** Gewählte Optionen, die falsch sind. */
  readonly zuviel: readonly string[];
}

export const ERGEBNIS_TITEL: Readonly<Record<ErgebnisArt, string>> = Object.freeze({
  richtig: 'Richtig',
  unvollstaendig: 'Unvollständig',
  falsch: 'Falsch',
});

/**
 * Symbol zusätzlich zu Text und Farbe (WCAG 1.4.1): Die Bedeutung darf nie
 * allein an der Farbe hängen.
 */
export const ERGEBNIS_SYMBOL: Readonly<Record<ErgebnisArt, string>> = Object.freeze({
  richtig: '✓',
  unvollstaendig: '!',
  falsch: '✗',
});

/**
 * Wird diese Frage durch Ankreuzen beantwortet?
 *
 * Zusätzlich zum Typ wird geprüft, ob überhaupt Optionen hinterlegt sind:
 * Eine Multiple-Choice-Frage ohne Optionen ließe sich sonst nie bestätigen.
 * Sie wird dann wie eine offene Frage behandelt.
 */
export function istAuswahlfrage(frage: Frage): boolean {
  return frage.typ === 'mc' && (frage.optionen?.length ?? 0) > 0;
}

export function mcErgebnis(frage: Frage, auswahl: readonly string[]): McErgebnis {
  const { richtig, fehlend, zuviel } = bewerteAuswahl(frage, auswahl);
  const art: ErgebnisArt = richtig ? 'richtig' : zuviel.length === 0 ? 'unvollstaendig' : 'falsch';
  return { art, richtig, fehlend, zuviel };
}

/**
 * Bewertung, die bei Multiple Choice automatisch aus dem Ergebnis folgt.
 *
 * Ein Klick ist keine Selbsteinschätzung: Die erratene Antwort geht hier
 * ebenso als „gut“ ein wie die gewusste. Nachgemessen und bewusst so gelassen
 * – `docs/entscheidung-ratewahrscheinlichkeit.md`. Über den **Verlauf**
 * sammelt Raten keinen Vorsprung an: Bei einer Ratechance von 1/3 steht die
 * Frage nach 60 Tagen bei einer Stabilität von 0,21 statt 162,9 Tagen und wird
 * an 53 von 61 Tagen wieder vorgelegt, statt an vieren.
 *
 * „Unvollständig“ bleibt deshalb bei „nochmal“ und wird **nicht** zu „schwer“:
 * „schwer“ ist in FSRS ein Erfolg mit Abschlag. Eine Antwort, die in der
 * Prüfung als falsch zählt, bekäme damit wachsende Intervalle bis 25 Tage bei
 * einer Trefferquote von null. Die Messung dazu steht in
 * `tests/messung-ratewahrscheinlichkeit.test.ts`.
 */
export function bewertungAusErgebnis(ergebnis: McErgebnis): Bewertung {
  return ergebnis.richtig ? 'gut' : 'nochmal';
}

/* `giltAlsRichtig` steht seit 0.22.0 in `shared/lernstand.ts`: Der
   Anwendungskern braucht dieselbe Grenze für den Reife-Beleg, und zwei
   Fassungen derselben Regel liefen auseinander. Hier nur
   weitergereicht, damit die bisherigen Importe unverändert gelten. */
export { giltAlsRichtig } from '../../../shared/lernstand';

/** Aufzählung von Optionslabels: „a“, „a und b“, „a, b und c“. */
export function labelListe(labels: readonly string[]): string {
  const liste = [...labels];
  const [erstes] = liste;
  if (erstes === undefined) {
    return '';
  }
  if (liste.length === 1) {
    return erstes;
  }
  const letztes = liste[liste.length - 1] ?? '';
  return `${liste.slice(0, -1).join(', ')} und ${letztes}`;
}

/** Satz, der die richtige Lösung benennt. */
export function loesungssatz(richtige: readonly string[]): string {
  if (richtige.length === 0) {
    return 'Zu dieser Frage ist keine richtige Antwort hinterlegt.';
  }
  return richtige.length === 1
    ? `Richtig ist Antwort ${labelListe(richtige)}.`
    : `Richtig sind die Antworten ${labelListe(richtige)}.`;
}

/**
 * Text für die Live-Region nach dem Bestätigen einer Multiple-Choice-Frage.
 * Bewusst kurz: die Einzelheiten stehen sichtbar im Ergebnisbereich, der
 * anschließend den Fokus erhält.
 */
export function mcAnsage(ergebnis: McErgebnis, richtige: readonly string[]): string {
  const loesung = loesungssatz(richtige);
  switch (ergebnis.art) {
    case 'richtig':
      return `Richtig. ${loesung}`;
    case 'unvollstaendig': {
      const fehlt =
        ergebnis.fehlend.length === 1
          ? `Es fehlt Antwort ${labelListe(ergebnis.fehlend)}.`
          : `Es fehlen die Antworten ${labelListe(ergebnis.fehlend)}.`;
      return `Unvollständig. ${fehlt} ${loesung}`;
    }
    case 'falsch':
      return `Falsch. ${loesung}`;
  }
}

/**
 * Text für die Live-Region nach einer Selbstbewertung.
 *
 * Sagte bis 0.22.0 „Bewertung gespeichert“. Das stimmt seither nicht mehr:
 * Die Buchung wird bis zum Weiterblättern zurückgehalten, damit sich ein
 * Fehlgriff noch zurücknehmen lässt (`useSitzung`, `bewertungAendern`). Eine
 * Ansage, die eine Speicherung behauptet, die noch aussteht, wäre genau die
 * Sorte kleiner Unwahrheit, die dieses Programm sich nicht leistet – und sie
 * verschwiege ausgerechnet vor Screenreader-Nutzern, dass sich gerade noch
 * etwas ändern lässt.
 */
export function selbstbewertungAnsage(bezeichnung: string): string {
  return `Bewertung: ${bezeichnung}. Sie lässt sich noch ändern.`;
}
