"""
academic/serializers.py
========================
Serializers para el módulo académico.
Incluye serializers de lectura (listado) y escritura (creación/edición).
"""

from rest_framework import serializers
from academic.models import Asignatura, Seccion, Inscripcion, Grupo, ActividadExposicion
from shared.serializers.base import TimestampedSerializer


# ── ASIGNATURA ──

class AsignaturaSerializer(TimestampedSerializer):
    """Serializer completo de asignatura con campos calculados."""

    # Usar properties del modelo directamente — no dependen de anotaciones ORM
    total_alumnos   = serializers.SerializerMethodField()
    total_secciones = serializers.SerializerMethodField()

    class Meta:
        model   = Asignatura
        fields  = [
            'id', 'nombre', 'codigo', 'descripcion', 'color',
            'es_publica', 'total_alumnos', 'total_secciones',
            'created_at', 'updated_at',
        ]
        read_only_fields = ['id', 'owner', 'created_at', 'updated_at']

    def get_total_alumnos(self, obj):
        try:
            return obj.total_alumnos
        except Exception:
            return 0

    def get_total_secciones(self, obj):
        try:
            return obj.total_secciones
        except Exception:
            return 0


class AsignaturaCreateSerializer(serializers.ModelSerializer):
    """Serializer para crear/editar asignaturas."""

    class Meta:
        model  = Asignatura
        fields = ['nombre', 'codigo', 'descripcion', 'color', 'es_publica']

    def validate_codigo(self, value):
        """El código no puede tener espacios y va en mayúsculas."""
        clean = value.strip().upper().replace(' ', '')
        if len(clean) < 2:
            raise serializers.ValidationError('El código debe tener al menos 2 caracteres.')
        return clean

    def validate(self, attrs):
        """Verificar que el docente no tenga otra asignatura con el mismo código."""
        request = self.context.get('request')
        if request and request.user:
            qs = Asignatura.objects.filter(
                owner=request.user,
                codigo=attrs.get('codigo', '')
            )
            if self.instance:
                qs = qs.exclude(pk=self.instance.pk)
            if qs.exists():
                raise serializers.ValidationError({
                    'codigo': f'Ya tienes una asignatura con el código "{attrs["codigo"]}".'
                })
        return attrs


# ── SECCIÓN ──

class SeccionSerializer(TimestampedSerializer):
    """Serializer de sección con estado del código de acceso."""

    total_alumnos = serializers.IntegerField(read_only=True)
    codigo_activo = serializers.BooleanField(read_only=True)

    class Meta:
        model  = Seccion
        fields = [
            'id', 'asignatura', 'nombre', 'periodo', 'capacidad_maxima',
            'codigo_acceso', 'codigo_expira', 'codigo_activo',
            'total_alumnos', 'created_at',
        ]
        read_only_fields = ['id', 'codigo_acceso', 'codigo_expira', 'created_at']


class SeccionCreateSerializer(serializers.ModelSerializer):
    """Serializer para crear secciones. El docente solo puede crear en sus asignaturas."""

    class Meta:
        model  = Seccion
        fields = ['asignatura', 'nombre', 'periodo', 'capacidad_maxima']

    def validate_asignatura(self, value):
        """Verificar que la asignatura pertenece al docente."""
        request = self.context.get('request')
        if request and value.owner != request.user:
            raise serializers.ValidationError('No puedes crear secciones en asignaturas de otros docentes.')
        return value


# ── INSCRIPCIÓN ──

class UnirseSeccionSerializer(serializers.Serializer):
    """
    Serializer para que un alumno se una a una sección con código efímero.
    Valida que el código sea válido, no expirado y que el alumno no esté ya inscrito.
    """

    codigo = serializers.CharField(min_length=6, max_length=8)

    def validate_codigo(self, value):
        """
        Verifica el código de acceso efímero.
        Busca la sección con ese código activo.
        """
        from django.utils import timezone

        seccion = Seccion.objects.filter(
            codigo_acceso=value.upper().strip(),
            codigo_expira__gt=timezone.now(),  # No expirado
        ).first()

        if seccion is None:
            raise serializers.ValidationError(
                'Código de acceso inválido o expirado. '
                'Pide un nuevo código a tu docente.'
            )

        self.context['seccion'] = seccion
        return value

    def save(self, alumno):
        """Inscribe al alumno en la sección si no está ya inscrito."""
        seccion = self.context['seccion']

        # Verificar capacidad máxima
        if seccion.capacidad_maxima and seccion.total_alumnos >= seccion.capacidad_maxima:
            raise serializers.ValidationError('La sección ha alcanzado su capacidad máxima.')

        inscripcion, created = Inscripcion.objects.get_or_create(
            alumno=alumno,
            seccion=seccion,
            defaults={'activo': True}
        )

        if not created and not inscripcion.activo:
            # Reactivar inscripción existente
            inscripcion.activo = True
            inscripcion.save(update_fields=['activo'])

        return inscripcion, seccion


# ── GRUPO ──

class GrupoSerializer(TimestampedSerializer):
    """Serializer de grupo con lista de integrantes."""

    integrantes_info = serializers.SerializerMethodField()

    class Meta:
        model  = Grupo
        fields = ['id', 'seccion', 'nombre', 'color', 'integrantes', 'integrantes_info', 'created_at']
        read_only_fields = ['id', 'created_at']

    def get_integrantes_info(self, obj) -> list:
        """Lista de integrantes con datos básicos (no email — privado)."""
        return [
            {
                'id':       u.id,
                'nickname': u.nickname,
            }
            for u in obj.integrantes.all()
        ]


class GrupoCreateSerializer(serializers.ModelSerializer):
    """Serializer para crear/editar grupos."""

    class Meta:
        model  = Grupo
        fields = ['seccion', 'nombre', 'color', 'integrantes']

    def validate_seccion(self, value):
        """Solo el docente de la sección puede crear grupos en ella."""
        request = self.context.get('request')
        if request and value.docente != request.user:
            raise serializers.ValidationError('No puedes crear grupos en secciones de otros docentes.')
        return value

    def validate_integrantes(self, value):
        """Verificar que los integrantes están inscritos en la sección."""
        if not value:
            raise serializers.ValidationError('El grupo debe tener al menos un integrante.')
        return value


# ── ACTIVIDAD EXPOSICIÓN ──

class ActividadExposicionSerializer(TimestampedSerializer):
    """Serializer de actividad de exposición."""

    class Meta:
        model  = ActividadExposicion
        fields = [
            'id', 'seccion', 'nombre', 'descripcion', 'fecha',
            'estado', 'grupos', 'created_at',
        ]
        read_only_fields = ['id', 'estado', 'created_at']
