# Guía de Desarrollo - Portal Admin

**Fecha de creación:** 2025-11-29
**Versión:** 1.0.0
**Estado:** VIGENTE
**Aplica a:** apps/frontend/src/apps/admin/ + apps/backend/src/modules/admin/

---

## 1. Visión General

### 1.1 Propósito

El Portal Admin es la interfaz principal para administradores del sistema GAMILIT. Proporciona herramientas para:

- **Gestión de Usuarios:** Crear, editar, suspender y eliminar usuarios del sistema
- **Gestión de Organizaciones:** Administrar tenants, instituciones y sus suscripciones
- **Configuración del Sistema:** Settings globales, feature flags y mantenimiento
- **Moderación de Contenido:** Aprobar/rechazar contenido creado por teachers
- **Configuración de Gamificación:** Parámetros de ML Coins, rangos Maya, achievements
- **Monitoreo del Sistema:** Salud del sistema, métricas, logs y performance
- **Alertas del Sistema:** Gestión de alertas críticas y de intervención
- **Reportes y Analytics:** Dashboards, estadísticas y exportación de datos
- **Operaciones Masivas:** Bulk operations (suspend, delete, role updates)
- **Gestión de Roles y Permisos:** Configuración de permisos por rol
- **Asignación de Aulas:** Asignar teachers a classrooms

### 1.2 Usuarios Objetivo

| Rol | Acceso | Funcionalidades |
|-----|--------|-----------------|
| Admin | Completo | Todas las funcionalidades del portal |
| Super Admin | Completo + System | Incluye configuración crítica del sistema |

---

## 2. Arquitectura

### 2.1 Estructura de Carpetas

#### Frontend (apps/frontend/src/apps/admin/)

```
admin/
├── index.ts                    # Barrel export principal
├── layouts/
│   └── AdminLayout.tsx         # Layout principal con navegación
├── pages/                      # Páginas del portal (14 páginas)
│   ├── AdminDashboardPage.tsx          # Dashboard principal
│   ├── AdminUsersPage.tsx              # Gestión de usuarios
│   ├── AdminInstitutionsPage.tsx       # Gestión de organizaciones
│   ├── AdminRolesPage.tsx              # Roles y permisos
│   ├── AdminContentPage.tsx            # Moderación de contenido
│   ├── AdminGamificationPage.tsx       # Config gamificación
│   ├── AdminSettingsPage.tsx           # Configuración del sistema
│   ├── AdminMonitoringPage.tsx         # Monitoreo del sistema
│   ├── AdminAlertsPage.tsx             # Alertas del sistema
│   ├── AdminAnalyticsPage.tsx          # Analytics y métricas
│   ├── AdminReportsPage.tsx            # Generación de reportes
│   ├── AdminProgressPage.tsx           # Progreso general
│   ├── AdminClassroomTeacherPage.tsx   # Asignación de aulas
│   └── AdminAdvancedPage.tsx           # Configuración avanzada
├── components/                 # Componentes organizados por dominio
│   ├── dashboard/              # Dashboard components
│   │   └── AdminDashboardHero.tsx
│   ├── users/                  # Gestión de usuarios
│   ├── alerts/                 # Sistema de alertas
│   ├── analytics/              # Gráficas y métricas
│   ├── monitoring/             # Monitoreo del sistema
│   ├── content/                # Moderación de contenido
│   ├── gamification/           # Configuración gamificación
│   ├── reports/                # Generación de reportes
│   ├── progress/               # Vistas de progreso
│   ├── classroom-teacher/      # Asignación de aulas
│   ├── settings/               # Configuración
│   ├── advanced/               # Configuración avanzada
│   └── index.ts
├── hooks/                      # Custom hooks (20+ hooks)
│   ├── useAdminDashboard.ts            # Dashboard data
│   ├── useAdminData.ts                 # General admin data
│   ├── useUserManagement.ts            # CRUD usuarios
│   ├── useOrganizations.ts             # CRUD organizaciones
│   ├── useRoles.ts                     # Gestión de roles
│   ├── useRolePermissions.ts           # Permisos por rol
│   ├── useContentManagement.ts         # Moderación contenido
│   ├── useGamificationConfig.ts        # Config gamificación
│   ├── useSystemConfig.ts              # Config sistema
│   ├── useSettings.ts                  # Settings generales
│   ├── useMonitoring.ts                # Monitoreo
│   ├── useSystemMonitoring.ts          # Monitoreo avanzado
│   ├── useSystemMetrics.ts             # Métricas del sistema
│   ├── useAlerts.ts                    # Alertas
│   ├── useAnalytics.ts                 # Analytics
│   ├── useReports.ts                   # Reportes
│   ├── useProgress.ts                  # Progreso
│   ├── useClassroomTeacher.ts          # Asignaciones aulas
│   ├── useAuditLogs.ts                 # Logs de auditoría
│   └── index.ts
└── types/
    └── index.ts                # 50+ interfaces/types
```

#### Backend (apps/backend/src/modules/admin/)

```
admin/
├── admin.module.ts             # Módulo NestJS principal
├── index.ts                    # Barrel exports
├── controllers/                # 17 controllers
│   ├── admin-dashboard.controller.ts       # Dashboard general
│   ├── admin-users.controller.ts           # CRUD usuarios
│   ├── admin-organizations.controller.ts   # CRUD organizaciones
│   ├── admin-roles.controller.ts           # Gestión de roles
│   ├── admin-content.controller.ts         # Moderación contenido
│   ├── admin-gamification-config.controller.ts  # Config gamificación
│   ├── admin-system.controller.ts          # Config sistema
│   ├── admin-monitoring.controller.ts      # Monitoreo
│   ├── admin-alerts.controller.ts          # Alertas sistema
│   ├── admin-interventions.controller.ts   # Alertas intervención
│   ├── admin-analytics.controller.ts       # Analytics
│   ├── admin-reports.controller.ts         # Reportes
│   ├── admin-progress.controller.ts        # Progreso general
│   ├── admin-logs.controller.ts            # Audit logs
│   ├── admin-bulk-operations.controller.ts # Operaciones masivas
│   ├── classroom-assignments.controller.ts # Asignación aulas
│   └── classroom-teachers-rest.controller.ts
├── services/                   # 15 services
│   ├── admin-dashboard.service.ts
│   ├── admin-users.service.ts
│   ├── admin-organizations.service.ts
│   ├── admin-roles.service.ts
│   ├── admin-content.service.ts
│   ├── gamification-config.service.ts
│   ├── admin-system.service.ts
│   ├── admin-monitoring.service.ts
│   ├── admin-alerts.service.ts
│   ├── admin-interventions.service.ts
│   ├── admin-analytics.service.ts
│   ├── admin-reports.service.ts
│   ├── admin-progress.service.ts
│   ├── bulk-operations.service.ts
│   └── classroom-assignments.service.ts
├── dto/                        # Data Transfer Objects (15 categorías)
│   ├── dashboard/              # Dashboard DTOs
│   ├── users/                  # User management DTOs
│   ├── organizations/          # Organization DTOs
│   ├── roles/                  # Role management DTOs
│   ├── content/                # Content moderation DTOs
│   ├── gamification-config/    # Gamification config DTOs
│   ├── system/                 # System config DTOs
│   ├── monitoring/             # Monitoring DTOs
│   ├── alerts/                 # Alerts DTOs
│   ├── interventions/          # Intervention alerts DTOs
│   ├── analytics/              # Analytics DTOs
│   ├── reports/                # Reports DTOs
│   ├── progress/               # Progress tracking DTOs
│   ├── bulk-operations/        # Bulk operations DTOs
│   └── classroom-assignments/  # Classroom assignment DTOs
├── entities/                   # Entidades TypeORM
│   ├── system-setting.entity.ts
│   ├── feature-flag.entity.ts
│   ├── notification-settings.entity.ts
│   ├── bulk-operation.entity.ts
│   ├── system-alert.entity.ts
│   └── index.ts
├── guards/                     # Guards de autorización
│   └── admin.guard.ts
└── __tests__/                  # Tests unitarios
```

### 2.2 Diagrama de Dependencias

