from rest_framework import viewsets, status, generics
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from django.db.models import Q
from django.utils import timezone
from datetime import datetime
from .models import (
    AnnouncementType,
    ClassAnnouncement,
    StudentAnnouncement,
    TeacherAnnouncement,
    CommonAnnouncement,
)
from .serializers import (
    AnnouncementTypeSerializer,
    ClassAnnouncementSerializer,
    StudentAnnouncementSerializer,
    TeacherAnnouncementSerializer,
    CommonAnnouncementSerializer,
    CombinedAnnouncementSerializer,
)


class AnnouncementTypeViewSet(viewsets.ModelViewSet):
    queryset = AnnouncementType.objects.all()
    serializer_class = AnnouncementTypeSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        queryset = AnnouncementType.objects.all()

        # Filter by is_active
        is_active = self.request.query_params.get("is_active")
        if is_active is not None:
            queryset = queryset.filter(is_active=is_active.lower() == "true")

        # Search by name or code
        search = self.request.query_params.get("search")
        if search:
            queryset = queryset.filter(
                Q(name__icontains=search)
                | Q(code__icontains=search)
                | Q(description__icontains=search)
            )

        return queryset

    @action(detail=False, methods=["get"])
    def active(self, request):
        """Get only active announcement types"""
        queryset = self.get_queryset().filter(is_active=True)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


