import { useId } from 'react';

import type { Antwortoption, KatalogBild as KatalogBildDaten } from '../../../../shared/katalog';
import { Bilderleiste } from './Bilderleiste';
import { RichTextAnzeige } from './RichTextAnzeige';
import { Zeichenbedeutung } from './Zeichenbedeutung';

export interface AuswahlAntwortProps {
  readonly optionen: readonly Antwortoption[];
  readonly auswahl: readonly string[];
  /** Mehr als eine Antwort ist richtig – dann Kontrollkästchen statt Radios. */
  readonly mehrfach: boolean;
  /**
   * Darf die Darstellung verraten, wie viele Antworten richtig sind?
   *
   * Im Lernmodus ja – die Hilfe gehört zum Lernen. In der Prüfungssimulation
   * nein: Die Zahl stammt aus dem Lösungsschlüssel, und in der echten Prüfung
   * steht sie nirgends. Sonst wäre die Simulation leichter als die Prüfung,
   * auf die sie vorbereitet.
   */
  readonly anzahlVerraten?: boolean;
  /** Nach dem Bestätigen bleibt die Auswahl unverändert stehen. */
  readonly gesperrt: boolean;
  readonly zeigeLoesung: boolean;
  /** Ziffernkürzel nur einblenden, solange sie eingeschaltet sind. */
  readonly kuerzelAktiv: boolean;
  readonly onUmschalten: (label: string) => void;
  readonly bildDaten: (bildId: string) => KatalogBildDaten | undefined;
}

interface Statusanzeige {
  readonly symbol: string;
  readonly text: string;
  readonly klasse: string;
}

/** Rückmeldung je Option – immer Symbol UND Text UND Farbe (WCAG 1.4.1). */
function statusFuer(korrekt: boolean, gewaehlt: boolean): Statusanzeige | null {
  if (korrekt && gewaehlt) {
    return { symbol: '✓', text: 'Richtig – von Ihnen gewählt', klasse: 'richtig' };
  }
  if (korrekt) {
    return { symbol: '✓', text: 'Richtig – nicht gewählt', klasse: 'verpasst' };
  }
  if (gewaehlt) {
    return { symbol: '✗', text: 'Falsch – von Ihnen gewählt', klasse: 'falsch' };
  }
  return null;
}

/**
 * Antwortoptionen einer Multiple-Choice-Frage.
 *
 * Bewusst native Bedienelemente in `<fieldset>` mit `<legend>`: Radios bringen
 * die Pfeiltasten-Navigation und den gemeinsamen Namen der Gruppe von Haus
 * aus mit, Kontrollkästchen die Mehrfachauswahl. Das ist verlässlicher als
 * jede nachgebaute ARIA-Gruppe.
 *
 * ## Warum nach dem Bestätigen kein `disabled`
 *
 * Bis Fassung 0.19.2 trug das `<fieldset>` `disabled={gesperrt}`. Ein
 * gesperrtes Feldset sperrt jedes Bedienelement darin: Nach dem Bestätigen
 * nahm keine einzige Antwortmöglichkeit mehr den Fokus. Wer die Rückmeldung
 * mit dem Tabulator durchgehen wollte, um zu sehen, was er gewählt hatte und
 * was richtig war, kam an keine Zeile mehr heran – und das ausgerechnet in
 * dem Schritt, für den die Optionen überhaupt stehenbleiben. Es war dieselbe
 * Fehlerklasse, die in Fassung 0.17.0 am Freitextfeld behoben wurde
 * (siehe `FreitextAntwort.tsx`), nur auf dem Hauptweg: 471 der 575 Fragen.
 *
 * Jetzt bleiben die Felder erreichbar und melden sich über `aria-disabled`
 * als nicht änderbar; der Umschalter kehrt früh zurück. Ändern lässt sich
 * damit nichts mehr, durchgehen alles (WCAG 2.1.1, 2.4.3).
 *
 * Verrät die Darstellung die Antwortzahl nicht (`anzahlVerraten = false`),
 * erscheinen ausnahmslos Kontrollkästchen, und die Beschriftung nennt nur,
 * was auch im amtlichen Vorwort steht: mindestens eine Antwort ist richtig.
 */