```
┌─────────────────────────────────────────────────────────────────┐
│                        FRONTEND                                  │
├─────────────────────────────────────────────────────────────────┤
│  Pages ──────► Components ──────► Hooks ──────► API Services    │
│                    │                   │                         │
│                    └───────────────────┼─────► Types             │
└────────────────────────────────────────┼─────────────────────────┘
                                         │
                                    HTTP/REST
                                         │
┌────────────────────────────────────────▼─────────────────────────┐
│                        BACKEND                                    │
├──────────────────────────────────────────────────────────────────┤
│  Controllers ──────► Services ──────► Repositories ──────► DB    │
│       │                  │                                       │
│       └──────────────────┼─────► Guards (AdminGuard)             │
│                          │                                       │
│                          └─────► External Modules                │
│                                  (Auth, Social, Educational,     │
│                                   Gamification, Progress, etc.)  │
└──────────────────────────────────────────────────────────────────┘
```

### 2.3 Flujo de Datos

```
┌──────────────┐
│  AdminPage   │ Renderiza la UI
└──────┬───────┘
       │ Usa
       ▼
┌──────────────┐
│  useAdminXXX │ Hook personalizado que maneja lógica
└──────┬───────┘
       │ Llama
       ▼
┌──────────────┐
│  adminAPI.ts │ Servicio API (axios)
└──────┬───────┘
       │ HTTP
       ▼
┌──────────────────┐
│  AdminController │ Backend NestJS
└──────┬───────────┘
       │ Usa
       ▼
┌──────────────────┐
│  AdminService    │ Lógica de negocio
└──────┬───────────┘
       │ Query
       ▼
┌──────────────────┐
│  TypeORM Repo    │ Acceso a base de datos
└──────┬───────────┘
       │
       ▼
┌──────────────────┐
│  PostgreSQL DB   │ Múltiples schemas (auth, social, educational, etc.)
└──────────────────┘
```

---

## 3. Módulos Principales

### 3.1 Dashboard Administrativo

**Propósito:** Vista general del estado del sistema y métricas clave.

**Componentes:**
- `AdminDashboardPage.tsx` - Página principal
- `AdminDashboardHero.tsx` - Hero con métricas principales
- `useAdminDashboard.ts` - Hook con auto-refresh

**Funcionalidades:**
- Estadísticas del sistema (usuarios, organizaciones, contenido)
- Salud del sistema (CPU, memoria, uptime)
- Alertas recientes
- Actividad de usuarios
- Acciones recientes de admins

**Endpoints principales:**
```typescript
GET /admin/dashboard              // Dashboard completo
GET /admin/dashboard/stats        // Estadísticas
GET /admin/dashboard/recent-activity
GET /admin/dashboard/user-stats
GET /admin/dashboard/organization-stats
GET /admin/dashboard/actions/recent
GET /admin/dashboard/alerts
GET /admin/dashboard/analytics/user-activity
```

**Ejemplo de uso:**
```typescript
// useAdminDashboard.ts
export function useAdminDashboard() {
  const {
    systemHealth,
    metrics,
    recentActions,
    alerts,
    userActivity,
    loading,
    error,
    refreshAll,
  } = useAdminDashboard();

  return {
    systemHealth,    // CPU, memory, uptime
    metrics,         // Total users, orgs, sessions
    recentActions,   // Últimas acciones de admins
    alerts,          // Alertas del sistema
    userActivity,    // Actividad de usuarios
    loading,
    error,
    refreshAll,
  };
}
```

### 3.2 Gestión de Usuarios

**Propósito:** CRUD completo de usuarios del sistema.

**Componentes:**
- `AdminUsersPage.tsx` - Lista y gestión de usuarios
- Componentes: filtros, tabla, modales de edición

**Funcionalidades:**
- Listar usuarios con filtros (rol, status, búsqueda)
- Crear nuevos usuarios
- Editar información de usuario
- Suspender/reactivar usuarios
- Eliminar usuarios (soft delete)
- Resetear contraseñas
- Ver detalles y estadísticas por usuario
- Operaciones masivas (bulk suspend, bulk delete, bulk role update)

**Endpoints principales:**
```typescript
GET    /admin/users                    // Lista paginada
GET    /admin/users/stats              // Estadísticas
GET    /admin/users/:id                // Detalles
PUT    /admin/users/:id                // Actualizar
DELETE /admin/users/:id                // Eliminar
POST   /admin/users/:id/suspend        // Suspender
POST   /admin/users/:id/activate       // Activar
POST   /admin/users/:id/reset-password // Reset password
POST   /admin/users/bulk/suspend       // Bulk suspend
POST   /admin/users/bulk/delete        // Bulk delete
POST   /admin/users/bulk/role          // Bulk role update
GET    /admin/users/bulk/:operationId  // Status operación
```

**DTOs clave:**
```typescript
// ListUsersDto
interface ListUsersDto {
  page?: number;
  limit?: number;
  role?: string;
  status?: 'active' | 'suspended' | 'inactive';
  search?: string;
  sortBy?: string;
  sortOrder?: 'ASC' | 'DESC';
}

// UpdateUserDto
interface UpdateUserDto {
  username?: string;
  email?: string;
  role?: string;
  status?: string;
  profile?: {
    first_name?: string;
    last_name?: string;
  };
}

// SuspendUserDto
interface SuspendUserDto {
  reason: string;
  duration_days?: number;
}
```

### 3.3 Gestión de Organizaciones

**Propósito:** Administrar tenants e instituciones educativas.

**Componentes:**
- `AdminInstitutionsPage.tsx` - Gestión de organizaciones

**Funcionalidades:**
- Listar organizaciones/tenants
- Crear nueva organización
- Editar información de organización
- Configurar suscripción (plan, features)
- Ver usuarios por organización
- Activar/desactivar features
- Ver estadísticas por organización

**Endpoints principales:**
```typescript
GET    /admin/organizations                 // Lista
POST   /admin/organizations                 // Crear
GET    /admin/organizations/:id             // Detalles
PUT    /admin/organizations/:id             // Actualizar
DELETE /admin/organizations/:id             // Eliminar
GET    /admin/organizations/:id/users       // Usuarios
GET    /admin/organizations/:id/stats       // Estadísticas
PATCH  /admin/organizations/:id/subscription // Actualizar suscripción
PATCH  /admin/organizations/:id/features    // Actualizar features
```

### 3.4 Configuración de Gamificación

**Propósito:** Configurar parámetros del sistema de gamificación.

**Componentes:**
- `AdminGamificationPage.tsx` - Configuración completa

**Funcionalidades:**
- Configurar parámetros de ML Coins (rewards, costs)
- Configurar rangos Maya (thresholds, nombres, colores)
- Configurar achievements (criterios, recompensas)
- Preview de impacto de cambios
- Historial de cambios de configuración

**Endpoints principales:**
```typescript
GET    /admin/gamification/settings          // Settings actuales
PATCH  /admin/gamification/settings          // Actualizar settings
GET    /admin/gamification/parameters        // Lista parámetros
PATCH  /admin/gamification/parameters/:id    // Actualizar parámetro
GET    /admin/gamification/maya-ranks        // Rangos Maya
PATCH  /admin/gamification/maya-ranks/:id    // Actualizar rango
POST   /admin/gamification/preview-impact    // Preview de cambios
```

**Parámetros configurables:**
```typescript
// Rewards
- exercise_completion_xp: number
- exercise_completion_coins: number
- daily_login_coins: number
- assignment_completion_bonus_xp: number

// Costs
- comodin_cost: number
- hint_cost: number
- retry_cost: number

// Maya Ranks
- ajaw_threshold: number
- kinich_threshold: number
- kukulkan_threshold: number
```

### 3.5 Moderación de Contenido

**Propósito:** Aprobar/rechazar contenido creado por teachers.

**Componentes:**
- `AdminContentPage.tsx` - Cola de moderación

**Funcionalidades:**
- Ver cola de contenido pendiente
- Aprobar contenido
- Rechazar contenido (con razón)
- Ver historial de aprobaciones
- Filtrar por tipo (ejercicios, módulos, media)
- Ver versiones de contenido

**Endpoints principales:**
```typescript
GET    /admin/content                    // Lista contenido
GET    /admin/content/pending            // Pendiente moderación
GET    /admin/content/:id                // Detalles
POST   /admin/content/:id/approve        // Aprobar
POST   /admin/content/:id/reject         // Rechazar
GET    /admin/content/:id/versions       // Versiones
POST   /admin/content/:id/versions       // Crear versión
GET    /admin/content/:id/approval-history // Historial
GET    /admin/media                      // Lista media files
```

