"""
shared/permissions/roles.py
============================
Clases de permisos por rol para toda la plataforma.
Se aplican en las vistas con permission_classes = [...].

Jerarquía de roles:
  admin   → acceso total al sistema
  docente → gestiona sus propios recursos, aprobado por admin
  alumno  → accede solo a sus secciones y sesiones

Convención: todas las clases heredan de BasePermission de DRF
y documentan claramente qué permiten y qué no.
"""

from rest_framework.permissions import BasePermission
from django.utils import timezone


class IsAdmin(BasePermission):
    """
    Permite acceso solo a usuarios con role='admin'.
    Usar en: gestión de docentes, auditoría, métricas globales.
    """
    message = 'Se requiere rol de administrador.'

    def has_permission(self, request, view):
        return (
            request.user.is_authenticated and
            request.user.role == 'admin'
        )


class IsApprovedDocente(BasePermission):
    """
    Permite acceso solo a docentes aprobados por el admin.
    Un docente no aprobado puede ver el estado de su solicitud
    pero no puede crear recursos.
    """
    message = 'Tu cuenta de docente aún no ha sido aprobada por el administrador.'

    def has_permission(self, request, view):
        return (
            request.user.is_authenticated and
            request.user.role == 'docente' and
            request.user.is_approved
        )


class IsDocente(BasePermission):
    """
    Permite acceso a docentes (aprobados o no).
    Usar en vistas donde un docente puede ver su estado de solicitud.
    Para acciones que requieren cuenta activa, usar IsApprovedDocente.
    """
    message = 'Se requiere rol de docente.'

    def has_permission(self, request, view):
        return (
            request.user.is_authenticated and
            request.user.role == 'docente'
        )


class IsAlumno(BasePermission):
    """
    Permite acceso solo a alumnos activos.
    """
    message = 'Se requiere rol de alumno activo.'

    def has_permission(self, request, view):
        return (
            request.user.is_authenticated and
            request.user.role == 'alumno' and
            request.user.is_active
        )


class IsAdminOrDocente(BasePermission):
    """
    Permite acceso a admin O docente aprobado.
    Útil para endpoints que ambos roles pueden consultar
    (ej: banco público de preguntas).
    """
    message = 'Se requiere rol de administrador o docente.'

    def has_permission(self, request, view):
        if not request.user.is_authenticated:
            return False
        if request.user.role == 'admin':
            return True
        if request.user.role == 'docente' and request.user.is_approved:
            return True
        return False


class IsDocenteOwner(BasePermission):
    """
    Permite acceso solo si el docente es propietario del objeto.
    Se evalúa a nivel de objeto (has_object_permission).
    
    El objeto debe tener un campo 'owner' o 'docente' que apunte al usuario.
    
    Uso:
        permission_classes = [IsApprovedDocente, IsDocenteOwner]
    """
    message = 'No tienes permiso para acceder a este recurso — no eres el propietario.'

    def has_permission(self, request, view):
        return (
            request.user.is_authenticated and
            request.user.role == 'docente' and
            request.user.is_approved
        )

    def has_object_permission(self, request, view, obj):
        # Buscar el campo owner en el objeto o en su relación
        owner = getattr(obj, 'owner', None) or getattr(obj, 'docente', None)
        if owner is None:
            return False
        # Comparar por ID para evitar problemas con instancias diferentes
        owner_id = getattr(owner, 'id', owner)
        return owner_id == request.user.id


class IsInscritoEnSeccion(BasePermission):
    """
    Verifica que el alumno esté inscrito en la sección del recurso.
    Se evalúa a nivel de objeto.
    
    El objeto debe tener acceso a la sección a través de:
      - obj.seccion
      - obj.sesion.seccion
      
    Uso:
        permission_classes = [IsAlumno, IsInscritoEnSeccion]
    """
    message = 'No estás inscrito en la sección de este recurso.'

    def has_permission(self, request, view):
        return (
            request.user.is_authenticated and
            request.user.role == 'alumno'
        )

    def has_object_permission(self, request, view, obj):
        # Obtener la sección desde el objeto
        seccion = (
            getattr(obj, 'seccion', None) or
            getattr(getattr(obj, 'sesion', None), 'seccion', None)
        )
        if seccion is None:
            return False
        # Verificar inscripción activa
        return seccion.inscripcion_set.filter(
            alumno=request.user,
            activo=True
        ).exists()


class IsSesionActiva(BasePermission):
    """
    Permite acciones dentro de una sesión solo si está en estado 'activa'.
    Previene que alumnos respondan fuera del tiempo de la sesión.
    
    El objeto debe ser una Sesion o tener obj.sesion.
    """
    message = 'La sesión no está activa — no se pueden enviar respuestas.'

    def has_permission(self, request, view):
        return request.user.is_authenticated

    def has_object_permission(self, request, view, obj):
        sesion = getattr(obj, 'sesion', obj)
        return getattr(sesion, 'estado', None) == 'activa'
