from django.shortcuts import render
from rest_framework import viewsets, status, generics
from rest_framework.response import Response
from django.db.models.functions import TruncDate
from datetime import date, timedelta
from django.db.models import Count
from rest_framework.views import APIView
from users.models import User_Roles
from rest_framework.permissions import IsAuthenticated
from .models import Complaint, ComplaintCategory, ComplaintStatusHistory
from .serializers import (
    ComplaintSerializer,
    ComplaintCategorySerializer,
    CitizenComplaintReadSerializer,
    MinistryComplaintUpdateSerializer,
    ComplaintStatisticsSerializer
)
from django.db import transaction


# -----------------------------
# Permission classes
# -----------------------------
class IsMinistryOfficer(IsAuthenticated):
    def has_permission(self, request, view):
        return super().has_permission(request, view) and request.user.is_staff


# -----------------------------
# Utility function
# -----------------------------
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)


# -----------------------------
# Complaint ViewSet
# -----------------------------
class ComplaintViewSet(viewsets.ModelViewSet):
    serializer_class = ComplaintSerializer
    permission_classes = [IsMinistryOfficer]
    http_method_names = ["get", "patch"]  # Only allow GET and PATCH methods

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

        if tenant_ids is None:
            # Superuser → see all complaints
            return Complaint.objects.all().order_by("-timestamp")
        

        # Officer → filter by tenant(s)
        return Complaint.objects.filter(category__tenant_id__in=tenant_ids).order_by(
            "-timestamp"
        )

    def partial_update(self, request, *args, **kwargs):
        """
           Custom update method to handle status changes and create a history record,
           including a resolution message if the complaint is closed.
         """
        instance = self.get_object()

    # Use the custom serializer for validation
        serializer = MinistryComplaintUpdateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
    
        new_status = serializer.validated_data.get("status")
        resolution_message = serializer.validated_data.get("resolution_message", None)

        with transaction.atomic():
        # Update the complaint status
               instance.status = new_status
               instance.save()

        # Create a new status history record, including the resolution message
               ComplaintStatusHistory.objects.create(
            complaint=instance,
            status=new_status,
            resolution_message=resolution_message,
            changed_by=request.user
        )

    
        response_serializer = ComplaintSerializer(instance)
        return Response(response_serializer.data)



class CitizenComplaintCreateView(generics.CreateAPIView):
    queryset = Complaint.objects.all()
    serializer_class = ComplaintSerializer
    permission_classes = [IsAuthenticated]

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


# -----------------------------
# Complaint Categories
# -----------------------------
class ComplaintCategoryListView(generics.ListAPIView):
    serializer_class = ComplaintCategorySerializer
    permission_classes = [IsAuthenticated]

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

        # Superuser or citizen → all categories
        if tenant_ids is None or not tenant_ids.exists():
            return ComplaintCategory.objects.all()

        # Officer → restrict to tenant categories
        return ComplaintCategory.objects.filter(tenant_id__in=tenant_ids)


# -----------------------------
# Citizen Complaint List
# -----------------------------
class CitizenComplaintListView(generics.ListAPIView):
    serializer_class = CitizenComplaintReadSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        return Complaint.objects.filter(user=self.request.user).order_by("-timestamp")

    def get_serializer_context(self):
        return {"request": self.request}


# -----------------------------
# Complaint Trends
# -----------------------------
class ComplaintTrendsAPIView(APIView):
    permission_classes = [IsMinistryOfficer]

    def get(self, request, *args, **kwargs):
        user = request.user
        tenant_ids = get_user_tenant_ids(user)

        if tenant_ids is not None and not tenant_ids.exists():
            return Response(
                {"detail": "No tenant assigned. Cannot retrieve trends."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        tenant_filter = {} if tenant_ids is None else {"tenant_id__in": tenant_ids}

        end_date = date.today()
        start_date = end_date - timedelta(days=30)

        received_by_date = (
            Complaint.objects.filter(
                **tenant_filter,
                timestamp__date__range=[start_date, end_date],
            )
            .annotate(date=TruncDate("timestamp"))
            .values("date")
            .annotate(count=Count("complaint_id"))
            .order_by("date")
        )

        closed_by_date = (
            Complaint.objects.filter(**tenant_filter, status="closed")
            .annotate(date=TruncDate("timestamp"))
            .values("date")
            .annotate(count=Count("complaint_id"))
            .order_by("date")
        )

        received_data = {
            item["date"].strftime("%Y-%m-%d"): item["count"]
            for item in received_by_date
        }
        closed_data = {
            item["date"].strftime("%Y-%m-%d"): item["count"] for item in closed_by_date
        }

        trends_data = []
        backlog = 0
        current_date = start_date

        while current_date <= end_date:
            date_str = current_date.strftime("%Y-%m-%d")
            received_count = received_data.get(date_str, 0)
            closed_count = closed_data.get(date_str, 0)
            backlog += received_count - closed_count
            backlog = max(backlog, 0)

            trends_data.append(
                {
                    "date": date_str,
                    "dateLabel": current_date.strftime("%b %d"),
                    "received": received_count,
                    "closed": closed_count,
                    "backlog": backlog,
                }
            )
            current_date += timedelta(days=1)

        return Response(trends_data, status=status.HTTP_200_OK)
    

class UserComplaintStatisticsAPIView(APIView):
    """
    API view to get the complaint statistics for the currently logged-in user.
    """
    permission_classes = [IsAuthenticated] # Ensures only logged-in users can access

    def get(self, request, *args, **kwargs):
        
        user = request.user
        
        
        user_complaints = Complaint.objects.filter(user=user)
        
       
        total_complaints = user_complaints.count()
        
       
        status_counts = user_complaints.values('status').annotate(count=Count('status'))
        
      
        stats = {
            'total_complaints': total_complaints,
            'received_complaints': 0,
            'pending_complaints': 0,
            'closed_complaints': 0,
        }
        
        
        for item in status_counts:
            status = item['status']
            count = item['count']
            
            if status == 'received':
                stats['received_complaints'] = count
            elif status == 'pending':
                stats['pending_complaints'] = count
            elif status == 'closed': # 'Resolved' on the frontend is 'closed' in the model
                stats['closed_complaints'] = count

        
        serializer = ComplaintStatisticsSerializer(stats)
        
        
        return Response(serializer.data)