### 3.6 Alertas del Sistema

**Propósito:** Gestionar alertas críticas y de intervención.

**Componentes:**
- `AdminAlertsPage.tsx` - Gestión de alertas

**Funcionalidades:**
- Ver alertas del sistema (critical, high, medium, low)
- Ver alertas de intervención estudiantil
- Crear alertas manuales
- Resolver/cerrar alertas
- Acknowledge alertas
- Filtrar por tipo, severidad, estado
- Ver estadísticas de alertas

**Endpoints principales:**
```typescript
// System Alerts
GET    /admin/alerts                    // Lista
POST   /admin/alerts                    // Crear
GET    /admin/alerts/stats              // Estadísticas
PATCH  /admin/alerts/:id/acknowledge    // Acknowledge
PATCH  /admin/alerts/:id/resolve        // Resolver

// Intervention Alerts (estudiantes en riesgo)
GET    /admin/interventions             // Lista
GET    /admin/interventions/:id         // Detalles
PATCH  /admin/interventions/:id/acknowledge
PATCH  /admin/interventions/:id/resolve
```

**Tipos de alertas:**
```typescript
// System Alerts
- high_error_rate
- database_connection
- high_memory_usage
- high_cpu_usage
- disk_space_low

// Intervention Alerts
- declining_trend        // Estudiante con tendencia decreciente
- low_engagement         // Baja participación
- failing_exercises      // Fallos repetidos
- no_activity            // Sin actividad reciente
```

### 3.7 Monitoreo del Sistema

**Propósito:** Monitorear salud y performance del sistema.

**Componentes:**
- `AdminMonitoringPage.tsx` - Dashboard de monitoreo

**Funcionalidades:**
- Salud del sistema (health check)
- Métricas en tiempo real (CPU, memoria, uptime)
- Logs de errores recientes
- Tendencias de errores
- Historial de métricas
- Performance de endpoints

**Endpoints principales:**
```typescript
GET /admin/monitoring/health            // Health check
GET /admin/monitoring/metrics           // Métricas actuales
GET /admin/monitoring/metrics/history   // Historial
GET /admin/monitoring/errors/recent     // Errores recientes
GET /admin/monitoring/errors/stats      // Estadísticas errores
GET /admin/monitoring/errors/trends     // Tendencias
```

### 3.8 Analytics y Reportes

**Propósito:** Dashboards analytics y generación de reportes.

**Componentes:**
- `AdminAnalyticsPage.tsx` - Analytics avanzados
- `AdminReportsPage.tsx` - Generación de reportes

**Funcionalidades Analytics:**
- Overview general
- Engagement analytics
- Retention analytics
- Gamification analytics
- Activity timeline
- Top users
- Exportar datos

**Funcionalidades Reportes:**
- Generar reportes en PDF/Excel
- Reportes predefinidos (usuarios, organizaciones, contenido)
- Reportes personalizados
- Programar reportes recurrentes

**Endpoints Analytics:**
```typescript
GET /admin/analytics/overview
GET /admin/analytics/engagement
GET /admin/analytics/retention
GET /admin/analytics/gamification
GET /admin/analytics/activity-timeline
GET /admin/analytics/top-users
POST /admin/analytics/export
```

**Endpoints Reportes:**
```typescript
GET  /admin/reports                    // Lista reportes
POST /admin/reports/generate           // Generar reporte
GET  /admin/reports/:id                // Descargar reporte
GET  /admin/reports/templates          // Templates disponibles
```

### 3.9 Configuración del Sistema

**Propósito:** Configuración global del sistema.

**Componentes:**
- `AdminSettingsPage.tsx` - Settings generales
- `AdminAdvancedPage.tsx` - Configuración avanzada

**Funcionalidades:**
- Configurar system settings (globales)
- Feature flags (habilitar/deshabilitar features)
- Notification settings
- Modo mantenimiento
- Limpiar cache
- Ejecutar tareas de mantenimiento
- Ver audit logs

**Endpoints principales:**
```typescript
GET    /admin/system/config              // Config actual
PATCH  /admin/system/config              // Actualizar config
GET    /admin/system/health              // Salud sistema
POST   /admin/system/maintenance/toggle  // Toggle mantenimiento
POST   /admin/system/maintenance/clear-cache
POST   /admin/system/maintenance/rebuild-indexes
GET    /admin/logs                       // Audit logs
```

### 3.10 Gestión de Roles y Permisos

**Propósito:** Configurar permisos por rol.

**Componentes:**
- `AdminRolesPage.tsx` - Gestión de roles

**Funcionalidades:**
- Listar roles
- Ver permisos por rol
- Actualizar permisos de un rol
- Crear roles personalizados (futuro)

**Endpoints principales:**
```typescript
GET   /admin/roles                  // Lista roles
GET   /admin/roles/:id              // Detalles rol
GET   /admin/roles/:id/permissions  // Permisos del rol
PATCH /admin/roles/:id/permissions  // Actualizar permisos
```

### 3.11 Asignación de Aulas

**Propósito:** Asignar teachers a classrooms.

**Componentes:**
- `AdminClassroomTeacherPage.tsx` - Gestión de asignaciones

**Funcionalidades:**
- Listar todas las asignaciones
- Asignar teacher a classroom
- Reasignar classroom a otro teacher
- Remover asignación
- Bulk assign (múltiples classrooms)
- Ver teachers disponibles
- Ver classrooms sin asignar

**Endpoints principales:**
```typescript
GET    /admin/classroom-assignments           // Lista todas
GET    /admin/classroom-assignments/teachers/:teacherId
GET    /admin/classroom-assignments/classrooms/:classroomId
POST   /admin/classroom-assignments/assign    // Asignar
POST   /admin/classroom-assignments/bulk-assign
PATCH  /admin/classroom-assignments/:id/reassign
DELETE /admin/classroom-assignments/:id       // Remover

// REST endpoints alternativos
GET    /admin/classrooms/:classroomId/teachers
POST   /admin/classrooms/:classroomId/teachers
DELETE /admin/classrooms/:classroomId/teachers/:teacherId
```

### 3.12 Progreso General

**Propósito:** Vista global del progreso de todos los usuarios.

**Componentes:**
- `AdminProgressPage.tsx` - Dashboard de progreso

**Funcionalidades:**
- Overview de progreso global
- Progreso por estudiante
- Progreso por classroom
- Progreso por módulo
- Logros más comunes
- Submissions recientes
- Exportar datos de progreso

**Endpoints principales:**
```typescript
GET /admin/progress/overview
GET /admin/progress/students
GET /admin/progress/classrooms
GET /admin/progress/modules
GET /admin/progress/export
```

---

## 4. Patrones de Diseño

### 4.1 Frontend Patterns

#### 4.1.1 Page + Hook Pattern

Cada página tiene un hook correspondiente que encapsula la lógica:

```typescript
// Pattern: Page con Hook dedicado

// AdminUsersPage.tsx
export default function AdminUsersPage() {
  const {
    users,
    stats,
    loading,
    error,
    filters,
    setFilters,
    createUser,
    updateUser,
    deleteUser,
    suspendUser,
  } = useUserManagement();

  if (loading) return <LoadingSpinner />;
  if (error) return <ErrorDisplay error={error} />;

  return (
    <AdminLayout>
      <UserFilters filters={filters} onChange={setFilters} />
      <UserStats stats={stats} />
      <UserTable
        users={users}
        onEdit={updateUser}
        onDelete={deleteUser}
        onSuspend={suspendUser}
      />
    </AdminLayout>
  );
}

// useUserManagement.ts
export function useUserManagement() {
  const [filters, setFilters] = useState<UserFilters>({});

  const { data: users, isLoading } = useQuery({
    queryKey: ['admin', 'users', filters],
    queryFn: () => adminAPI.listUsers(filters),
  });

  const { data: stats } = useQuery({
    queryKey: ['admin', 'users', 'stats'],
    queryFn: () => adminAPI.getUserStats(),
  });

  const { mutate: createUser } = useMutation({
    mutationFn: adminAPI.createUser,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });
    },
  });

  // ... más mutations

  return {
    users,
    stats,
    loading: isLoading,
    filters,
    setFilters,
    createUser,
    updateUser,
    deleteUser,
    suspendUser,
  };
}
```

#### 4.1.2 Auto-Refresh Pattern

