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

/**
 * E2E Tests: Autenticación
 * Tests de prioridad alta que cubren flujos críticos de login, registro y reset de contraseña.
 * Estos tests corren contra el backend real (no mocks).
 */

test.describe('Autenticación - Login', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/login');
  });

  test('debe mostrar el formulario de login', async ({ page }) => {
    await expect(page.getByRole('heading', { name: /iniciar sesión/i })).toBeVisible();
    await expect(page.getByLabel(/usuario/i)).toBeVisible();
    await expect(page.getByLabel(/contraseña/i)).toBeVisible();
    await expect(page.getByRole('button', { name: /iniciar sesión/i })).toBeVisible();
  });

  test('debe mostrar error con credenciales inválidas', async ({ page }) => {
    await page.getByLabel(/usuario/i).fill('usuario_inexistente');
    await page.getByLabel(/contraseña/i).fill('password123');
    await page.getByRole('button', { name: /iniciar sesión/i }).click();

    await expect(page.getByText(/usuario o contraseña incorrectos/i)).toBeVisible({
      timeout: 10000,
    });
  });

  test('debe deshabilitar botón mientras carga', async ({ page }) => {
    await page.getByLabel(/usuario/i).fill('test');
    await page.getByLabel(/contraseña/i).fill('test123');

    const submitButton = page.getByRole('button', { name: /iniciar sesión/i });
    await submitButton.click();

    // El botón debería estar deshabilitado durante la petición
    await expect(submitButton).toBeDisabled();
  });

  test('debe navegar a página de registro', async ({ page }) => {
    await page.getByRole('link', { name: /crear cuenta|registrarse/i }).click();
    await expect(page).toHaveURL(/\/register/);
  });

  test('debe navegar a recuperación de contraseña', async ({ page }) => {
    await page.getByRole('link', { name: /olvidaste tu contraseña/i }).click();
    await expect(page).toHaveURL(/\/reset-password/);
  });

  test('debe validar campos requeridos', async ({ page }) => {
    const submitButton = page.getByRole('button', { name: /iniciar sesión/i });

    // Intentar submit sin datos
    await page.getByLabel(/usuario/i).focus();
    await page.getByLabel(/contraseña/i).focus();
    await page.getByLabel(/usuario/i).blur();

    // El botón debería estar deshabilitado
    await expect(submitButton).toBeDisabled();
  });
});

test.describe('Autenticación - Registro', () => {
  const timestamp = Date.now();

  test.beforeEach(async ({ page }) => {
    await page.goto('/register');
  });

  test('debe mostrar el formulario de registro', async ({ page }) => {
    await expect(page.getByRole('heading', { name: /crear cuenta|registro/i })).toBeVisible();
    await expect(page.getByLabel(/usuario/i)).toBeVisible();
    await expect(page.getByLabel(/nombre/i)).toBeVisible();
    await expect(page.getByLabel(/email/i)).toBeVisible();
    await expect(page.getByLabel(/contraseña/i).first()).toBeVisible();
  });

  test('debe validar email inválido', async ({ page }) => {
    await page.getByLabel(/email/i).fill('email-invalido');
    await page.getByLabel(/nombre/i).focus();

    await expect(page.getByText(/email.*válido|correo.*válido/i)).toBeVisible();
  });

  test('debe validar contraseña mínima', async ({ page }) => {
    await page.getByLabel(/contraseña/i).first().fill('123');
    await page.getByLabel(/nombre/i).focus();

    await expect(page.getByText(/al menos 6 caracteres/i)).toBeVisible();
  });

  test('debe registrar usuario y mostrar código de recuperación', async ({ page }) => {
    const uniqueUser = `testuser_${timestamp}`;
    const uniqueEmail = `test_${timestamp}@example.com`;

    await page.getByLabel(/usuario/i).fill(uniqueUser);
    await page.getByLabel(/nombre/i).fill('Usuario de Prueba E2E');
    await page.getByLabel(/email/i).fill(uniqueEmail);
    await page.getByLabel(/contraseña/i).first().fill('Test123!');

    // Si hay campo de confirmar contraseña
    const confirmPassword = page.getByLabel(/confirmar/i);
    if (await confirmPassword.isVisible()) {
      await confirmPassword.fill('Test123!');
    }

    await page.getByRole('button', { name: /crear cuenta|registrar/i }).click();

    // Debe mostrar código de recuperación o redirigir al dashboard
    await expect(
      page.getByText(/código de recuperación|cuenta creada|bienvenido/i)
    ).toBeVisible({ timeout: 15000 });
  });

  test('debe mostrar error si usuario ya existe', async ({ page }) => {
    // Usar un usuario que probablemente exista
    await page.getByLabel(/usuario/i).fill('admin');
    await page.getByLabel(/nombre/i).fill('Test');
    await page.getByLabel(/email/i).fill('admin@test.com');
    await page.getByLabel(/contraseña/i).first().fill('Test123!');

    const confirmPassword = page.getByLabel(/confirmar/i);
    if (await confirmPassword.isVisible()) {
      await confirmPassword.fill('Test123!');
    }

    await page.getByRole('button', { name: /crear cuenta|registrar/i }).click();

    await expect(page.getByText(/usuario ya existe|ya está en uso/i)).toBeVisible({
      timeout: 10000,
    });
  });

  test('debe navegar a login desde registro', async ({ page }) => {
    await page.getByRole('link', { name: /iniciar sesión|ya tienes cuenta/i }).click();
    await expect(page).toHaveURL(/\/login/);
  });
});

