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

/**
 * História 21 — Perfil próprio (P2.S5/ADR-033).
 *
 * Jornada: o administrador cria um operador; o operador entra, abre **o próprio perfil**, tenta
 * trocar a senha com a senha atual errada (erro de validação), troca com a atual correta, prova que
 * a antiga não autentica mais e entra com a nova. Ao final o administrador desativa o operador
 * criado (não deixa conta ativa com senha publicada). O perfil próprio **não** exige `acesso.*`;
 * a tela nunca oferece perfil de acesso. Cada execução cria a própria identidade.
 */
test.describe('CMS — Perfil próprio', () => {
  const stamp = Date.now();
  const email = `e2e-perfil-${stamp}@concordia.test`;
  const name = `Operador Perfil E2E ${stamp}`;
  const password = 'E2ePerfil#2026';
  const newPassword = 'E2ePerfilNova#2026';

  test('troca a própria senha e entra com a nova credencial', async ({ page }) => {
    await signIn(page);

    // O administrador cria o operador que abrirá o próprio perfil.
    await page.goto('/usuarios/criar');
    await page.getByLabel('Nome').fill(name);
    await page.getByLabel('E-mail').fill(email);
    await page.getByLabel('Perfil').selectOption({ label: 'Administrador' });
    await page.locator('#field-password').fill(password);
    await page.locator('#field-password_confirmation').fill(password);
    await page.getByRole('button', { name: 'Salvar' }).click();
    await expect(page).toHaveURL(/\/usuarios$/);

    // O operador entra com a própria credencial.
    await page.getByRole('button', { name: 'Sair' }).click();
    await expect(page).toHaveURL(/\/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(),
    ]);

    // O link do perfil está no shell, sem exigir permissão de módulo.
    await page.getByRole('link', { name: 'Meu perfil' }).click();
    await expect(page).toHaveURL(/\/perfil$/);
    await expect(page.getByRole('heading', { name: 'Meu perfil', level: 1 })).toBeVisible();
    await expect(page.getByLabel('Nome')).toHaveValue(name);
    await expect(page.getByLabel('E-mail')).toHaveValue(email);
    await expectNoA11yViolations(page);

    // Senha atual errada: erro de validação genérico, nada muda.
    await page.locator('#field-current_password').fill('SenhaErrada#2026');
    await page.locator('#field-password').fill(newPassword);
    await page.locator('#field-password_confirmation').fill(newPassword);
    await page.getByRole('button', { name: 'Trocar senha' }).click();

    await expect(page.locator('#field-current_password-error')).toHaveText('A senha atual está incorreta.');
    await expectNoA11yViolations(page);

    // Senha atual correta: troca e mantém a sessão atual.
    await page.locator('#field-current_password').fill(password);
    await page.locator('#field-password').fill(newPassword);
    await page.locator('#field-password_confirmation').fill(newPassword);
    await page.getByRole('button', { name: 'Trocar senha' }).click();

    await expect(page).toHaveURL(/\/perfil$/);
    await expect(page.getByText('Senha alterada.')).toBeVisible();
    await expectNoA11yViolations(page);

    // A senha antiga deixa de autenticar.
    await page.getByRole('button', { name: 'Sair' }).click();
    await expect(page).toHaveURL(/\/login$/);
    await page.getByLabel('E-mail').fill(email);
    await page.getByLabel('Senha').fill(password);
    await page.getByRole('button', { name: 'Entrar' }).click();

    await expect(page.getByText('Credenciais inválidas.')).toBeVisible();
    await expect(page).toHaveURL(/\/login$/);

    // A nova senha autentica.
    await page.getByLabel('E-mail').fill(email);
    await page.getByLabel('Senha').fill(newPassword);
    await Promise.all([
      page.waitForURL(/\/$/, { timeout: 30_000 }),
      page.getByRole('button', { name: 'Entrar' }).click(),
    ]);
    await expect(page.getByRole('heading', { name: 'Painel', level: 1 })).toBeVisible();

    // Limpeza: o administrador desativa o operador criado por esta execução (não fica conta
    // ativa com senha publicada no spec, e a lista filtrável não depende da página 1).
    await page.getByRole('button', { name: 'Sair' }).click();
    await expect(page).toHaveURL(/\/login$/);
    await signIn(page);
    await page.goto(`/usuarios?q=${encodeURIComponent(email)}`);

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

    const trigger = row.getByRole('button', { name: 'Desativar' });
    const popoverId = await trigger.getAttribute('popovertarget');
    expect(popoverId).toBeTruthy();

    await trigger.click();

    const dialog = page.locator(`#${popoverId}`);
    await expect(dialog).toBeVisible();
    await dialog.getByRole('button', { name: 'Desativar' }).click();

    await expect(page.getByText('Usuário desativado.')).toBeVisible();
  });
});
