from django.shortcuts import render
from rest_framework import viewsets, status, generics
from rest_framework.decorators import action
from rest_framework.response import Response as DRF_Response
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from .models import PollSurvey, Response
from users.models import User_Roles
from .serializers import (
    PollSurveySerializer,
    ResponseSerializer,
    MinistryResponseSerializer,
    CitizenPollSurveySerializer,
)
from django.utils import timezone
from django.shortcuts import get_object_or_404
from django.db.models import Count
from django.db import IntegrityError


class IsMinistryOfficer(IsAuthenticated):
    """
    Custom permission to check if the user is a staff member.
    """

    def has_permission(self, request, view):
        return super().has_permission(request, view) and request.user.is_staff


# utility function for getting tenant id for ifficer
def get_user_tenant_ids(user):
    """
    Returns a queryset of tenant IDs the user belongs to.
    If superuser, returns None to indicate "all tenants".
    """
    if user.is_superuser:
        return None  # None indicates no restriction
    return User_Roles.objects.filter(user=user).values_list("tenant_id", flat=True)


class PollSurveyViewSet(viewsets.ModelViewSet):
    """
    API endpoint for ministry officers to manage polls and surveys.
    - Allows CRUD operations for PollSurvey objects.
    - The custom 'responses' action will now be handled by a separate view.
    """

    serializer_class = PollSurveySerializer
    permission_classes = [IsMinistryOfficer]

    def get_queryset(self):
        user = self.request.user
        tenant_ids = get_user_tenant_ids(user)

        if tenant_ids is None:
            return (
                PollSurvey.objects.all()
                .annotate(response_count=Count("responses"))
                .order_by("-created_at")
            )
        return (
            PollSurvey.objects.filter(tenant__in=tenant_ids)
            .annotate(response_count=Count("responses"))
            .order_by("-created_at")
        )

    @action(detail=False, methods=["get"])
    def drafts(self, request):
        # Filter the queryset to get only the drafts
        drafts = self.get_queryset().filter(status="draft")
        drafts = drafts.filter(created_by=request.user)
        # You might want to add a filter here for the current user's drafts

        serializer = self.get_serializer(drafts, many=True)
        return DRF_Response(serializer.data)

    @action(detail=False, methods=["get"])
    def summary(self, request):
        active_polls = PollSurvey.objects.filter(type="poll", status="active").count()
        active_surveys = PollSurvey.objects.filter(
            type="survey", status="active"
        ).count()
        drafts = PollSurvey.objects.filter(status="draft").count()
        total_responses = Response.objects.all().count()

        summary_data = {
            "active_polls": active_polls,
            "active_surveys": active_surveys,
            "drafts": drafts,
            "total_responses": total_responses,
        }

        return DRF_Response(summary_data)

    @action(detail=False, methods=["get"])
    def trends(self, request):
        """
        Returns a list of objects, each containing the date and count of responses
        submitted on that date within the last 30 days.
        """
        thirty_days_ago = timezone.now() - timezone.timedelta(days=30)
        trends_data = (
            Response.objects.filter(submitted_at__gte=thirty_days_ago)
            .values("submitted_at__date")
            .annotate(count=Count("id"))
            .order_by("submitted_at__date")
        )

        return DRF_Response(trends_data)


class ActivePollSurveyListView(generics.ListAPIView):
    """
    API endpoint for citizens to view a list of all active polls/surveys.
    """

    serializer_class = CitizenPollSurveySerializer

    def get_queryset(self):
        """
        Filters out polls/surveys that the current authenticated user has already
        responded to.
        """
        # Start with all active polls/surveys
        queryset = PollSurvey.objects.filter(
            status="active",
            # start_date__lte=timezone.now(),
            # end_date__gte=timezone.now()
        )

        # Check for the poll type filter
        poll_type = self.request.query_params.get("type")
        if poll_type:
            queryset = queryset.filter(type=poll_type)

        # 🚨 Crucial Change: Filter out polls that the user has already answered
        if self.request.user.is_authenticated:
            # Get the IDs of all polls the current user has responded to
            answered_poll_ids = Response.objects.filter(
                user=self.request.user
            ).values_list("survey_id", flat=True)
            # Exclude those polls from the queryset
            queryset = queryset.exclude(id__in=answered_poll_ids)

        return queryset.order_by("-created_at")


class PollSurveyDetailView(generics.RetrieveAPIView):
    """
    API endpoint to retrieve a single active poll/survey for a citizen to answer.
    """

    queryset = PollSurvey.objects.filter(
        status="active",
        # start_date__lte=timezone.now(),
        # end_date__gte=timezone.now()
    )
    serializer_class = CitizenPollSurveySerializer
    lookup_field = "id"


class ResponseCreateView(generics.CreateAPIView):
    """
    API endpoint for citizens to submit a response to an active poll/survey.
    """

    queryset = Response.objects.all()
    serializer_class = ResponseSerializer

    def create(self, request, *args, **kwargs):
        survey_id = request.data.get("survey")
        user = self.request.user if self.request.user.is_authenticated else None

        # 1. First, check if the user has already submitted a response for this survey.
        # This is a pre-emptive check to give a cleaner error message before the serializer runs.
        if Response.objects.filter(survey_id=survey_id, user=user).exists():
            return DRF_Response(
                {
                    "detail": "You have already submitted a response for this poll/survey."
                },
                status=status.HTTP_409_CONFLICT,
            )

        try:
            survey = PollSurvey.objects.get(
                id=survey_id,
                status="active",
            )
        except PollSurvey.DoesNotExist:
            return DRF_Response(
                {"detail": "This survey is not active or does not exist."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        tenant = survey.tenant if survey else None
        context = {"request": request, "user": user, "tenant": tenant}

        # 2. Use a single serializer instance and a single try-except block
        serializer = self.get_serializer(data=request.data, context=context)

        # Validate the data (including required questions)
        serializer.is_valid(raise_exception=True)

        try:
            # Attempt to save the validated data
            instance = serializer.save()
        except IntegrityError:
            # This is a fallback in case of a race condition, but our initial check
            # above should prevent it in most cases.
            return DRF_Response(
                {
                    "detail": "You have already submitted a response for this poll/survey."
                },
                status=status.HTTP_409_CONFLICT,
            )

        # 3. All logic is now complete; return the success response.
        headers = self.get_success_headers(serializer.data)
        return DRF_Response(
            serializer.data, status=status.HTTP_201_CREATED, headers=headers
        )


class PollSurveyResponsesListView(generics.ListAPIView):
    """
    Dedicated API endpoint to list all responses for a specific poll.
    """

    serializer_class = MinistryResponseSerializer
    permission_classes = [IsMinistryOfficer]

    def get_queryset(self):
        """
        Overrides the queryset to filter responses based on the poll's primary key.
        The pk is passed in the URL.
        """
        # The pk of the poll is available in the URL kwargs
        pk = self.kwargs["pk"]
        try:
            poll_survey = get_object_or_404(PollSurvey, pk=pk)
            return (
                poll_survey.responses.all()
                .prefetch_related("details__question", "details__option")
                .order_by("-submitted_at")
            )
        except ValueError as e:
            # Catch the UUID error and log it
            print(f"Error fetching responses for PollSurvey ID {pk}: {e}")
            # You might need to check your database manually to find the bad data
            raise