Para datos que requieren actualización frecuente:

```typescript
// Pattern: Auto-refresh con control manual

export function useAdminDashboard(customIntervals?: RefreshIntervals) {
  const [isPaused, setIsPaused] = useState(false);

  // Fetch functions
  const fetchHealth = useCallback(async () => {
    const data = await adminAPI.getSystemHealth();
    setHealth(data);
  }, []);

  // Auto-refresh intervals
  useEffect(() => {
    if (isPaused) return;

    const healthInterval = setInterval(fetchHealth, 10000);
    const metricsInterval = setInterval(fetchMetrics, 30000);

    return () => {
      clearInterval(healthInterval);
      clearInterval(metricsInterval);
    };
  }, [isPaused, fetchHealth, fetchMetrics]);

  return {
    health,
    metrics,
    pauseRefresh: () => setIsPaused(true),
    resumeRefresh: () => setIsPaused(false),
    isPaused,
  };
}
```

#### 4.1.3 Bulk Operations Pattern

Para operaciones masivas con feedback de progreso:

```typescript
// Pattern: Bulk operations con progress tracking

export function useBulkOperations() {
  const [operation, setOperation] = useState<BulkOperation | null>(null);

  const { mutate: bulkSuspend } = useMutation({
    mutationFn: async (userIds: string[]) => {
      const result = await adminAPI.bulkSuspendUsers({
        user_ids: userIds,
        reason: 'Admin bulk suspend',
      });

      // Poll operation status
      return pollOperationStatus(result.operation_id);
    },
    onSuccess: (operation) => {
      setOperation(operation);
      queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });
    },
  });

  // Poll para status updates
  const pollOperationStatus = async (operationId: string) => {
    let status = await adminAPI.getBulkOperationStatus(operationId);

    while (status.status === 'in_progress') {
      await new Promise(resolve => setTimeout(resolve, 2000));
      status = await adminAPI.getBulkOperationStatus(operationId);
    }

    return status;
  };

  return {
    bulkSuspend,
    bulkDelete,
    bulkUpdateRole,
    operation,
  };
}
```

#### 4.1.4 Modal Pattern

Modales para operaciones complejas:

```typescript
// Pattern: Modal con confirmación

interface ConfirmDeleteModalProps {
  isOpen: boolean;
  onClose: () => void;
  user: User;
  onConfirm: (userId: string) => void;
}

export const ConfirmDeleteModal: React.FC<ConfirmDeleteModalProps> = ({
  isOpen,
  onClose,
  user,
  onConfirm,
}) => {
  const [confirmText, setConfirmText] = useState('');
  const canDelete = confirmText === user.username;

  return (
    <Modal isOpen={isOpen} onClose={onClose}>
      <div className="p-6">
        <h2>Confirmar eliminación</h2>
        <p>Para eliminar al usuario {user.username}, escribe su nombre:</p>

        <input
          value={confirmText}
          onChange={(e) => setConfirmText(e.target.value)}
          placeholder="Nombre de usuario"
        />

        <div className="flex gap-2">
          <Button variant="secondary" onClick={onClose}>
            Cancelar
          </Button>
          <Button
            variant="danger"
            onClick={() => onConfirm(user.id)}
            disabled={!canDelete}
          >
            Eliminar
          </Button>
        </div>
      </div>
    </Modal>
  );
};
```

### 4.2 Backend Patterns

#### 4.2.1 Guard-Based Authorization

```typescript
// Pattern: AdminGuard para proteger rutas

@Controller('admin')
@UseGuards(JwtAuthGuard, AdminGuard)  // Requiere autenticación + rol admin
@ApiTags('Admin')
export class AdminUsersController {

  @Get('users')
  async listUsers(@Query() query: ListUsersDto): Promise<PaginatedUsersDto> {
    return this.adminUsersService.listUsers(query);
  }
}
```

#### 4.2.2 AdminGuard Implementation

```typescript
// guards/admin.guard.ts
@Injectable()
export class AdminGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest();
    const user = request.user;

    if (!user) {
      throw new ForbiddenException('User not authenticated');
    }

    // Verificar rol admin o super_admin
    const isAdmin = user.role === 'admin' || user.role === 'super_admin';

    if (!isAdmin) {
      throw new ForbiddenException('Access denied. Admin privileges required.');
    }

    return true;
  }
}
```

#### 4.2.3 Service Layer with Pagination

```typescript
// Pattern: Service con paginación y filtros

@Injectable()
export class AdminUsersService {
  constructor(
    @InjectRepository(User, 'auth')
    private userRepo: Repository<User>,
  ) {}

  async listUsers(query: ListUsersDto): Promise<PaginatedUsersDto> {
    const { page = 1, limit = 20, role, status, search, sortBy = 'created_at', sortOrder = 'DESC' } = query;

    const qb = this.userRepo.createQueryBuilder('user')
      .leftJoinAndSelect('user.profile', 'profile')
      .leftJoinAndSelect('user.roles', 'userRoles')
      .leftJoinAndSelect('userRoles.role', 'role');

    // Aplicar filtros
    if (role) {
      qb.andWhere('role.name = :role', { role });
    }

    if (status) {
      qb.andWhere('user.status = :status', { status });
    }

    if (search) {
      qb.andWhere(
        '(user.username ILIKE :search OR user.email ILIKE :search OR profile.first_name ILIKE :search OR profile.last_name ILIKE :search)',
        { search: `%${search}%` }
      );
    }

    // Sorting
    qb.orderBy(`user.${sortBy}`, sortOrder);

    // Paginación
    const skip = (page - 1) * limit;
    qb.skip(skip).take(limit);

    const [users, total] = await qb.getManyAndCount();

    return {
      data: users,
      meta: {
        total,
        page,
        limit,
        totalPages: Math.ceil(total / limit),
      },
    };
  }
}
```

#### 4.2.4 Bulk Operations Pattern

```typescript
// Pattern: Operaciones masivas con tracking

@Injectable()
export class BulkOperationsService {
  constructor(
    @InjectRepository(BulkOperation, 'auth')
    private bulkOpRepo: Repository<BulkOperation>,
    @InjectRepository(User, 'auth')
    private userRepo: Repository<User>,
  ) {}

  async bulkSuspendUsers(dto: BulkSuspendUsersDto): Promise<BulkOperationStatusDto> {
    // Crear registro de operación
    const operation = this.bulkOpRepo.create({
      operation_type: 'suspend_users',
      target_count: dto.user_ids.length,
      status: 'in_progress',
      initiated_by: dto.admin_id,
    });
    await this.bulkOpRepo.save(operation);

    // Ejecutar operación en background
    this.executeBulkSuspend(operation.id, dto).catch(err => {
      this.logger.error(`Bulk suspend failed: ${err.message}`);
    });

    return {
      operation_id: operation.id,
      status: 'in_progress',
      total: dto.user_ids.length,
      completed: 0,
      failed: 0,
    };
  }

  private async executeBulkSuspend(operationId: string, dto: BulkSuspendUsersDto): Promise<void> {
    const operation = await this.bulkOpRepo.findOne({ where: { id: operationId } });
    let completed = 0;
    let failed = 0;

    for (const userId of dto.user_ids) {
      try {
        await this.userRepo.update(userId, { status: 'suspended' });
        completed++;
      } catch (error) {
        failed++;
      }

      // Actualizar progreso
      operation.completed_count = completed;
      operation.failed_count = failed;
      await this.bulkOpRepo.save(operation);
    }

    // Marcar como completado
    operation.status = 'completed';
    operation.completed_at = new Date();
    await this.bulkOpRepo.save(operation);
  }
}
```

#### 4.2.5 Audit Logging Pattern

```typescript
// Pattern: Audit logging automático

@Injectable()
export class AdminUsersService {
  constructor(
    @InjectRepository(User, 'auth')
    private userRepo: Repository<User>,
    @Inject(CACHE_MANAGER) private cacheManager: Cache,
    private auditLogService: AuditLogService,
  ) {}

  async updateUser(userId: string, dto: UpdateUserDto, adminId: string): Promise<User> {
    const user = await this.userRepo.findOne({ where: { id: userId } });

    if (!user) {
      throw new NotFoundException('User not found');
    }

    // Guardar estado anterior para audit
    const previousState = { ...user };

    // Actualizar
    Object.assign(user, dto);
    await this.userRepo.save(user);

    // Log de auditoría
    await this.auditLogService.log({
      event_type: 'user_updated',
      actor_id: adminId,
      target_id: userId,
      target_type: 'user',
      changes: {
        before: previousState,
        after: user,
      },
      metadata: {
        updated_fields: Object.keys(dto),
      },
    });

    return user;
  }
}
```

