import { expect, test, type Page } from '@playwright/test';
import { expectNoA11yViolations } from './support/axe';
import { openNavGroup, signIn } from './support/cms';

/**
 * Largura do **layout viewport** (`clientWidth`) é a referência de overflow — nunca
 * `window.innerWidth`: quando o conteúdo estoura, o Chromium móvel amplia o layout viewport e
 * `innerWidth` "cresce junto", mascarando o defeito (medido: 575×412 antes da correção do
 * cabeçalho, achado P5.S6.1).
 */
async function expectNoHorizontalOverflow(page: Page, path: string): Promise<void> {
  const metrics = await page.evaluate(() => ({
    client: document.documentElement.clientWidth,
    scroll: document.documentElement.scrollWidth,
  }));

  expect(
    metrics.scroll,
    `${path} com overflow horizontal (${metrics.scroll} > ${metrics.client})`,
  ).toBeLessThanOrEqual(metrics.client + 1);
}

/**
 * História 16 — CMS em ponteiro grosso (Pixel 7). O painel não pode depender de hover nem de
 * alvos pequenos: off-canvas, alvos ≥ 24px (44px é o padrão da casa), **sem overflow horizontal**
 * (o cabeçalho quebra linha e tabela larga rola no próprio contêiner) e axe no viewport real.
 */
test.describe('CMS — mobile', () => {
  test('serve o painel sem overflow e com a navegação off-canvas acessível', async ({ page }) => {
    await signIn(page);

    await expect(page.locator('html')).toHaveAttribute('data-cms-sidebar', 'left');
    await expect(page.locator('main#cms-content')).toBeVisible();

    // As telas com mais controles/camadas: o cabeçalho (usuário/sair), a lista e o formulário
    // longo com o editor rico, e a superfície de layout com duas tabelas.
    for (const path of ['/', '/paginas', '/paginas/criar', '/layout']) {
      await page.goto(path);
      await expect(page.locator('main#cms-content')).toBeVisible();
      await expectNoHorizontalOverflow(page, path);
    }

    await page.goto('/');

    const toggle = page.locator('[data-cms-sidebar-toggle]');
    await expect(toggle).toBeVisible();
    await expect(toggle).toHaveAttribute('aria-expanded', 'false');

    await toggle.click();

    const sidebar = page.locator('#cms-sidebar');
    await expect(sidebar).toBeVisible();
    await expect(toggle).toHaveAttribute('aria-expanded', 'true');

    // P5.6.S2: a gaveta cobre o conteúdo — `main`/`footer` ficam `inert` (nada de foco atrás do
    // painel) e o foco vai ao **primeiro item** da navegação. Não é armadilha: Tab continua andando
    // e o `Escape` devolve o foco ao gatilho.
    await expect(page.locator('main#cms-content')).toHaveAttribute('inert', '');
    await expect(page.locator('.cms-footer')).toHaveAttribute('inert', '');
    await expect(sidebar.locator('a').first()).toBeFocused();

    // Grupos fora da rota atual nascem fechados: abre um para medir os alvos reais.
    await openNavGroup(page, 'Desenvolvimento');

    for (const link of await page.locator('.cms-sidebar__nav a:visible').all()) {
      const box = await link.boundingBox();
      expect(box, 'link do menu sem caixa').not.toBeNull();
      const b = box as NonNullable<typeof box>;
      expect(b.height, 'alvo vertical < 24px').toBeGreaterThanOrEqual(24);
      expect(b.width, 'alvo horizontal < 24px').toBeGreaterThanOrEqual(24);
    }

    await expectNoA11yViolations(page);

    // `Escape` fecha, libera o conteúdo e devolve o foco ao gatilho.
    await page.keyboard.press('Escape');
    await expect(toggle).toHaveAttribute('aria-expanded', 'false');
    await expect(page.locator('body')).not.toHaveClass(/is-sidebar-open/);
    await expect(page.locator('main#cms-content')).not.toHaveAttribute('inert', '');
    await expect(toggle).toBeFocused();

    // Clique no overlay também fecha (a gaveta ocupa a maior parte da tela; clica fora dela).
    await toggle.click();
    await expect(page.locator('[data-cms-sidebar-overlay]')).toBeVisible();

    const viewport = page.viewportSize();
    expect(viewport, 'viewport ausente').not.toBeNull();
    const vp = viewport as NonNullable<typeof viewport>;

    await page
      .locator('[data-cms-sidebar-overlay]')
      .click({ position: { x: vp.width - 8, y: Math.round(vp.height / 2) } });

    await expect(toggle).toHaveAttribute('aria-expanded', 'false');
    await expect(toggle).toBeFocused();
    await expect(page.locator('main#cms-content')).not.toHaveAttribute('inert', '');
  });
});
