export interface FortschrittProps {
  /** Zugänglicher Name des Balkens, z. B. „Fortschritt der Lernsitzung“. */
  readonly beschriftung: string;
  /** Sichtbare Textentsprechung, zugleich `aria-valuetext`. */
  readonly text: string;
  /**
   * Leiser Vorspann vor dem Text, etwa der Name der Sitzung.
   *
   * Steht bewusst **nicht** in `aria-valuetext`: Der Balken soll den Stand
   * melden, nicht den Zusammenhang wiederholen – den nennt schon der
   * zugängliche Name des umgebenden Bereichs.
   */
  readonly vorspann?: string;
  readonly wert: number;
  readonly minimum: number;
  readonly maximum: number;
}

/**
 * Fortschrittsanzeige mit Text.
 *
 * Der Balken ist Zugabe: Der Stand steht immer auch als Satz da, nie allein
 * als Länge oder Farbe (WCAG 1.4.1). Der Balken meldet sich als
 * `progressbar` mit `aria-valuenow`, `aria-valuemin` und `aria-valuemax`.
 */
export function Fortschritt({
  beschriftung,
  text,
  vorspann,
  wert,
  minimum,
  maximum,
}: FortschrittProps): React.JSX.Element {
  const spanne = maximum - minimum;
  const anteil = spanne > 0 ? Math.min(100, Math.max(0, ((wert - minimum) / spanne) * 100)) : 0;

  return (
    <div className="fortschritt">
      <p className="fortschritt__text">
        {vorspann === undefined ? null : (
          <span className="fortschritt__vorspann">{vorspann} · </span>
        )}
        {text}
      </p>
      <div
        className="fortschritt__schiene"
        role="progressbar"
        aria-label={beschriftung}
        aria-valuemin={minimum}
        aria-valuemax={maximum}
        aria-valuenow={wert}
        aria-valuetext={text}
      >
        {/*
          Die Breite ist der einzige wirklich dynamische Wert. React setzt sie
          über das CSSOM (`element.style`), nicht als HTML-Attribut – die
          strenge CSP ohne `unsafe-inline` bleibt damit unberührt.
        */}
        <div className="fortschritt__fuellung" style={{ inlineSize: `${String(anteil)}%` }} />
      </div>
    </div>
  );
}
