import {
  benoetigteFragen,
  reifesatz,
  SCHWELLE_REIF,
  STUFE_WORT,
  type Reifestufe,
} from '../../../../shared/reife';

export interface ReifeampelProps {
  readonly belegt: number;
  readonly fragenGesamt: number;
  readonly stufe: Reifestufe;
  /** Bereiche, die das Gesamturteil deckeln. Leer bei einer Bereichsampel. */
  readonly deckelnd?: readonly string[];
  /** Zugänglicher Name des Balkens, z. B. „Prüfungsreife insgesamt“. */
  readonly beschriftung: string;
  /**
   * Kurzfassung ohne den Satz zur Bestehensgrenze – für die Bereichsliste.
   *
   * Acht bis zwölf Bereiche mit jeweils voller Begründung wären eine Wand
   * Text, und ein Screenreader läse denselben Satz zwölfmal. Die Grenze
   * gehört zur Gesamtaussage; je Bereich zählt der Stand.
   */
  readonly knapp?: boolean;
}

/**
 * Die Prüfungsreife-Ampel.
 *
 * ## Warum das hier keine Ampel im Wortsinn ist
 *
 * `PLAN.md` sagt eine „Ampel“ zu, und eine Ampel wörtlich genommen ist der
 * WCAG-Albtraum schlechthin: drei Farben, sonst nichts. Hier trägt die Farbe
 * **keine** Information. Was die Stufe ist, steht als Wort da; warum sie es
 * ist, steht als Satz daneben; wie weit es noch ist, steht als Zahl. Wer die
 * Seite in Graustufen ausdruckt, im Modus für hohen Kontrast liest oder sich
 * vorlesen lässt, bekommt genau dasselbe (WCAG 1.4.1).
 *
 * Der Farbstreifen links ist Zugabe für den schnellen Blick – und er ist
 * bewusst kein Rot-Grün-Paar allein, sondern zusätzlich durch seine Breite
 * unterscheidbar, damit er auch bei Farbfehlsichtigkeit etwas beiträgt.
 *
 * ## Warum das Wort vor der Zahl steht, aber nicht im Balkennamen
 *
 * Die Überschrift nennt die Stufe, weil sie die Frage beantwortet, mit der
 * jemand auf den Bildschirm sieht. Der Satz darunter nennt zuerst die
 * nachprüfbare Tatsache („413 von 486 Fragen sitzen belegt“) und erst dann
 * die Auslegung – wer nur den Anfang liest, hat die Tatsache.
 *
 * Der Balken meldet sich als `progressbar` mit `aria-valuetext`, das denselben
 * Text trägt. Ein Screenreader liest damit nie eine nackte Prozentzahl.
 */
export function Reifeampel({
  belegt,
  fragenGesamt,
  stufe,
  deckelnd = [],
  beschriftung,
  knapp = false,
}: ReifeampelProps): React.JSX.Element {
  const satz = knapp
    ? `${String(belegt)} von ${String(fragenGesamt)} Fragen sitzen belegt.`
    : reifesatz(belegt, fragenGesamt, stufe, deckelnd);
  const ziel = benoetigteFragen(SCHWELLE_REIF, fragenGesamt);

  return (
    <div className={`reifeampel reifeampel--${stufe}${knapp ? ' reifeampel--knapp' : ''}`}>
      {/* In der Kurzfassung trägt eine Zeile beides: Wer zwölf Bereiche
          überfliegt, will nicht zwölfmal zwei Absätze lesen. */}
      <p className="reifeampel__satz">
        <span className="reifeampel__stufe">{STUFE_WORT[stufe]}</span>
        {knapp ? ' · ' : null}
        {knapp ? satz : null}
      </p>
      {knapp ? null : <p className="reifeampel__satz">{satz}</p>}

      <div
        className="reifeampel__schiene"
        role="progressbar"
        aria-label={beschriftung}
        aria-valuemin={0}
        aria-valuemax={fragenGesamt}
        aria-valuenow={belegt}
        aria-valuetext={satz}
      >
        {/*
          Die Zielmarke sitzt auf derselben ganzen Zahl, die der Satz nennt –
          nicht auf dem Bruchwert der Schwelle. Sonst stünde die Füllung bei
          erreichter Stufe links von der Marke, und die Marke behauptete das
          Gegenteil des Wortes daneben.

          Beide Breiten laufen über das CSSOM (`element.style`), nicht als
          HTML-Attribut – die strenge CSP ohne `unsafe-inline` bleibt unberührt.
        */}
        <div
          className="reifeampel__fuellung"
          style={{
            inlineSize: `${String(fragenGesamt === 0 ? 0 : (belegt / fragenGesamt) * 100)}%`,
          }}
        />
        {fragenGesamt === 0 ? null : (
          <div
            className="reifeampel__marke"
            style={{ insetInlineStart: `${String((ziel / fragenGesamt) * 100)}%` }}
          />
        )}
      </div>
    </div>
  );
}
