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

/**
 * E2E Tests: Control de Acceso por Roles
 * Verifica que las rutas estén correctamente protegidas según el rol del usuario.
 */

// Helper para simular sesión de usuario
async function setUserSession(page: Page, role: 'Admin' | 'Student', studentId?: number) {
  const mockToken = 'mock.jwt.token';
  const mockUser = {
    id: 1,
    username: role === 'Admin' ? 'admin' : 'student',
    role,
    studentId: studentId || (role === 'Student' ? 1 : null),
    studentName: role === 'Student' ? 'Test Student' : null,
  };

  await page.evaluate(
    ({ token, user }) => {
      localStorage.setItem('auth_token', token);
      localStorage.setItem('user', JSON.stringify(user));
    },
    { token: mockToken, user: mockUser }
  );
}

test.describe('Control de Acceso - Rol Admin', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/');
    await setUserSession(page, 'Admin');
  });

  test('admin debe poder acceder al panel de administración', async ({ page }) => {
    await page.goto('/admin');

    // No debe redirigir a otra página
    await expect(page).toHaveURL(/\/admin/);

    // Debe mostrar contenido de admin
    await expect(
      page.getByRole('heading', { name: /panel.*admin|administración|gestión/i })
    ).toBeVisible({ timeout: 10000 });
  });

  test('admin debe poder acceder a gestión de estudiantes', async ({ page }) => {
    await page.goto('/students');

    await expect(page).toHaveURL(/\/students/);
    await expect(
      page.getByRole('heading', { name: /estudiantes|listado/i })
    ).toBeVisible({ timeout: 10000 });
  });

  test('admin debe poder crear estudiantes', async ({ page }) => {
    await page.goto('/students/new');

    await expect(page).toHaveURL(/\/students\/new/);
    await expect(
      page.getByRole('heading', { name: /nuevo estudiante/i })
    ).toBeVisible({ timeout: 10000 });
  });

  test('admin debe ver menú de navegación completo', async ({ page }) => {
    await page.goto('/admin');

    // Admin debe ver opciones de administración
    await expect(
      page.getByRole('link', { name: /panel admin|administración/i }).or(
        page.getByRole('button', { name: /panel admin|administración/i })
      )
    ).toBeVisible({ timeout: 10000 });

    await expect(
      page.getByRole('link', { name: /estudiantes|gestión/i }).or(
        page.getByRole('button', { name: /estudiantes|gestión/i })
      )
    ).toBeVisible();
  });
});

test.describe('Control de Acceso - Rol Student', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/');
    await setUserSession(page, 'Student', 1);
  });

  test('estudiante debe acceder a su dashboard', async ({ page }) => {
    await page.goto('/dashboard');

    await expect(page).toHaveURL(/\/dashboard/);
    await expect(
      page.getByText(/bienvenido|mi portal|dashboard/i)
    ).toBeVisible({ timeout: 10000 });
  });

  test('estudiante debe acceder a sus inscripciones', async ({ page }) => {
    await page.goto('/enrollment/1');

    // No debe redirigir si es su propio ID
    await expect(page).toHaveURL(/\/enrollment/);
  });

  test('estudiante debe acceder a compañeros', async ({ page }) => {
    await page.goto('/classmates/1');

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

  test('estudiante NO debe acceder al panel de admin', async ({ page }) => {
    await page.goto('/admin');

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

  test('estudiante NO debe acceder a gestión de estudiantes', async ({ page }) => {
    await page.goto('/students');

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

  test('estudiante NO debe poder crear estudiantes', async ({ page }) => {
    await page.goto('/students/new');

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

  test('estudiante debe ver menú de navegación limitado', async ({ page }) => {
    await page.goto('/dashboard');

    // Estudiante debe ver opciones de estudiante
    await expect(
      page.getByRole('link', { name: /mi portal|dashboard/i }).or(
        page.getByRole('button', { name: /mi portal|dashboard/i })
      )
    ).toBeVisible({ timeout: 10000 });

    await expect(
      page.getByRole('link', { name: /mis materias|inscripción/i }).or(
        page.getByRole('button', { name: /mis materias|inscripción/i })
      )
    ).toBeVisible();

    // NO debe ver opciones de admin
    await expect(
      page.getByRole('link', { name: /panel admin/i })
    ).not.toBeVisible();
  });
});

test.describe('Control de Acceso - Sin Autenticación', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/');
    await page.evaluate(() => {
      localStorage.clear();
      sessionStorage.clear();
    });
  });

  test('usuario no autenticado debe ir a login desde dashboard', async ({ page }) => {
    await page.goto('/dashboard');
    await expect(page).toHaveURL(/\/login/);
  });

  test('usuario no autenticado debe ir a login desde admin', async ({ page }) => {
    await page.goto('/admin');
    await expect(page).toHaveURL(/\/login/);
  });

  test('usuario no autenticado debe ir a login desde students', async ({ page }) => {
    await page.goto('/students');
    await expect(page).toHaveURL(/\/login/);
  });

  test('usuario no autenticado puede acceder a login', async ({ page }) => {
    await page.goto('/login');
    await expect(page).toHaveURL(/\/login/);
    await expect(page.getByRole('heading', { name: /iniciar sesión/i })).toBeVisible();
  });

  test('usuario no autenticado puede acceder a registro', async ({ page }) => {
    await page.goto('/register');
    await expect(page).toHaveURL(/\/register/);
    await expect(page.getByRole('heading', { name: /crear cuenta|registro/i })).toBeVisible();
  });

  test('usuario no autenticado puede acceder a reset password', async ({ page }) => {
    await page.goto('/reset-password');
    await expect(page).toHaveURL(/\/reset-password/);
  });
});

test.describe('Control de Acceso - Navegación Post-Login', () => {
  test('usuario autenticado no debe ver página de login', async ({ page }) => {
    await page.goto('/');
    await setUserSession(page, 'Student', 1);

    await page.goto('/login');

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

  test('usuario autenticado no debe ver página de registro', async ({ page }) => {
    await page.goto('/');
    await setUserSession(page, 'Student', 1);

    await page.goto('/register');

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