---

## 5. Rutas y Navegación

### 5.1 Rutas Frontend

```typescript
// Estructura de rutas del portal admin
const adminRoutes = [
  {
    path: '/admin',
    element: <AdminLayout />,
    children: [
      { path: '', element: <AdminDashboardPage /> },
      { path: 'dashboard', element: <AdminDashboardPage /> },

      // Gestión
      { path: 'users', element: <AdminUsersPage /> },
      { path: 'institutions', element: <AdminInstitutionsPage /> },
      { path: 'roles', element: <AdminRolesPage /> },

      // Contenido
      { path: 'content', element: <AdminContentPage /> },
      { path: 'classroom-teacher', element: <AdminClassroomTeacherPage /> },

      // Configuración
      { path: 'gamification', element: <AdminGamificationPage /> },
      { path: 'settings', element: <AdminSettingsPage /> },
      { path: 'advanced', element: <AdminAdvancedPage /> },

      // Monitoreo
      { path: 'monitoring', element: <AdminMonitoringPage /> },
      { path: 'alerts', element: <AdminAlertsPage /> },

      // Analytics
      { path: 'analytics', element: <AdminAnalyticsPage /> },
      { path: 'reports', element: <AdminReportsPage /> },
      { path: 'progress', element: <AdminProgressPage /> },
    ],
  },
];
```

### 5.2 Navegación Lateral

```typescript
// Sidebar navigation items
const navigationItems = [
  {
    label: 'Dashboard',
    icon: <LayoutDashboard />,
    path: '/admin/dashboard',
  },
  {
    label: 'Gestión',
    icon: <Users />,
    children: [
      { label: 'Usuarios', path: '/admin/users' },
      { label: 'Instituciones', path: '/admin/institutions' },
      { label: 'Roles', path: '/admin/roles' },
    ],
  },
  {
    label: 'Contenido',
    icon: <BookOpen />,
    children: [
      { label: 'Moderación', path: '/admin/content' },
      { label: 'Asignación Aulas', path: '/admin/classroom-teacher' },
    ],
  },
  {
    label: 'Configuración',
    icon: <Settings />,
    children: [
      { label: 'Gamificación', path: '/admin/gamification' },
      { label: 'Sistema', path: '/admin/settings' },
      { label: 'Avanzado', path: '/admin/advanced' },
    ],
  },
  {
    label: 'Monitoreo',
    icon: <Activity />,
    children: [
      { label: 'Sistema', path: '/admin/monitoring' },
      { label: 'Alertas', path: '/admin/alerts' },
    ],
  },
  {
    label: 'Analytics',
    icon: <BarChart />,
    children: [
      { label: 'Estadísticas', path: '/admin/analytics' },
      { label: 'Reportes', path: '/admin/reports' },
      { label: 'Progreso', path: '/admin/progress' },
    ],
  },
];
```

---

## 6. APIs del Portal Admin

### 6.1 Tabla Resumen de Endpoints

| Categoría | Método | Endpoint | Descripción | Guard |
|-----------|--------|----------|-------------|-------|
| **Dashboard** | GET | `/admin/dashboard` | Dashboard completo | AdminGuard |
| | GET | `/admin/dashboard/stats` | Estadísticas | AdminGuard |
| | GET | `/admin/dashboard/recent-activity` | Actividad reciente | AdminGuard |
| | GET | `/admin/dashboard/actions/recent` | Acciones de admins | AdminGuard |
| | GET | `/admin/dashboard/alerts` | Alertas | AdminGuard |
| **Users** | GET | `/admin/users` | Lista de usuarios | AdminGuard |
| | GET | `/admin/users/stats` | Estadísticas usuarios | AdminGuard |
| | GET | `/admin/users/:id` | Detalles usuario | AdminGuard |
| | PUT | `/admin/users/:id` | Actualizar usuario | AdminGuard |
| | DELETE | `/admin/users/:id` | Eliminar usuario | AdminGuard |
| | POST | `/admin/users/:id/suspend` | Suspender usuario | AdminGuard |
| | POST | `/admin/users/:id/activate` | Activar usuario | AdminGuard |
| | POST | `/admin/users/bulk/suspend` | Suspender múltiples | AdminGuard |
| | POST | `/admin/users/bulk/delete` | Eliminar múltiples | AdminGuard |
| **Organizations** | GET | `/admin/organizations` | Lista organizaciones | AdminGuard |
| | POST | `/admin/organizations` | Crear organización | AdminGuard |
| | GET | `/admin/organizations/:id` | Detalles organización | AdminGuard |
| | PUT | `/admin/organizations/:id` | Actualizar organización | AdminGuard |
| | PATCH | `/admin/organizations/:id/subscription` | Actualizar suscripción | AdminGuard |
| **Roles** | GET | `/admin/roles` | Lista de roles | AdminGuard |
| | GET | `/admin/roles/:id/permissions` | Permisos del rol | AdminGuard |
| | PATCH | `/admin/roles/:id/permissions` | Actualizar permisos | AdminGuard |
| **Content** | GET | `/admin/content` | Lista contenido | AdminGuard |
| | GET | `/admin/content/pending` | Pendiente moderación | AdminGuard |
| | POST | `/admin/content/:id/approve` | Aprobar contenido | AdminGuard |
| | POST | `/admin/content/:id/reject` | Rechazar contenido | AdminGuard |
| **Gamification** | GET | `/admin/gamification/settings` | Config gamificación | AdminGuard |
| | PATCH | `/admin/gamification/settings` | Actualizar config | AdminGuard |
| | GET | `/admin/gamification/parameters` | Parámetros | AdminGuard |
| | PATCH | `/admin/gamification/parameters/:id` | Actualizar parámetro | AdminGuard |
| **System** | GET | `/admin/system/config` | Config sistema | AdminGuard |
| | PATCH | `/admin/system/config` | Actualizar config | AdminGuard |
| | GET | `/admin/system/health` | Salud del sistema | AdminGuard |
| | POST | `/admin/system/maintenance/toggle` | Toggle mantenimiento | AdminGuard |
| **Monitoring** | GET | `/admin/monitoring/health` | Health check | AdminGuard |
| | GET | `/admin/monitoring/metrics` | Métricas actuales | AdminGuard |
| | GET | `/admin/monitoring/errors/recent` | Errores recientes | AdminGuard |
| **Alerts** | GET | `/admin/alerts` | Lista alertas | AdminGuard |
| | POST | `/admin/alerts` | Crear alerta | AdminGuard |
| | PATCH | `/admin/alerts/:id/acknowledge` | Acknowledge | AdminGuard |
| | PATCH | `/admin/alerts/:id/resolve` | Resolver | AdminGuard |
| **Analytics** | GET | `/admin/analytics/overview` | Overview | AdminGuard |
| | GET | `/admin/analytics/engagement` | Engagement | AdminGuard |
| | GET | `/admin/analytics/retention` | Retention | AdminGuard |
| | POST | `/admin/analytics/export` | Exportar datos | AdminGuard |
| **Reports** | GET | `/admin/reports` | Lista reportes | AdminGuard |
| | POST | `/admin/reports/generate` | Generar reporte | AdminGuard |
| **Progress** | GET | `/admin/progress/overview` | Overview progreso | AdminGuard |
| | GET | `/admin/progress/students` | Progreso estudiantes | AdminGuard |
| | GET | `/admin/progress/export` | Exportar progreso | AdminGuard |
| **Classroom** | GET | `/admin/classroom-assignments` | Lista asignaciones | AdminGuard |
| | POST | `/admin/classroom-assignments/assign` | Asignar | AdminGuard |
| | POST | `/admin/classroom-assignments/bulk-assign` | Bulk assign | AdminGuard |
| **Logs** | GET | `/admin/logs` | Audit logs | AdminGuard |

### 6.2 Frontend API Services

