"""
academic/views.py
==================
Vistas del módulo académico.
"""

import logging
from django.db import transaction
from django.db.models import Q
from rest_framework.views import APIView
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated

from academic.models import Asignatura, Seccion, Inscripcion, Grupo, ActividadExposicion
from academic.serializers import (
    AsignaturaSerializer, AsignaturaCreateSerializer,
    SeccionSerializer, SeccionCreateSerializer,
    UnirseSeccionSerializer,
    GrupoSerializer, GrupoCreateSerializer,
    ActividadExposicionSerializer,
)
from shared.permissions import IsApprovedDocente, IsAlumno, IsDocenteOwner
from shared.utils.responses import success_response, error_response
from shared.pagination import StandardPagination

logger = logging.getLogger('eduplay')


class AsignaturaViewSet(viewsets.ModelViewSet):
    permission_classes = [IsApprovedDocente]
    pagination_class   = StandardPagination

    def get_queryset(self):
        qs = Asignatura.objects.filter(
            owner=self.request.user
        ).select_related('owner')

        search = self.request.query_params.get('search', '').strip()
        if search:
            qs = qs.filter(
                Q(nombre__icontains=search) | Q(codigo__icontains=search)
            )

        color = self.request.query_params.get('color')
        if color:
            qs = qs.filter(color=color)

        return qs

    def get_serializer_class(self):
        if self.action in ('create', 'update', 'partial_update'):
            return AsignaturaCreateSerializer
        return AsignaturaSerializer

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

    def get_permissions(self):
        permissions = [IsApprovedDocente()]
        if self.action in ('update', 'partial_update', 'destroy'):
            permissions.append(IsDocenteOwner())
        return permissions

    @action(detail=False, methods=['get'], permission_classes=[IsAuthenticated])
    def publicas(self, request):
        qs = Asignatura.objects.filter(es_publica=True).select_related('owner')
        serializer = AsignaturaSerializer(qs, many=True)
        return success_response(data=serializer.data)


class SeccionViewSet(viewsets.ModelViewSet):
    permission_classes = [IsApprovedDocente]
    pagination_class   = StandardPagination

    def get_queryset(self):
        qs = Seccion.objects.filter(
            asignatura__owner=self.request.user
        ).select_related('asignatura')

        asignatura_id = self.request.query_params.get('asignatura_id')
        if asignatura_id:
            qs = qs.filter(asignatura_id=asignatura_id)

        return qs

    def get_serializer_class(self):
        if self.action in ('create', 'update', 'partial_update'):
            return SeccionCreateSerializer
        return SeccionSerializer

    @action(detail=True, methods=['post'])
    def generar_codigo(self, request, pk=None):
        seccion = self.get_object()
        codigo  = seccion.generar_codigo_acceso()
        logger.info(f'Código generado para seccion_id={seccion.id}')
        return success_response(
            data={
                'codigo':    codigo,
                'expira_en': seccion.codigo_expira,
                'minutos':   20,
            },
            message='Código generado. Compártelo con tus alumnos.'
        )

    @action(detail=True, methods=['delete'])
    def invalidar_codigo(self, request, pk=None):
        seccion = self.get_object()
        seccion.invalidar_codigo()
        return success_response(message='Código invalidado.')


class UnirseSeccionView(viewsets.GenericViewSet):
    permission_classes = [IsAlumno]
    serializer_class   = UnirseSeccionSerializer

    def create(self, request):
        serializer = self.get_serializer(data=request.data)
        if not serializer.is_valid():
            return error_response(
                message='Código inválido',
                errors=serializer.errors,
                status_code=400
            )

        inscripcion, seccion = serializer.save(alumno=request.user)
        return success_response(
            data={
                'inscripcion_id': inscripcion.id,
                'seccion': {
                    'id':         seccion.id,
                    'nombre':     seccion.nombre,
                    'asignatura': seccion.asignatura.nombre,
                }
            },
            message=f'¡Te uniste a {seccion.nombre}!',
            status_code=201
        )