export function AuswahlAntwort({
  optionen,
  auswahl,
  mehrfach,
  anzahlVerraten = true,
  gesperrt,
  zeigeLoesung,
  kuerzelAktiv,
  onUmschalten,
  bildDaten,
}: AuswahlAntwortProps): React.JSX.Element {
  const gruppenId = useId();
  /* Ohne Preisgabe der Antwortzahl müssen alle Fragen gleich aussehen –
     sonst verriete schon die Art des Bedienelements die Lösung. */
  const alsKaestchen = anzahlVerraten ? mehrfach : true;

  return (
    <fieldset className="antwortgruppe">
      <legend className="antwortgruppe__titel">
        {!anzahlVerraten
          ? 'Antwortmöglichkeiten – mindestens eine Antwort ist richtig'
          : mehrfach
            ? 'Antwortmöglichkeiten – mehrere Antworten sind richtig'
            : 'Antwortmöglichkeiten – genau eine Antwort ist richtig'}
      </legend>

      {/* Dass mehrere richtig sind, steht schon in der Beschriftung der
          Gruppe – hier folgt nur noch, was zu tun ist. */}
      {anzahlVerraten && mehrfach ? (
        <p className="antwortgruppe__hinweis">Wählen Sie alle zutreffenden aus.</p>
      ) : null}
      {!anzahlVerraten ? (
        <p className="antwortgruppe__hinweis">
          Wie in der Prüfung ist nicht angegeben, wie viele Antworten richtig sind. Wählen Sie alle
          zutreffenden aus.
        </p>
      ) : null}

      <div className="antwortgruppe__liste">
        {optionen.map((option, stelle) => {
          const gewaehlt = auswahl.includes(option.label);
          const status = zeigeLoesung ? statusFuer(option.korrekt, gewaehlt) : null;
          const feldId = `${gruppenId}-${option.label}`;
          const hatText = option.inhalt.text.trim().length > 0;

          return (
            <div
              key={option.label}
              className={`antwortoption${status ? ` antwortoption--${status.klasse}` : ''}`}
            >
              <input
                className="antwortoption__feld"
                id={feldId}
                type={alsKaestchen ? 'checkbox' : 'radio'}
                name={gruppenId}
                checked={gewaehlt}
                aria-disabled={gesperrt}
                onChange={() => {
                  /* Gesperrt heißt gesperrt – aber erreichbar. React setzt
                     das Bedienelement selbst zurück, weil `checked` am
                     Zustand hängt und der hier unverändert bleibt. */
                  if (!gesperrt) {
                    onUmschalten(option.label);
                  }
                }}
              />
              <label className="antwortoption__beschriftung" htmlFor={feldId}>
                {kuerzelAktiv ? (
                  <span className="antwortoption__ziffer" aria-hidden="true">
                    {stelle + 1}
                  </span>
                ) : null}
                {/* Der amtliche Buchstabe, nicht die Anzeigestelle. Er ist der
                    Verweis auf den gedruckten Katalog und auf die Erklärungen,
                    von denen 368 der 575 ihn beim Namen nennen („Zu a):“). Wird
                    gemischt, steht er deshalb bewusst nicht der Reihe nach – er
                    gehört zum Inhalt, nicht zur Stelle. Ihn aus `stelle`
                    abzuleiten wäre kein Fehler weniger, sondern einer mehr:
                    Die Erklärung darunter meint weiterhin den amtlichen. */}
                <span className="antwortoption__marke">{option.label})</span>
                <span className="antwortoption__inhalt">
                  {hatText ? <RichTextAnzeige text={option.inhalt} /> : null}
                  {option.bilder.length > 0 ? (
                    <Bilderleiste bildIds={option.bilder} bildDaten={bildDaten} />
                  ) : null}
                </span>
                {status ? (
                  <span className={`antwortoption__status antwortoption__status--${status.klasse}`}>
                    <span aria-hidden="true">{status.symbol}</span> {status.text}
                  </span>
                ) : null}
              </label>
              {/* Erst mit der Lösung: Vorher verriete die Bedeutung bei
                  Bild-als-Antwort die Lösung, und im Prüfungslauf (dort ist
                  `zeigeLoesung` immer falsch) gibt es keine Erklärungen.
                  Hinter dem `<label>`, nicht darin: Ein `<details>` gehört
                  nicht in eine Beschriftung – weder inhaltlich (der Name der
                  Option bliebe sonst nicht mehr die Option) noch technisch
                  (Beschriftungen fassen nur Satzinhalt). */}
              {zeigeLoesung && option.bilder.length > 0 ? (
                <Zeichenbedeutung bildIds={option.bilder} bildDaten={bildDaten} />
              ) : null}
            </div>
          );
        })}
      </div>
    </fieldset>
  );
}