```
services/api/admin/
├── adminAPI.ts                     # Main admin API (dashboard, general)
├── adminUsersAPI.ts                # User management
├── adminOrganizationsAPI.ts        # Organizations management
├── adminRolesAPI.ts                # Roles and permissions
├── adminContentAPI.ts              # Content moderation
├── adminGamificationAPI.ts         # Gamification config
├── adminSystemAPI.ts               # System configuration
├── adminMonitoringAPI.ts           # System monitoring
├── adminAlertsAPI.ts               # Alerts management
├── adminAnalyticsAPI.ts            # Analytics
├── adminReportsAPI.ts              # Reports generation
├── adminProgressAPI.ts             # Progress tracking
├── adminClassroomAPI.ts            # Classroom assignments
├── adminLogsAPI.ts                 # Audit logs
└── index.ts                        # Barrel export
```

---

## 7. Estado y Stores

### 7.1 Zustand Stores (Opcional)

El portal admin usa principalmente React Query para state management, pero puede usar Zustand para estado global:

```typescript
// stores/adminStore.ts
interface AdminState {
  // Global admin state
  selectedOrganization: Organization | null;
  maintenanceMode: boolean;

  // Actions
  setSelectedOrganization: (org: Organization | null) => void;
  setMaintenanceMode: (mode: boolean) => void;
}

export const useAdminStore = create<AdminState>((set) => ({
  selectedOrganization: null,
  maintenanceMode: false,

  setSelectedOrganization: (org) => set({ selectedOrganization: org }),
  setMaintenanceMode: (mode) => set({ maintenanceMode: mode }),
}));
```

### 7.2 React Query Cache

```typescript
// Configuración de React Query para admin
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 5 * 60 * 1000, // 5 minutos
      cacheTime: 10 * 60 * 1000, // 10 minutos
      refetchOnWindowFocus: true,
      retry: 1,
    },
  },
});

// Query keys structure
const adminQueryKeys = {
  all: ['admin'] as const,

  dashboard: () => [...adminQueryKeys.all, 'dashboard'] as const,
  dashboardStats: () => [...adminQueryKeys.dashboard(), 'stats'] as const,

  users: () => [...adminQueryKeys.all, 'users'] as const,
  usersList: (filters: UserFilters) => [...adminQueryKeys.users(), 'list', filters] as const,
  usersStats: () => [...adminQueryKeys.users(), 'stats'] as const,

  organizations: () => [...adminQueryKeys.all, 'organizations'] as const,
  organizationsList: () => [...adminQueryKeys.organizations(), 'list'] as const,

  monitoring: () => [...adminQueryKeys.all, 'monitoring'] as const,
  monitoringHealth: () => [...adminQueryKeys.monitoring(), 'health'] as const,
  monitoringMetrics: () => [...adminQueryKeys.monitoring(), 'metrics'] as const,
};
```

---

## 8. Seguridad

### 8.1 Autorización

1. **JwtAuthGuard:** Verifica token JWT válido
2. **AdminGuard:** Verifica rol admin/super_admin

### 8.2 Reglas de Acceso

```yaml
Admin puede:
  - Ver todos los usuarios del sistema
  - Crear/editar/eliminar usuarios
  - Suspender/reactivar usuarios
  - Gestionar organizaciones
  - Moderar contenido
  - Configurar gamificación
  - Ver audit logs completos
  - Ejecutar bulk operations
  - Configurar sistema
  - Ver todas las métricas

Admin NO puede:
  - Modificar datos de super_admin (solo super_admin puede)
  - Eliminar su propia cuenta
  - Desactivar modo mantenimiento si no lo activó
```

### 8.3 Audit Logging

Todas las acciones de admin se registran:

```typescript
// Eventos auditados
const AUDIT_EVENTS = {
  USER_CREATED: 'user_created',
  USER_UPDATED: 'user_updated',
  USER_DELETED: 'user_deleted',
  USER_SUSPENDED: 'user_suspended',
  ORG_CREATED: 'organization_created',
  ORG_UPDATED: 'organization_updated',
  CONTENT_APPROVED: 'content_approved',
  CONTENT_REJECTED: 'content_rejected',
  CONFIG_UPDATED: 'config_updated',
  MAINTENANCE_TOGGLED: 'maintenance_toggled',
  BULK_OPERATION: 'bulk_operation',
};
```

### 8.4 Rate Limiting

Endpoints de admin tienen rate limiting más permisivo:

```typescript
// Rate limits por rol
const RATE_LIMITS = {
  admin: {
    windowMs: 15 * 60 * 1000, // 15 minutos
    maxRequests: 1000,         // 1000 requests
  },
  default: {
    windowMs: 15 * 60 * 1000,
    maxRequests: 100,
  },
};
```

---

## 9. Flujos Principales

### 9.1 Flujo: Crear Usuario

```
1. Admin navega a /admin/users
2. Click en "Nuevo Usuario"
3. Modal de creación se abre
4. Admin completa form:
   - Username
   - Email
   - Password
   - Role
   - Profile info
5. Submit → POST /admin/users
6. Backend valida datos
7. Backend crea usuario en DB
8. Backend registra audit log
9. Backend retorna usuario creado
10. Frontend actualiza lista (invalidate query)
11. Modal se cierra
12. Toast de éxito
```

### 9.2 Flujo: Suspender Usuario

```
1. Admin ve lista de usuarios
2. Selecciona usuario problemático
3. Click "Suspender"
4. Modal de confirmación:
   - Razón (requerido)
   - Duración (opcional)
5. Confirm → POST /admin/users/:id/suspend
6. Backend suspende usuario
7. Backend registra audit log
8. Backend envía notificación al usuario
9. Frontend actualiza UI
10. Toast de confirmación
```

### 9.3 Flujo: Aprobar Contenido

```
1. Admin navega a /admin/content
2. Ve lista de contenido pendiente
3. Click en item para ver detalles
4. Revisa contenido:
   - Preview del ejercicio
   - Metadata
   - Author
5. Decisión:
   a) Aprobar → POST /admin/content/:id/approve
      - Contenido pasa a published
      - Creator recibe notificación
   b) Rechazar → POST /admin/content/:id/reject
      - Modal para razón
      - Contenido pasa a rejected
      - Creator recibe notificación con feedback
6. Frontend actualiza cola de moderación
```

### 9.4 Flujo: Configurar Gamificación

```
1. Admin navega a /admin/gamification
2. Ve config actual de parámetros
3. Modifica valores:
   - ML Coins por ejercicio
   - XP por logro
   - Costos de comodines
4. Click "Preview Impact"
   → POST /admin/gamification/preview-impact
   - Backend simula impacto en usuarios
   - Muestra estadísticas proyectadas
5. Admin revisa preview
6. Confirm → PATCH /admin/gamification/settings
7. Backend actualiza config
8. Backend registra audit log
9. Config nueva aplica a partir de ahora
10. Toast de éxito con resumen de cambios
```

### 9.5 Flujo: Operación Masiva (Bulk Suspend)

```
1. Admin selecciona múltiples usuarios (checkboxes)
2. Click "Suspender seleccionados"
3. Modal de confirmación:
   - Lista de usuarios
   - Razón global
   - Duración
4. Confirm → POST /admin/users/bulk/suspend
5. Backend:
   - Crea BulkOperation record
   - Retorna operation_id inmediatamente
   - Ejecuta suspensión en background
6. Frontend:
   - Muestra progress modal
   - Poll GET /admin/users/bulk/:operationId cada 2s
7. Backend actualiza progreso:
   - completed_count incrementa
   - failed_count si hay errores
8. Al completar:
   - Frontend muestra resumen
   - Invalidate users query
   - Cierra modal después de 3s
```

### 9.6 Flujo: Modo Mantenimiento

```
1. Admin navega a /admin/settings
2. Toggle "Maintenance Mode"
3. Modal de confirmación:
   - Mensaje personalizado para usuarios
   - Duración estimada
4. Confirm → POST /admin/system/maintenance/toggle
5. Backend:
   - Actualiza system_settings
   - Broadcast WebSocket a todos los usuarios
6. Frontend (todos los portales):
   - Reciben notificación
   - Muestran banner de mantenimiento
   - Bloquean acciones críticas
7. Admin puede seguir usando el portal
8. Para desactivar:
   - Admin toggle OFF
   - Backend notifica a todos
   - Sistema vuelve a normal
```

---

## 10. Testing

### 10.1 Tests Unitarios Backend

