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

/** Credenciais do painel usadas pelo e2e (semente demo — `php artisan db:seed`). */
export const EMAIL = 'admin@concordia.inf.br';
export const PASSWORD = 'Concordia';

/**
 * Identidade da equipe de suporte (ADR-033): criada pela semente demo com o perfil `suporte`
 * protegido. O e-mail é a identidade reservada — não é possível criar outra conta com ele pela UI.
 */
export const SUPPORT_EMAIL = 'suporte@maxima.inf.br';
export const SUPPORT_PASSWORD = 'Fundador@2026';

/**
 * Autentica no painel esperando a **navegação** (não o clique).
 *
 * O `actionTimeout` do projeto é 10s e o **primeiro** request do CMS depois de uma edição de PHP
 * paga OPcache frio + Argon2id; o clique isolado estourava esse teto e o spec ficava flaky (visto
 * em `10-cms-layout`). A espera é do **destino**, nunca de tempo fixo (ADR-001).
 */
export async function signIn(
  page: Page,
  email: string = EMAIL,
  password: string = PASSWORD,
): Promise<void> {
  await page.goto('/login');
  await page.getByLabel('E-mail').fill(email);
  await page.getByLabel('Senha').fill(password);

  await Promise.all([
    page.waitForURL(/\/$/, { timeout: 30_000 }),
    page.getByRole('button', { name: 'Entrar' }).click(),
  ]);
}

/** Autentica como a equipe de suporte (grupo `Suporte` visível só para ela — ADR-033). */
export async function signInSupport(page: Page): Promise<void> {
  await signIn(page, SUPPORT_EMAIL, SUPPORT_PASSWORD);
}

/**
 * Abre o menu de usuário do cabeçalho (P5.6.S2).
 *
 * O menu é um `<details>` nativo: abre sem JS e o clique no `summary` é a interação real do
 * operador. Abrir só quando está fechado evita fechar um menu já aberto (clique alterna).
 */
export async function openUserMenu(page: Page): Promise<void> {
  const menu = page.locator('[data-cms-user-menu]');

  await expect(menu).toHaveCount(1);

  if (!(await menu.evaluate((element) => (element as HTMLDetailsElement).open))) {
    await menu.locator('summary').click();
  }

  await expect(menu).toHaveJSProperty('open', true);
}

/**
 * Encerra a sessão pelo menu de usuário (`POST` + CSRF — ADR-037).
 *
 * O antigo botão solto do cabeçalho virou item do menu: quem sai abre o menu primeiro.
 */
export async function signOut(page: Page): Promise<void> {
  await openUserMenu(page);
  await page.locator('[data-cms-user-menu]').getByRole('button', { name: 'Sair' }).click();
}

/**
 * Abre um grupo da navegação lateral pelo rótulo traduzido (P5.6.S2).
 *
 * Grupos fora da rota atual nascem fechados; o link do módulo só existe de fato (visível e
 * clicável) depois de abrir o grupo — como o operador faz.
 */
export async function openNavGroup(page: Page, label: string): Promise<void> {
  const details = page
    .locator('.cms-sidebar__nav details[data-cms-nav-group]')
    .filter({ has: page.locator('summary', { hasText: label }) });

  await expect(details).toHaveCount(1);

  if (!(await details.evaluate((element) => (element as HTMLDetailsElement).open))) {
    await details.locator('summary').click();
  }

  await expect(details).toHaveJSProperty('open', true);
}

/**
 * Arquiva a notícia criada pelo teste (limpeza determinística — ADR-001).
 *
 * O e2e não pode deixar `e2e-*` acumulando no banco de dev: usa a própria rota de arquivamento
 * (soft delete), pela UI, sem atalho de banco. A lista ordena por `updated_at` desc, então a
 * notícia recém-criada é a primeira.
 */
export async function archiveNoticia(page: Page, slug: string): Promise<void> {
  await page.goto('/noticias');

  const row = page.locator('tbody tr', { hasText: slug });
  await expect(row).toHaveCount(1);

  await Promise.all([
    page.waitForURL(/\/noticias$/),
    row.getByRole('button', { name: 'Arquivar' }).click(),
  ]);
}
