/**
 * Gemeinsame Theme-Definitionen für Main-, Preload- und Renderer-Prozess.
 *
 * Es gibt drei tatsächlich gerenderte Themes (hell, dunkel, hochkontrast).
 * Die Nutzerauswahl kennt zusätzlich `system`: dann entscheiden die
 * Betriebssystem-Einstellungen (`prefers-color-scheme`, `forced-colors`,
 * `prefers-contrast`).
 */

/** Auswahlmöglichkeiten im Theme-Umschalter. */
export const THEME_AUSWAHLEN = ['system', 'hell', 'dunkel', 'hochkontrast'] as const;

/** Was die Nutzerin/der Nutzer eingestellt hat. */
export type ThemeAuswahl = (typeof THEME_AUSWAHLEN)[number];

/** Was tatsächlich gerendert wird – `system` ist hier bereits aufgelöst. */
export type ThemeAufgeloest = Exclude<ThemeAuswahl, 'system'>;

/** Deutsche Beschriftungen für die Oberfläche. */
export const THEME_BESCHRIFTUNGEN: Readonly<Record<ThemeAuswahl, string>> = Object.freeze({
  system: 'Systemvorgabe',
  hell: 'Hell',
  dunkel: 'Dunkel',
  hochkontrast: 'Hoher Kontrast',
});

/** Ergänzende Erläuterung je Auswahl (für `aria-describedby`). */
export const THEME_ERLAEUTERUNGEN: Readonly<Record<ThemeAuswahl, string>> = Object.freeze({
  system: 'Folgt automatisch den Anzeigeeinstellungen Ihres Betriebssystems.',
  hell: 'Dunkle Schrift auf hellem Grund, ruhige Farbgebung.',
  dunkel: 'Helle Schrift auf dunklem Grund, blendarm für Abendstunden.',
  hochkontrast: 'Maximaler Kontrast mit kräftigen Rändern und Akzentfarben.',
});

/**
 * Signale, die das Betriebssystem bzw. der Browser über Media Queries meldet.
 * Werden separat übergeben, damit die Auflösungslogik rein und testbar bleibt.
 */
export interface SystemAnzeigeSignale {
  /** `(prefers-color-scheme: dark)` */
  readonly bevorzugtDunkel: boolean;
  /** `(forced-colors: active)` – z. B. Windows-Kontrastdesign */
  readonly erzwungeneFarben: boolean;
  /** `(prefers-contrast: more)` */
  readonly bevorzugtMehrKontrast: boolean;
}

export const SYSTEM_SIGNALE_STANDARD: SystemAnzeigeSignale = Object.freeze({
  bevorzugtDunkel: false,
  erzwungeneFarben: false,
  bevorzugtMehrKontrast: false,
});

/** Prüft zur Laufzeit, ob ein unbekannter Wert eine gültige Theme-Auswahl ist. */
export function istThemeAuswahl(wert: unknown): wert is ThemeAuswahl {
  return typeof wert === 'string' && (THEME_AUSWAHLEN as readonly string[]).includes(wert);
}

/**
 * Löst die Nutzerauswahl gegen die Systemsignale zu einem konkreten Theme auf.
 *
 * Regeln:
 * 1. Erzwungene Farben (Windows-Kontrastdesign) haben immer Vorrang – dann
 *    liefert das Betriebssystem die Farben und wir schalten auf `hochkontrast`.
 * 2. Eine explizite Nutzerauswahl schlägt die restlichen Systemsignale.
 * 3. Bei `system` entscheiden `prefers-contrast` und `prefers-color-scheme`.
 */
export function themeAufloesen(
  auswahl: ThemeAuswahl,
  signale: SystemAnzeigeSignale = SYSTEM_SIGNALE_STANDARD,
): ThemeAufgeloest {
  if (signale.erzwungeneFarben) {
    return 'hochkontrast';
  }

  if (auswahl !== 'system') {
    return auswahl;
  }

  if (signale.bevorzugtMehrKontrast) {
    return 'hochkontrast';
  }

  return signale.bevorzugtDunkel ? 'dunkel' : 'hell';
}