class ClassAnnouncementViewSet(viewsets.ModelViewSet):
    queryset = ClassAnnouncement.objects.all()
    serializer_class = ClassAnnouncementSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        queryset = ClassAnnouncement.objects.all()

        # Filter by academic year (via the announcement's class)
        academic_year_id = self.request.query_params.get("academic_year")
        if academic_year_id:
            queryset = queryset.filter(
                academic_class__academic_year_id=academic_year_id
            )

        # Filter by class
        class_id = self.request.query_params.get("class_id")
        if class_id:
            queryset = queryset.filter(academic_class_id=class_id)

        # Filter by announcement type
        type_id = self.request.query_params.get("type_id")
        if type_id:
            queryset = queryset.filter(announcement_type_id=type_id)

        # Filter by priority
        priority = self.request.query_params.get("priority")
        if priority:
            queryset = queryset.filter(priority=priority)

        # Filter active/non-expired
        active_only = self.request.query_params.get("active_only")
        if active_only and active_only.lower() == "true":
            today = timezone.now().date()
            queryset = queryset.filter(
                Q(is_active=True)
                & (Q(expire_on__isnull=True) | Q(expire_on__gte=today))
            )

        # Filter by status — the frontend sends 'status' (active/expired), which
        # is distinct from the boolean 'active_only' above.
        today = timezone.now().date()
        status_filter = self.request.query_params.get("status")
        if status_filter == "active":
            queryset = queryset.filter(
                Q(is_active=True)
                & (Q(expire_on__isnull=True) | Q(expire_on__gte=today))
            )
        elif status_filter == "expired":
            queryset = queryset.filter(expire_on__isnull=False, expire_on__lt=today)
        elif status_filter == "inactive":
            queryset = queryset.filter(is_active=False)

        # Filter by exact date the announcement was posted
        date_filter = self.request.query_params.get("date")
        if date_filter:
            queryset = queryset.filter(created_at__date=date_filter)

        # Search in title/message
        search = self.request.query_params.get("search")
        if search:
            queryset = queryset.filter(
                Q(title__icontains=search) | Q(message__icontains=search)
            )

        return queryset

    @action(detail=False, methods=["get"])
    def for_class(self, request):
        """Get announcements for a specific class"""
        class_id = request.query_params.get("class_id")
        if not class_id:
            return Response(
                {"error": "class_id parameter is required"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        today = timezone.now().date()
        queryset = (
            self.get_queryset()
            .filter(academic_class_id=class_id, is_active=True)
            .filter(Q(expire_on__isnull=True) | Q(expire_on__gte=today))
        )

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


class StudentAnnouncementViewSet(viewsets.ModelViewSet):
    queryset = StudentAnnouncement.objects.all()
    serializer_class = StudentAnnouncementSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        queryset = StudentAnnouncement.objects.all()

        # Filter by academic year (via the announcement's class)
        academic_year_id = self.request.query_params.get("academic_year")
        if academic_year_id:
            queryset = queryset.filter(
                academic_class__academic_year_id=academic_year_id
            )

        # Filter by section
        section = self.request.query_params.get("section")
        if section:
            queryset = queryset.filter(section=section)

        # Filter by class
        class_id = self.request.query_params.get("class_id")
        if class_id:
            queryset = queryset.filter(academic_class_id=class_id)

        # Filter for all students
        for_all = self.request.query_params.get("for_all")
        if for_all is not None:
            queryset = queryset.filter(is_for_all_students=for_all.lower() == "true")

        # Filter by announcement type
        type_id = self.request.query_params.get("type_id")
        if type_id:
            queryset = queryset.filter(announcement_type_id=type_id)

        # Filter by priority
        priority = self.request.query_params.get("priority")
        if priority:
            queryset = queryset.filter(priority=priority)

        # Filter active/non-expired
        active_only = self.request.query_params.get("active_only")
        if active_only and active_only.lower() == "true":
            today = timezone.now().date()
            queryset = queryset.filter(
                Q(is_active=True)
                & (Q(expire_on__isnull=True) | Q(expire_on__gte=today))
            )

        # Filter by status — the frontend sends 'status' (active/expired), which
        # is distinct from the boolean 'active_only' above.
        today = timezone.now().date()
        status_filter = self.request.query_params.get("status")
        if status_filter == "active":
            queryset = queryset.filter(
                Q(is_active=True)
                & (Q(expire_on__isnull=True) | Q(expire_on__gte=today))
            )
        elif status_filter == "expired":
            queryset = queryset.filter(expire_on__isnull=False, expire_on__lt=today)
        elif status_filter == "inactive":
            queryset = queryset.filter(is_active=False)

        # Filter by exact date the announcement was posted
        date_filter = self.request.query_params.get("date")
        if date_filter:
            queryset = queryset.filter(created_at__date=date_filter)

        # Search
        search = self.request.query_params.get("search")
        if search:
            queryset = queryset.filter(
                Q(title__icontains=search) | Q(message__icontains=search)
            )

        return queryset

    @action(detail=False, methods=["get"])
    def for_student(self, request):
        """Get announcements for a specific student based on class/section"""
        class_id = request.query_params.get("class_id")
        section = request.query_params.get("section")

        if not class_id and not section:
            return Response(
                {"error": "Either class_id or section parameter is required"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        today = timezone.now().date()

        # Build query for student-specific announcements
        query = Q(is_active=True) & (
            Q(expire_on__isnull=True) | Q(expire_on__gte=today)
        )

        # Add filters based on provided parameters
        if class_id:
            query &= Q(academic_class_id=class_id) | Q(is_for_all_students=True)
        if section:
            query &= Q(section=section) | Q(is_for_all_students=True)

        queryset = self.get_queryset().filter(query)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


class TeacherAnnouncementViewSet(viewsets.ModelViewSet):
    queryset = TeacherAnnouncement.objects.all()
    serializer_class = TeacherAnnouncementSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        queryset = TeacherAnnouncement.objects.all()

        # Filter by department
        department = self.request.query_params.get("department")
        if department:
            queryset = queryset.filter(department=department)

        # Filter for all teachers
        for_all = self.request.query_params.get("for_all")
        if for_all is not None:
            queryset = queryset.filter(is_for_all_teachers=for_all.lower() == "true")

        # Filter by announcement type
        type_id = self.request.query_params.get("type_id")
        if type_id:
            queryset = queryset.filter(announcement_type_id=type_id)

        # Filter by priority
        priority = self.request.query_params.get("priority")
        if priority:
            queryset = queryset.filter(priority=priority)

        # Filter active/non-expired
        active_only = self.request.query_params.get("active_only")
        if active_only and active_only.lower() == "true":
            today = timezone.now().date()
            queryset = queryset.filter(
                Q(is_active=True)
                & (Q(expire_on__isnull=True) | Q(expire_on__gte=today))
            )

        # Filter by status — the frontend sends 'status' (active/expired), which
        # is distinct from the boolean 'active_only' above.
        today = timezone.now().date()
        status_filter = self.request.query_params.get("status")
        if status_filter == "active":
            queryset = queryset.filter(
                Q(is_active=True)
                & (Q(expire_on__isnull=True) | Q(expire_on__gte=today))
            )
        elif status_filter == "expired":
            queryset = queryset.filter(expire_on__isnull=False, expire_on__lt=today)
        elif status_filter == "inactive":
            queryset = queryset.filter(is_active=False)

        # Filter by exact date the announcement was posted
        date_filter = self.request.query_params.get("date")
        if date_filter:
            queryset = queryset.filter(created_at__date=date_filter)

        # Search
        search = self.request.query_params.get("search")
        if search:
            queryset = queryset.filter(
                Q(title__icontains=search) | Q(message__icontains=search)
            )

        return queryset

    @action(detail=False, methods=["get"])
    def for_teacher(self, request):
        """Get announcements for a specific teacher based on department"""
        department = request.query_params.get("department")

        today = timezone.now().date()

        # Build query
        query = Q(is_active=True) & (
            Q(expire_on__isnull=True) | Q(expire_on__gte=today)
        )

        if department:
            query &= Q(department=department) | Q(is_for_all_teachers=True)
        else:
            query &= Q(is_for_all_teachers=True)

        queryset = self.get_queryset().filter(query)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


class CommonAnnouncementViewSet(viewsets.ModelViewSet):
    queryset = CommonAnnouncement.objects.all()
    serializer_class = CommonAnnouncementSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        queryset = CommonAnnouncement.objects.all()

        # Filter by announcement type
        type_id = self.request.query_params.get("type_id")
        if type_id:
            queryset = queryset.filter(announcement_type_id=type_id)

        # Filter by priority
        priority = self.request.query_params.get("priority")
        if priority:
            queryset = queryset.filter(priority=priority)

        # Filter active/non-expired
        active_only = self.request.query_params.get("active_only")
        if active_only and active_only.lower() == "true":
            today = timezone.now().date()
            queryset = queryset.filter(
                Q(is_active=True)
                & (Q(expire_on__isnull=True) | Q(expire_on__gte=today))
            )

        # Filter by status — the frontend sends 'status' (active/expired), which
        # is distinct from the boolean 'active_only' above.
        today = timezone.now().date()
        status_filter = self.request.query_params.get("status")
        if status_filter == "active":
            queryset = queryset.filter(
                Q(is_active=True)
                & (Q(expire_on__isnull=True) | Q(expire_on__gte=today))
            )
        elif status_filter == "expired":
            queryset = queryset.filter(expire_on__isnull=False, expire_on__lt=today)
        elif status_filter == "inactive":
            queryset = queryset.filter(is_active=False)

        # Filter by exact date the announcement was posted
        date_filter = self.request.query_params.get("date")
        if date_filter:
            queryset = queryset.filter(created_at__date=date_filter)

        # Search
        search = self.request.query_params.get("search")
        if search:
            queryset = queryset.filter(
                Q(title__icontains=search) | Q(message__icontains=search)
            )

        return queryset

    @action(detail=False, methods=["get"])
    def active(self, request):
        """Get all active common announcements"""
        today = timezone.now().date()
        queryset = (
            self.get_queryset()
            .filter(is_active=True)
            .filter(Q(expire_on__isnull=True) | Q(expire_on__gte=today))
        )
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


class DashboardAnnouncementsView(generics.GenericAPIView):
    """Combined view for dashboard to get all relevant announcements"""

    permission_classes = [IsAuthenticated]

    def get(self, request):
        user_role = request.query_params.get("role", "")
        class_id = request.query_params.get("class_id")
        section = request.query_params.get("section")
        department = request.query_params.get("department")

        today = timezone.now().date()
        announcements = []

        # Get common announcements (for everyone)
        common_announcements = CommonAnnouncement.objects.filter(is_active=True).filter(
            Q(expire_on__isnull=True) | Q(expire_on__gte=today)
        )
        for ann in common_announcements:
            announcements.append(ann)

        # Get role-specific announcements
        if user_role.lower() == "student" and class_id:
            student_announcements = StudentAnnouncement.objects.filter(
                Q(is_active=True)
                & (Q(expire_on__isnull=True) | Q(expire_on__gte=today))
            ).filter(
                Q(is_for_all_students=True)
                | Q(academic_class_id=class_id)
                | Q(section=section)
            )
            for ann in student_announcements:
                announcements.append(ann)

        elif user_role.lower() == "teacher":
            teacher_announcements = TeacherAnnouncement.objects.filter(
                Q(is_active=True)
                & (Q(expire_on__isnull=True) | Q(expire_on__gte=today))
            ).filter(Q(is_for_all_teachers=True) | Q(department=department))
            for ann in teacher_announcements:
                announcements.append(ann)

        elif user_role.lower() == "class_teacher" and class_id:
            class_announcements = ClassAnnouncement.objects.filter(
                Q(is_active=True)
                & (Q(expire_on__isnull=True) | Q(expire_on__gte=today))
            ).filter(academic_class_id=class_id)
            for ann in class_announcements:
                announcements.append(ann)

        # Sort by created_at descending
        announcements.sort(key=lambda x: x.created_at, reverse=True)

        # Serialize
        serializer = CombinedAnnouncementSerializer(announcements, many=True)
        return Response(serializer.data)
