import { expect, test } from '@playwright/test';
import { expectNoA11yViolations } from './support/axe';
import { gotoExpecting } from './support/portal';

/**
 * @intent História 05 — preferências de acessibilidade (`histories/05-preferencias-a11y.md`).
 */
const TOGGLES = [
  { label: 'Contraste', attribute: 'data-a11y-contrast', value: 'high' },
  { label: 'Imagens', attribute: 'data-a11y-grayscale', value: 'true' },
  { label: 'Espaçamento', attribute: 'data-a11y-spacing', value: 'wide' },
  { label: 'Dislexia', attribute: 'data-a11y-dyslexia', value: 'true' },
  { label: 'Movimento reduzido', attribute: 'data-a11y-motion', value: 'reduced' },
] as const;

test.describe('História 05 — Preferências de acessibilidade', () => {
  for (const toggle of TOGGLES) {
    test(`o controle "${toggle.label}" alterna ${toggle.attribute} e o aria-pressed`, async ({
      page,
    }) => {
      await gotoExpecting(page, '/', 200);

      const button = page.getByRole('button', { name: toggle.label, exact: true });
      await expect(page.locator('html')).not.toHaveAttribute(toggle.attribute, toggle.value);
      await expect(button).toHaveAttribute('aria-pressed', 'false');

      await button.click();
      await expect(page.locator('html')).toHaveAttribute(toggle.attribute, toggle.value);
      await expect(button).toHaveAttribute('aria-pressed', 'true');

      await button.click();
      await expect(page.locator('html')).not.toHaveAttribute(toggle.attribute, toggle.value);
      await expect(button).toHaveAttribute('aria-pressed', 'false');
    });
  }

  test('a preferência persiste entre navegações e volta pronta do servidor (SSR)', async ({
    page,
  }) => {
    await gotoExpecting(page, '/', 200);

    await page.getByRole('button', { name: 'Contraste', exact: true }).click();
    await expect(page.locator('html')).toHaveAttribute('data-a11y-contrast', 'high');

    await gotoExpecting(page, '/noticias', 200);
    await expect(page.locator('html')).toHaveAttribute('data-a11y-contrast', 'high');

    // O atributo já vem no HTML do servidor: sem FOUC no primeiro paint.
    const html = await (await page.request.get('/noticias')).text();
    expect(html).toContain('data-a11y-contrast="high"');
  });

  test('a escala de fonte muda o font-size computado do documento', async ({ page }) => {
    await gotoExpecting(page, '/', 200);

    const baseline = await page.evaluate(() =>
      Number.parseFloat(getComputedStyle(document.documentElement).fontSize),
    );

    await page.getByRole('button', { name: 'Aumentar fonte' }).click();
    await expect(page.locator('html')).toHaveAttribute('data-a11y-font-scale', '112');

    const enlarged = await page.evaluate(() =>
      Number.parseFloat(getComputedStyle(document.documentElement).fontSize),
    );

    expect(enlarged).toBeGreaterThan(baseline);

    await page.getByRole('button', { name: 'Restaurar fonte' }).click();
    await expect(page.locator('html')).not.toHaveAttribute('data-a11y-font-scale', '112');
  });

  test('o alto contraste mantém o contraste AA (axe) no texto sobre botão primário', async ({
    page,
    context,
  }) => {
    // O alto contraste troca `--tenant-primary`/`--status-*` (amarelo/branco) sem trocar os
    // `--color-*-content` do daisyUI: sem esta prova, `btn-primary` ficaria branco sobre amarelo
    // (~1,07:1) e nenhum gate rodava o axe nesse modo (ADR-025).
    await context.addCookies([
      { name: 'a11y_contrast', value: '1', domain: 'localhost', path: '/' },
    ]);

    // Páginas com texto civic (`civic-*`) e botões daisyUI: o alto contraste precisa manter AA.
    for (const path of ['/', '/noticias', '/lgpd', '/dados-abertos']) {
      await gotoExpecting(page, path, 200);
      await expect(page.locator('html')).toHaveAttribute('data-a11y-contrast', 'high');
      await expectNoA11yViolations(page);
    }
  });

  test('as preferências não alteram a marcação do shell (ADR-016)', async ({ page }) => {
    await gotoExpecting(page, '/', 200);

    const structure = await page.evaluate(() => ({
      signs: document.querySelectorAll(
        'nav.skip-links, header.site-header, main#main-content, footer#site-footer',
      ).length,
      headings: Array.from(document.querySelectorAll('h1, h2, h3')).map((h) => h.textContent?.trim()),
    }));

    await page.getByRole('button', { name: 'Contraste', exact: true }).click();
    await page.getByRole('button', { name: 'Espaçamento', exact: true }).click();
    await page.getByRole('button', { name: 'Aumentar fonte' }).click();

    const withPreferences = await page.evaluate(() => ({
      signs: document.querySelectorAll(
        'nav.skip-links, header.site-header, main#main-content, footer#site-footer',
      ).length,
      headings: Array.from(document.querySelectorAll('h1, h2, h3')).map((h) => h.textContent?.trim()),
    }));

    expect(withPreferences).toEqual(structure);
  });
});