class GrupoViewSet(viewsets.ModelViewSet):
    permission_classes = [IsApprovedDocente]

    def get_queryset(self):
        qs = Grupo.objects.filter(
            seccion__asignatura__owner=self.request.user
        ).prefetch_related('integrantes')

        seccion_id = self.request.query_params.get('seccion_id')
        if seccion_id:
            qs = qs.filter(seccion_id=seccion_id)

        return qs

    def get_serializer_class(self):
        if self.action in ('create', 'update', 'partial_update'):
            return GrupoCreateSerializer
        return GrupoSerializer


class ActividadExposicionViewSet(viewsets.ModelViewSet):
    permission_classes = [IsApprovedDocente]
    serializer_class   = ActividadExposicionSerializer

    def get_queryset(self):
        qs = ActividadExposicion.objects.filter(
            seccion__asignatura__owner=self.request.user
        ).prefetch_related('grupos')

        seccion_id = self.request.query_params.get('seccion_id')
        if seccion_id:
            qs = qs.filter(seccion_id=seccion_id)

        estado = self.request.query_params.get('estado')
        if estado:
            qs = qs.filter(estado=estado)

        return qs

    @action(detail=True, methods=['post'])
    def iniciar(self, request, pk=None):
        actividad = self.get_object()
        if actividad.estado != 'pendiente':
            return error_response(message='Solo se puede iniciar una actividad pendiente.', status_code=400)
        actividad.estado = 'activa'
        actividad.save(update_fields=['estado'])
        return success_response(message='Actividad iniciada.')

    @action(detail=True, methods=['post'])
    def cerrar(self, request, pk=None):
        actividad = self.get_object()
        actividad.estado = 'cerrada'
        actividad.save(update_fields=['estado'])
        return success_response(message='Actividad cerrada.')


class MisSeccionesView(APIView):
    """
    GET /api/v1/academic/mis-secciones/
    Retorna las secciones en las que el usuario está inscrito.
    Funciona para alumnos. Para docentes retorna lista vacía.
    """
    permission_classes = [IsAuthenticated]

    def get(self, request):
        from academic.models import Inscripcion

        inscripciones = Inscripcion.objects.filter(
            alumno=request.user,
            activo=True
        ).select_related(
            'seccion',
            'seccion__asignatura',
            'seccion__asignatura__owner',
            'seccion__asignatura__owner__perfil_docente',
        )

        data = []
        for insc in inscripciones:
            sec  = insc.seccion
            asig = sec.asignatura
            try:
                docente_nombre = asig.owner.perfil_docente.nombre_completo
            except Exception:
                docente_nombre = f'Docente #{asig.owner_id}'

            data.append({
                'inscripcion_id': insc.id,
                'seccion': {
                    'id':      sec.id,
                    'nombre':  sec.nombre,
                    'periodo': sec.periodo,
                },
                'asignatura': {
                    'id':          asig.id,
                    'nombre':      asig.nombre,
                    'codigo':      asig.codigo,
                    'color':       asig.color,
                    'descripcion': asig.descripcion,
                },
                'docente': docente_nombre,
            })

        return success_response(data=data)


class AlumnosSeccionView(APIView):
    """
    GET /api/v1/academic/secciones/{pk}/alumnos/
    Retorna los alumnos inscritos en una sección específica.
    Solo el docente dueño puede verlo.
    """
    permission_classes = [IsApprovedDocente]

    def get(self, request, pk):
        from academic.models import Inscripcion

        try:
            seccion = Seccion.objects.get(
                pk=pk,
                asignatura__owner=request.user
            )
        except Seccion.DoesNotExist:
            return error_response(message='Sección no encontrada.', status_code=404)

        inscripciones = Inscripcion.objects.filter(
            seccion=seccion,
            activo=True
        ).select_related('alumno', 'alumno__perfil_alumno')

        data = []
        for insc in inscripciones:
            alumno = insc.alumno
            try:
                nombre = alumno.perfil_alumno.nombre_completo
            except Exception:
                nombre = f'Alumno #{alumno.id}'

            data.append({
                'id':         alumno.id,
                'nombre':     nombre,
                'nickname':   alumno.nickname or '',
                'activo':     alumno.is_active,
                'inscrito_en': insc.created_at,
            })

        return success_response(data=data, meta={'total': len(data)})