/**
 * Passendes `color-scheme` für das aufgelöste Theme – steuert Scrollbalken,
 * Formularelemente und die Fensterdekoration.
 *
 * Muss mit den `color-scheme`-Deklarationen in `tokens.css` übereinstimmen:
 * Das eigene Thema „Hoher Kontrast“ zeichnet weiße Schrift auf Schwarz und
 * zählt deshalb als `dark`.
 *
 * **Beim Windows-Kontrastdesign entscheidet aber das System.** Es gibt auch
 * helle Kontrastdesigns (schwarz auf weiß). `hochkontrast` steht dann nur
 * dafür, dass die Farben von aussen kommen – über hell oder dunkel sagt es
 * nichts. Bis Fassung 0.24.1 lieferte diese Funktion dort unbedingt `dark`
 * und stellte damit Scrollbalken und Formularelemente auf dunkel, während
 * das System hell zeichnete. {@link startfarbeFuer} macht es seit jeher
 * richtig; hier fehlte die Entsprechung.
 */
export function farbschemaFuer(
  theme: ThemeAufgeloest,
  signale: SystemAnzeigeSignale = SYSTEM_SIGNALE_STANDARD,
): 'light' | 'dark' {
  if (signale.erzwungeneFarben) {
    return signale.bevorzugtDunkel ? 'dark' : 'light';
  }
  return theme === 'hell' ? 'light' : 'dark';
}

/**
 * Grundfarbe je Theme – dieselben Werte wie `--farbe-grund` in `tokens.css`.
 *
 * Sie stehen hier ein zweites Mal, weil der Hauptprozess die Fensterfarbe
 * setzen muss, bevor es ein Dokument gibt, das ein Stilblatt laden könnte.
 * Dass beide Stellen übereinstimmen, rechnet `tests/token-kontraste.test.ts`
 * gegen die CSS-Datei nach – eine Kopie, die niemand vergleicht, läuft
 * auseinander.
 */
const STARTFARBEN: Readonly<Record<ThemeAufgeloest, string>> = Object.freeze({
  hell: '#f7f7f5',
  dunkel: '#14161a',
  hochkontrast: '#000000',
});

/**
 * Hintergrundfarbe des Fensters für den Augenblick vor dem ersten Frame.
 *
 * `BrowserWindow` zeichnet diese Farbe, solange der Renderer noch nichts
 * geliefert hat. Sie muss deshalb der **gespeicherten Wahl** folgen und nicht
 * dem Systemdesign: Wer „Dunkel“ eingestellt hat, während das Betriebssystem
 * hell läuft, bekäme sonst bei jedem Start ein helles Aufblitzen – dieselbe
 * Falle, die bei der Anzeigegröße schon einmal zugeschlagen hat.
 *
 * Bei erzwungenen Farben (Windows-Kontrastdesign) gilt das nicht: Dort
 * liefert das Betriebssystem die Farben, und `tokens.css` greift auf `Canvas`
 * zurück. Ein helles Kontrastdesign ist weiß, ein dunkles schwarz – eine
 * eigene Farbe wäre hier schlicht falsch.
 */
export function startfarbeFuer(auswahl: ThemeAuswahl, signale: SystemAnzeigeSignale): string {
  if (signale.erzwungeneFarben) {
    return signale.bevorzugtDunkel ? '#000000' : '#ffffff';
  }
  return STARTFARBEN[themeAufloesen(auswahl, signale)];
}

/**
 * Satz für die `aria-live`-Region nach einer Umschaltung.
 *
 * **Bei erzwungenen Farben wird nichts umgestellt, und das muss dastehen.**
 * `themeAufloesen` gibt dem Windows-Kontrastdesign unbedingt Vorrang: Die
 * Wahl wird gespeichert, sie wirkt aber erst, wenn das Kontrastdesign wieder
 * aus ist. Bis Fassung 0.24.1 meldete die Ansage trotzdem „Darstellung
 * umgestellt auf Dunkel“ – für jemanden, der die Umstellung nicht sehen
 * kann, die denkbar irreführendste Auskunft.
 */
export function umschaltAnsage(
  auswahl: ThemeAuswahl,
  aufgeloest: ThemeAufgeloest,
  signale: SystemAnzeigeSignale = SYSTEM_SIGNALE_STANDARD,
): string {
  if (signale.erzwungeneFarben) {
    return (
      `Ihre Wahl ${THEME_BESCHRIFTUNGEN[auswahl]} ist gespeichert. ` +
      'Sichtbar wird sie erst, wenn das Kontrastdesign von Windows wieder ' +
      'ausgeschaltet ist – solange es läuft, bestimmt das Betriebssystem die Farben.'
    );
  }
  if (auswahl === 'system') {
    return `Darstellung folgt der Systemvorgabe. Aktiv ist ${THEME_BESCHRIFTUNGEN[aufgeloest]}.`;
  }
  return `Darstellung umgestellt auf ${THEME_BESCHRIFTUNGEN[auswahl]}.`;
}