```typescript
// admin-users.controller.spec.ts
describe('AdminUsersController', () => {
  let controller: AdminUsersController;
  let service: AdminUsersService;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      controllers: [AdminUsersController],
      providers: [
        { provide: AdminUsersService, useValue: mockService },
      ],
    }).compile();

    controller = module.get(AdminUsersController);
    service = module.get(AdminUsersService);
  });

  it('should list users with pagination', async () => {
    const query: ListUsersDto = { page: 1, limit: 20 };
    mockService.listUsers.mockResolvedValue(mockPaginatedUsers);

    const result = await controller.listUsers(query);

    expect(result.data).toHaveLength(20);
    expect(result.meta.total).toBe(100);
    expect(mockService.listUsers).toHaveBeenCalledWith(query);
  });

  it('should suspend user', async () => {
    const userId = 'user-123';
    const dto: SuspendUserDto = { reason: 'Violation', duration_days: 7 };

    await controller.suspendUser(userId, dto);

    expect(mockService.suspendUser).toHaveBeenCalledWith(userId, dto);
  });
});
```

### 10.2 Tests Frontend

```typescript
// useUserManagement.test.ts
describe('useUserManagement', () => {
  it('should fetch users list', async () => {
    const { result } = renderHook(() => useUserManagement(), {
      wrapper: QueryClientProvider,
    });

    await waitFor(() => {
      expect(result.current.loading).toBe(false);
    });

    expect(result.current.users).toBeDefined();
    expect(result.current.users.length).toBeGreaterThan(0);
  });

  it('should suspend user', async () => {
    const { result } = renderHook(() => useUserManagement(), {
      wrapper: QueryClientProvider,
    });

    await act(async () => {
      await result.current.suspendUser('user-123', {
        reason: 'Test suspension',
      });
    });

    await waitFor(() => {
      expect(mockAPI.suspendUser).toHaveBeenCalled();
    });
  });
});
```

### 10.3 E2E Tests

```typescript
// admin-users.e2e.spec.ts
describe('Admin Users Management (e2e)', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const moduleFixture = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    await app.init();
  });

  it('/admin/users (GET) - should require admin role', () => {
    return request(app.getHttpServer())
      .get('/admin/users')
      .set('Authorization', `Bearer ${studentToken}`)
      .expect(403);
  });

  it('/admin/users (GET) - should return users for admin', () => {
    return request(app.getHttpServer())
      .get('/admin/users')
      .set('Authorization', `Bearer ${adminToken}`)
      .expect(200)
      .expect((res) => {
        expect(res.body.data).toBeDefined();
        expect(res.body.meta).toBeDefined();
      });
  });
});
```

---

## 11. Buenas Prácticas

### 11.1 Frontend

```typescript
// DO: Hooks específicos por funcionalidad
export function useUserManagement() { ... }
export function useOrganizations() { ... }
export function useBulkOperations() { ... }

// DON'T: Un hook gigante
export function useAdmin() { ... } // Evitar

// DO: Query keys jerárquicas y descriptivas
const queryKey = ['admin', 'users', 'list', { role: 'teacher', page: 1 }];

// DO: Invalidar queries relacionadas
const { mutate } = useMutation({
  mutationFn: createUser,
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });
    queryClient.invalidateQueries({ queryKey: ['admin', 'dashboard', 'stats'] });
  },
});

// DO: Error boundaries para secciones críticas
<ErrorBoundary fallback={<ErrorDisplay />}>
  <AdminUsersPage />
</ErrorBoundary>
```

### 11.2 Backend

```typescript
// DO: DTOs con validación completa
export class CreateUserDto {
  @IsString()
  @MinLength(3)
  @MaxLength(50)
  username!: string;

  @IsEmail()
  email!: string;

  @IsString()
  @MinLength(8)
  @Matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/)
  password!: string;
}

// DO: Logging completo en servicios admin
@Injectable()
export class AdminUsersService {
  private readonly logger = new Logger(AdminUsersService.name);

  async suspendUser(userId: string, dto: SuspendUserDto): Promise<void> {
    this.logger.log(`Suspending user ${userId}: ${dto.reason}`);

    try {
      await this.userRepo.update(userId, { status: 'suspended' });
      await this.auditLogService.log({ ... });
    } catch (error) {
      this.logger.error(`Failed to suspend user ${userId}: ${error.message}`);
      throw new InternalServerErrorException('Failed to suspend user');
    }
  }
}

// DO: Transacciones para operaciones críticas
async createOrganization(dto: CreateOrganizationDto): Promise<Organization> {
  return this.dataSource.transaction(async (manager) => {
    const org = await manager.save(Organization, dto);
    await manager.save(Tenant, { organization_id: org.id });
    await manager.save(FeatureFlag, { tenant_id: tenant.id });
    return org;
  });
}
```

---

## 12. Troubleshooting

### 12.1 Problemas Comunes

| Problema | Causa | Solución |
|----------|-------|----------|
| 403 Forbidden | AdminGuard rechaza | Verificar rol del usuario (admin/super_admin) |
| Bulk operation timeout | Operación muy larga | Usar background jobs, no esperar respuesta |
| Dashboard lento | Queries N+1 | Usar eager loading en TypeORM |
| Métricas desactualizadas | Cache | Invalidar cache manualmente o reducir TTL |
| Audit logs faltantes | Error en middleware | Verificar AuditLogInterceptor está aplicado |

### 12.2 Debugging

```typescript
// Habilitar logs verbose en development
if (process.env.NODE_ENV === 'development') {
  // Frontend
  apiClient.interceptors.request.use((config) => {
    console.log(`[Admin API] ${config.method?.toUpperCase()} ${config.url}`);
    return config;
  });

  // Backend
  @Injectable()
  export class AdminUsersService {
    async listUsers(query: ListUsersDto) {
      this.logger.debug(`ListUsers called with:`, query);
      const result = await this.userRepo.find(...);
      this.logger.debug(`Returned ${result.length} users`);
      return result;
    }
  }
}
```

---

## 13. Checklist de Desarrollo

### 13.1 Nueva Funcionalidad Admin

- [ ] Definir tipos en `admin/types/index.ts`
- [ ] Crear DTOs en backend `admin/dto/`
- [ ] Implementar service en `admin/services/`
- [ ] Crear/modificar controller
- [ ] Aplicar AdminGuard a endpoints
- [ ] Agregar audit logging
- [ ] Crear API service en frontend
- [ ] Implementar hook en `admin/hooks/`
- [ ] Crear componentes necesarios
- [ ] Integrar en página correspondiente
- [ ] Agregar tests unitarios
- [ ] Documentar en Swagger
- [ ] Actualizar esta guía

### 13.2 Code Review Admin

- [ ] AdminGuard aplicado correctamente
- [ ] Validación de DTOs completa
- [ ] Error handling implementado
- [ ] Audit logging presente
- [ ] Logs apropiados en services
- [ ] Types alineados frontend/backend
- [ ] Query keys descriptivas
- [ ] Invalidación de cache correcta
- [ ] Permisos verificados
- [ ] Tests passing

---

## 14. Referencias

### Documentos Complementarios

| Documento | Descripción |
|-----------|-------------|
| [PORTAL-TEACHER-GUIDE.md](./PORTAL-TEACHER-GUIDE.md) | Guía del portal Teacher (estructura similar) |
| [COMPONENT-PATTERNS.md](./frontend/COMPONENT-PATTERNS.md) | Patrones de componentes |
| [HOOK-PATTERNS.md](./frontend/HOOK-PATTERNS.md) | Patrones de hooks |
| [DTO-CONVENTIONS.md](./backend/DTO-CONVENTIONS.md) | Convenciones de DTOs |
| [ESTRUCTURA-MODULOS.md](./backend/ESTRUCTURA-MODULOS.md) | Estructura de módulos |
| [ESTANDARES-API-ROUTES.md](../../orchestration/directivas/ESTANDARES-API-ROUTES.md) | Estándares de rutas API |

### ADRs Relevantes

- ADR-001: Separación de portales (student/teacher/admin)
- ADR-002: Uso de AdminGuard para autorización
- ADR-003: Bulk operations con background jobs
- ADR-004: Audit logging obligatorio para acciones admin

---

## 15. Ejemplos de Código Completos

### 15.1 Hook Completo - useUserManagement

