/**
 * Grundprüfungen der Barrierefreiheit am Startbildschirm, im echten Fenster.
 *
 * ## Was diese Datei prüft
 *
 * Drei Dinge, die keine Ansichtsrundreise brauchen:
 *
 * 1. einen axe-Rauchtest am Startbildschirm gegen den vollen Satz WCAG 2.2 AA
 *    – die schnellste Antwort auf „ist überhaupt etwas kaputt?“,
 * 2. den **AAA**-Zielwert 7:1 (`color-contrast-enhanced`) als Bericht: Er wird
 *    erhoben und ausgegeben, aber nicht erzwungen. AA ist das
 *    Abnahmekriterium, AAA das Ziel,
 * 3. Struktureigenschaften, die axe nicht misst: die drei Landmarken, ein
 *    zugänglicher Name an **jeder** vorhandenen `<section>` und ein sichtbarer
 *    Fokusring nach echten Tabulatorschritten.
 *
 * ## Was diese Datei ausdrücklich NICHT prüft
 *
 * Die Abdeckung **je Ansicht und je Farbschema** steht vollständig in
 * `barrierefreiheit-ansichten.spec.ts`. Hier lief früher zusätzlich eine
 * Schleife über die drei Schemata – aber nur mit der Einzelregel
 * `color-contrast` und ohne den Startbildschirm je zu verlassen. Das las sich
 * nach „alle drei Farbschemata geprüft“ und war die Messung einer einzigen
 * Ansicht. Die Schleife ist dorthin gewandert, wo sie etwas aussagt; hier
 * stünde sie nur noch doppelt.
 *
 * Ein grüner Lauf heißt auch hier nicht „barrierefrei“: Automatische Prüfung
 * entscheidet nur, was sich maschinell entscheiden lässt. Die Szenarien an
 * NVDA, JAWS und VoiceOver in `docs/barrierefreiheit-pruefplan.md` ersetzt
 * diese Suite nicht.
 */

import { type ElectronApplication, type Page } from '@playwright/test';

import { appStarten, bauPruefen, themaSetzen } from './electron-hilfe';
import { axePruefen, befunde, WCAG_TAGS } from './axe-hilfe';
import { expect, test } from './konsolenwache';

// `undefined`, solange der beforeAll-Hook übersprungen wurde.
let app: ElectronApplication | undefined;
let fenster: Page;

test.beforeAll(async () => {
  // Fehlender oder veralteter Bau ist ein Fehler, kein Grund zum Schweigen.
  bauPruefen();
  ({ app, fenster } = await appStarten());
});

test.afterAll(async () => {
  await app?.close();
});

test.describe('axe-core Rauchtest', () => {
  test('Startbildschirm ist frei von WCAG-A/AA-Verstößen', async () => {
    const ergebnis = await axePruefen(fenster, {
      runOnly: { type: 'tag', values: [...WCAG_TAGS] },
    });

    expect(befunde(ergebnis)).toEqual([]);
  });

  test('meldet den AAA-Zielwert (7:1) als Information, ohne den Lauf zu brechen', async () => {
    await themaSetzen(fenster, 'hell');

    const ergebnis = await axePruefen(fenster, {
      runOnly: { type: 'rule', values: ['color-contrast-enhanced'] },
    });

    const offen = befunde(ergebnis, ['color-contrast-enhanced']);
    if (offen.length > 0) {
      console.info(
        `[a11y] AAA-Zielwert noch nicht überall erreicht (${String(offen.length)} Stellen):`,
        JSON.stringify(offen, null, 2),
      );
    }

    // Bewusst keine Zusicherung: AAA ist Zielwert, nicht Abnahmekriterium.
    expect(Array.isArray(offen)).toBe(true);
  });
});

test.describe('Strukturelle Barrierefreiheit', () => {
  test('bietet die erwarteten Landmarken', async () => {
    await expect(fenster.getByRole('banner')).toBeVisible();
    await expect(fenster.getByRole('main')).toBeVisible();
    await expect(fenster.getByRole('contentinfo')).toBeVisible();
  });

  test('jede Sektion trägt einen zugänglichen Namen', async () => {
    /* Eine <section> wird nur dann als Landmarke („region“) an den Screenreader
       gemeldet, wenn sie benannt ist – sonst ist sie für die Navigation
       wertlos. Geprüft wird deshalb jede vorhandene Sektion, nicht eine feste
       Anzahl: So fällt auch eine später hinzugefügte Sektion ohne Namen auf. */
    const namenlose = await fenster.evaluate(() =>
      [...document.querySelectorAll('section')]
        .filter((s) => !s.getAttribute('aria-labelledby') && !s.getAttribute('aria-label'))
        .map((s) => s.className || s.textContent.trim().slice(0, 40) || '(ohne Kennzeichen)'),
    );

    expect(namenlose, `Sektionen ohne zugänglichen Namen: ${namenlose.join(' | ')}`).toEqual([]);
    expect(await fenster.locator('section').count()).toBeGreaterThan(0);
  });

  test('zeigt bei Tastaturfokus einen sichtbaren Fokusindikator', async () => {
    /* Der Ring hängt an `:focus-visible`. Chromium wendet das nur an, wenn
       zuletzt die Tastatur benutzt wurde – ein programmatisches `.focus()`
       nach einem Mausklick reicht nicht. Deshalb echte Tab-Schritte.
       Der erste Tabstopp ist der Skip-Link; geprüft wird der zweite, also das
       erste reguläre Bedienelement. Welches das ist, hängt vom Funktionsumfang
       ab – der Test stellt deshalb nur sicher, dass es überhaupt eines gibt. */
    await fenster.locator('body').press('Tab');
    await fenster.keyboard.press('Tab');

    const fokussiert = fenster.locator(':focus');
    await expect(fokussiert).toBeVisible();

    const stil = await fokussiert.evaluate((element) => {
      const berechnet = getComputedStyle(element);
      return {
        outlineStyle: berechnet.outlineStyle,
        outlineWidth: berechnet.outlineWidth,
        outlineColor: berechnet.outlineColor,
        boxShadow: berechnet.boxShadow,
      };
    });

    expect(stil.outlineStyle).toBe('solid');
    expect(Number.parseFloat(stil.outlineWidth)).toBeGreaterThanOrEqual(2);
    expect(stil.outlineColor).not.toBe('transparent');
    // Zweiter, gegenfarbiger Ring aus `box-shadow` – sorgt für Sichtbarkeit
    // auf hellem UND dunklem Untergrund.
    expect(stil.boxShadow).not.toBe('none');
  });
});