test.describe('Autenticación - Reset de Contraseña', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/reset-password');
  });

  test('debe mostrar el formulario de reset', async ({ page }) => {
    await expect(
      page.getByRole('heading', { name: /recuperar|restablecer|cambiar contraseña/i })
    ).toBeVisible();
    await expect(page.getByLabel(/usuario/i)).toBeVisible();
    await expect(page.getByLabel(/código.*recuperación/i)).toBeVisible();
    await expect(page.getByLabel(/nueva contraseña/i)).toBeVisible();
  });

  test('debe validar código de recuperación inválido', async ({ page }) => {
    await page.getByLabel(/usuario/i).fill('testuser');
    await page.getByLabel(/código.*recuperación/i).fill('CODIGO_INVALIDO');
    await page.getByLabel(/nueva contraseña/i).fill('NewPass123!');

    await page.getByRole('button', { name: /cambiar|restablecer|actualizar/i }).click();

    await expect(
      page.getByText(/código.*inválido|usuario no encontrado|error/i)
    ).toBeVisible({ timeout: 10000 });
  });

  test('debe validar nueva contraseña mínima', async ({ page }) => {
    await page.getByLabel(/nueva contraseña/i).fill('123');
    await page.getByLabel(/usuario/i).focus();

    await expect(page.getByText(/al menos 6 caracteres/i)).toBeVisible();
  });

  test('debe navegar a login desde reset', async ({ page }) => {
    await page.getByRole('link', { name: /volver.*login|iniciar sesión/i }).click();
    await expect(page).toHaveURL(/\/login/);
  });
});

test.describe('Autenticación - Logout', () => {
  test('debe cerrar sesión correctamente', async ({ page }) => {
    // Primero necesitamos estar logueados
    // Simulamos token en localStorage para test rápido
    await page.goto('/');

    // Si hay un botón de logout visible (usuario logueado)
    const logoutButton = page.getByRole('button', { name: /cerrar sesión|logout/i });
    const menuButton = page.getByRole('button', { name: /menú|usuario|perfil/i });

    if (await menuButton.isVisible()) {
      await menuButton.click();
    }

    if (await logoutButton.isVisible()) {
      await logoutButton.click();
      await expect(page).toHaveURL(/\/login/);
    } else {
      // Si no hay usuario logueado, debería redirigir a login
      await expect(page).toHaveURL(/\/login/);
    }
  });
});

test.describe('Autenticación - Protección de Rutas', () => {
  test('debe redirigir a login si no está autenticado', async ({ page }) => {
    // Limpiar cualquier token existente
    await page.goto('/');
    await page.evaluate(() => localStorage.clear());

    // Intentar acceder a ruta protegida
    await page.goto('/dashboard');

    // Debe redirigir a login
    await expect(page).toHaveURL(/\/login/);
  });

  test('debe redirigir a login al acceder a enrollment sin auth', async ({ page }) => {
    await page.evaluate(() => localStorage.clear());
    await page.goto('/enrollment/1');

    await expect(page).toHaveURL(/\/login/);
  });

  test('debe redirigir a login al acceder a classmates sin auth', async ({ page }) => {
    await page.evaluate(() => localStorage.clear());
    await page.goto('/classmates/1');

    await expect(page).toHaveURL(/\/login/);
  });
});
