import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import axe from 'axe-core';
import { jsdomOptionen } from '../src/shared/wcag';
import { useState } from 'react';
import { describe, expect, it } from 'vitest';

import { ThemaWahl } from '../src/renderer/src/components/ThemaWahl';
import { type ThemeAuswahl } from '../src/shared/theme';

/** Minimale Hülle, die die Auswahl wie in der echten App zustandsbehaftet hält. */
function Pruefstand({ start = 'system' }: { start?: ThemeAuswahl }): React.JSX.Element {
  const [auswahl, setzeAuswahl] = useState<ThemeAuswahl>(start);
  return (
    <>
      <h3 id="farbschema-titel">Farbschema</h3>
      <ThemaWahl auswahl={auswahl} onAuswahl={setzeAuswahl} beschriftetVon="farbschema-titel" />
    </>
  );
}

describe('ThemaWahl – ARIA-Struktur', () => {
  it('rendert eine benannte Radiogruppe mit allen vier Optionen', () => {
    render(<Pruefstand />);

    const gruppe = screen.getByRole('radiogroup', { name: 'Farbschema' });
    expect(gruppe).toBeInTheDocument();

    const optionen = screen.getAllByRole('radio');
    expect(optionen.map((o) => o.textContent.replace(/[●○]/gu, '').trim())).toEqual([
      'Systemvorgabe',
      'Hell',
      'Dunkel',
      'Hoher Kontrast',
    ]);
  });

  it('markiert genau eine Option als ausgewählt', () => {
    render(<Pruefstand start="dunkel" />);

    expect(screen.getByRole('radio', { name: /Dunkel/u })).toBeChecked();
    expect(
      screen.getAllByRole('radio').filter((o) => o.getAttribute('aria-checked') === 'true'),
    ).toHaveLength(1);
  });

  it('nutzt Roving Tabindex: nur die aktive Option ist per Tab erreichbar', () => {
    render(<Pruefstand start="hell" />);

    const optionen = screen.getAllByRole('radio');
    const tabIndizes = optionen.map((o) => o.getAttribute('tabindex'));
    expect(tabIndizes).toEqual(['-1', '0', '-1', '-1']);
  });
});

describe('ThemaWahl – Tastaturbedienung nach ARIA APG', () => {
  it('wählt mit Tab und Pfeiltasten ohne Maus', async () => {
    const nutzer = userEvent.setup();
    render(<Pruefstand start="system" />);

    await nutzer.tab();
    expect(screen.getByRole('radio', { name: /Systemvorgabe/u }).matches(':focus')).toBe(true);

    await nutzer.keyboard('{ArrowRight}');
    expect(screen.getByRole('radio', { name: /Hell/u })).toBeChecked();

    await nutzer.keyboard('{ArrowRight}');
    expect(screen.getByRole('radio', { name: /Dunkel/u })).toBeChecked();

    await nutzer.keyboard('{ArrowLeft}');
    expect(screen.getByRole('radio', { name: /Hell/u })).toBeChecked();
  });

  it('springt mit Pos1 und Ende an Anfang und Ende', async () => {
    const nutzer = userEvent.setup();
    render(<Pruefstand start="hell" />);

    await nutzer.tab();
    await nutzer.keyboard('{End}');
    expect(screen.getByRole('radio', { name: /Hoher Kontrast/u })).toBeChecked();

    await nutzer.keyboard('{Home}');
    expect(screen.getByRole('radio', { name: /Systemvorgabe/u })).toBeChecked();
  });

  it('läuft an den Rändern rundherum weiter', async () => {
    const nutzer = userEvent.setup();
    render(<Pruefstand start="system" />);

    await nutzer.tab();
    await nutzer.keyboard('{ArrowLeft}');
    expect(screen.getByRole('radio', { name: /Hoher Kontrast/u })).toBeChecked();

    await nutzer.keyboard('{ArrowRight}');
    expect(screen.getByRole('radio', { name: /Systemvorgabe/u })).toBeChecked();
  });

  it('wählt die fokussierte Option mit der Leertaste', async () => {
    const nutzer = userEvent.setup();
    render(<Pruefstand start="hell" />);

    await nutzer.tab();
    await nutzer.keyboard(' ');
    expect(screen.getByRole('radio', { name: /Hell/u })).toBeChecked();
  });
});

describe('ThemaWahl – Barrierefreiheits-Rauchtest (axe-core)', () => {
  it('meldet keine Verstöße gegen WCAG 2.1 A/AA', async () => {
    const { container } = render(<Pruefstand />);

    const ergebnis = await axe.run(container, jsdomOptionen());

    const zusammenfassung = ergebnis.violations.map((v) => `${v.id}: ${v.help}`);
    expect(zusammenfassung).toEqual([]);
  });
});