```typescript
// hooks/useUserManagement.ts
import { useState, useCallback } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import * as adminAPI from '@/services/api/adminAPI';
import type {
  User,
  ListUsersDto,
  UpdateUserDto,
  SuspendUserDto
} from '../types';

export interface UseUserManagementResult {
  // Data
  users: User[];
  stats: UserStatsDto | null;
  loading: boolean;
  error: string | null;

  // Filters
  filters: ListUsersDto;
  setFilters: (filters: ListUsersDto) => void;

  // Actions
  createUser: (data: CreateUserDto) => Promise<void>;
  updateUser: (id: string, data: UpdateUserDto) => Promise<void>;
  deleteUser: (id: string) => Promise<void>;
  suspendUser: (id: string, data: SuspendUserDto) => Promise<void>;
  activateUser: (id: string) => Promise<void>;
  resetPassword: (id: string) => Promise<void>;
}

export function useUserManagement(): UseUserManagementResult {
  const queryClient = useQueryClient();
  const [filters, setFilters] = useState<ListUsersDto>({
    page: 1,
    limit: 20,
  });

  // Queries
  const {
    data: usersData,
    isLoading: usersLoading,
    error: usersError
  } = useQuery({
    queryKey: ['admin', 'users', 'list', filters],
    queryFn: () => adminAPI.listUsers(filters),
  });

  const { data: stats } = useQuery({
    queryKey: ['admin', 'users', 'stats'],
    queryFn: () => adminAPI.getUserStats(),
  });

  // Mutations
  const { mutateAsync: createUser } = useMutation({
    mutationFn: adminAPI.createUser,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });
      queryClient.invalidateQueries({ queryKey: ['admin', 'dashboard'] });
    },
  });

  const { mutateAsync: updateUser } = useMutation({
    mutationFn: ({ id, data }: { id: string; data: UpdateUserDto }) =>
      adminAPI.updateUser(id, data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });
    },
  });

  const { mutateAsync: deleteUser } = useMutation({
    mutationFn: adminAPI.deleteUser,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });
      queryClient.invalidateQueries({ queryKey: ['admin', 'dashboard'] });
    },
  });

  const { mutateAsync: suspendUser } = useMutation({
    mutationFn: ({ id, data }: { id: string; data: SuspendUserDto }) =>
      adminAPI.suspendUser(id, data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });
    },
  });

  const { mutateAsync: activateUser } = useMutation({
    mutationFn: adminAPI.activateUser,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });
    },
  });

  const { mutateAsync: resetPassword } = useMutation({
    mutationFn: adminAPI.resetUserPassword,
    onSuccess: () => {
      // No need to invalidate, just show success toast
    },
  });

  return {
    users: usersData?.data || [],
    stats: stats || null,
    loading: usersLoading,
    error: usersError?.message || null,
    filters,
    setFilters,
    createUser,
    updateUser: useCallback(
      (id: string, data: UpdateUserDto) => updateUser({ id, data }),
      [updateUser]
    ),
    deleteUser,
    suspendUser: useCallback(
      (id: string, data: SuspendUserDto) => suspendUser({ id, data }),
      [suspendUser]
    ),
    activateUser,
    resetPassword,
  };
}
```

### 15.2 Service Backend Completo - AdminUsersService

```typescript
// services/admin-users.service.ts
import { Injectable, NotFoundException, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from '@modules/auth/entities/user.entity';
import { AuditLogService } from '@modules/audit/audit-log.service';
import {
  ListUsersDto,
  UpdateUserDto,
  SuspendUserDto,
  PaginatedUsersDto,
  UserStatsDto,
} from '../dto/users';

@Injectable()
export class AdminUsersService {
  private readonly logger = new Logger(AdminUsersService.name);

  constructor(
    @InjectRepository(User, 'auth')
    private userRepo: Repository<User>,
    private auditLogService: AuditLogService,
  ) {}

  async listUsers(query: ListUsersDto): Promise<PaginatedUsersDto> {
    const {
      page = 1,
      limit = 20,
      role,
      status,
      search,
      sortBy = 'created_at',
      sortOrder = 'DESC'
    } = query;

    this.logger.debug(`Listing users: page=${page}, limit=${limit}, role=${role}, status=${status}`);

    const qb = this.userRepo.createQueryBuilder('user')
      .leftJoinAndSelect('user.profile', 'profile')
      .leftJoinAndSelect('user.roles', 'userRoles')
      .leftJoinAndSelect('userRoles.role', 'role');

    // Filtros
    if (role) {
      qb.andWhere('role.name = :role', { role });
    }

    if (status) {
      qb.andWhere('user.status = :status', { status });
    }

    if (search) {
      qb.andWhere(
        '(user.username ILIKE :search OR user.email ILIKE :search OR profile.first_name ILIKE :search OR profile.last_name ILIKE :search)',
        { search: `%${search}%` }
      );
    }

    // Sorting
    qb.orderBy(`user.${sortBy}`, sortOrder);

    // Paginación
    const skip = (page - 1) * limit;
    qb.skip(skip).take(limit);

    const [users, total] = await qb.getManyAndCount();

    this.logger.debug(`Found ${total} users, returning page ${page}`);

    return {
      data: users,
      meta: {
        total,
        page,
        limit,
        totalPages: Math.ceil(total / limit),
      },
    };
  }

  async getUserDetails(id: string): Promise<User> {
    const user = await this.userRepo.findOne({
      where: { id },
      relations: ['profile', 'roles', 'roles.role'],
    });

    if (!user) {
      throw new NotFoundException(`User with ID ${id} not found`);
    }

    return user;
  }

  async updateUser(
    userId: string,
    dto: UpdateUserDto,
    adminId: string
  ): Promise<User> {
    const user = await this.getUserDetails(userId);

    this.logger.log(`Admin ${adminId} updating user ${userId}`);

    // Guardar estado anterior
    const previousState = { ...user };

    // Actualizar
    Object.assign(user, dto);
    await this.userRepo.save(user);

    // Audit log
    await this.auditLogService.log({
      event_type: 'user_updated',
      actor_id: adminId,
      target_id: userId,
      target_type: 'user',
      changes: {
        before: previousState,
        after: user,
      },
      metadata: {
        updated_fields: Object.keys(dto),
      },
    });

    return user;
  }

  async deleteUser(userId: string, adminId: string): Promise<void> {
    const user = await this.getUserDetails(userId);

    this.logger.log(`Admin ${adminId} deleting user ${userId}`);

    // Soft delete
    user.deleted_at = new Date();
    user.status = 'deleted';
    await this.userRepo.save(user);

    // Audit log
    await this.auditLogService.log({
      event_type: 'user_deleted',
      actor_id: adminId,
      target_id: userId,
      target_type: 'user',
    });
  }

  async suspendUser(
    userId: string,
    dto: SuspendUserDto,
    adminId: string
  ): Promise<void> {
    const user = await this.getUserDetails(userId);

    this.logger.log(`Admin ${adminId} suspending user ${userId}: ${dto.reason}`);

    user.status = 'suspended';
    user.suspended_at = new Date();
    user.suspension_reason = dto.reason;

    if (dto.duration_days) {
      const until = new Date();
      until.setDate(until.getDate() + dto.duration_days);
      user.suspended_until = until;
    }

    await this.userRepo.save(user);

    // Audit log
    await this.auditLogService.log({
      event_type: 'user_suspended',
      actor_id: adminId,
      target_id: userId,
      target_type: 'user',
      metadata: {
        reason: dto.reason,
        duration_days: dto.duration_days,
      },
    });
  }

  async getUserStats(): Promise<UserStatsDto> {
    const total = await this.userRepo.count();
    const active = await this.userRepo.count({ where: { status: 'active' } });
    const suspended = await this.userRepo.count({ where: { status: 'suspended' } });

    // Roles breakdown
    const roleBreakdown = await this.userRepo
      .createQueryBuilder('user')
      .leftJoin('user.roles', 'userRoles')
      .leftJoin('userRoles.role', 'role')
      .select('role.name', 'role')
      .addSelect('COUNT(user.id)', 'count')
      .groupBy('role.name')
      .getRawMany();

    return {
      total_users: total,
      active_users: active,
      suspended_users: suspended,
      inactive_users: total - active - suspended,
      role_breakdown: roleBreakdown,
    };
  }
}
```

---

## Changelog

| Versión | Fecha | Cambios |
|---------|-------|---------|
| 1.0.0 | 2025-11-29 | Creación inicial completa |

---

**Fin del documento - PORTAL-ADMIN-GUIDE.md**
