from rest_framework import viewsets, filters
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
from django_filters.rest_framework import DjangoFilterBackend
from django.db.models import Q, Prefetch
from .models import CaseStudy, CaseStudyCategory, Client, CaseStudyImage, CaseStudyProcess
from .serializers import (
    CaseStudyListSerializer,
    CaseStudyDetailSerializer,
    CaseStudyCategorySerializer,
    ClientSerializer
)


class CaseStudyPagination(PageNumberPagination):
    """Custom pagination for case studies"""
    page_size = 9
    page_size_query_param = 'page_size'
    max_page_size = 100


class CaseStudyViewSet(viewsets.ReadOnlyModelViewSet):
    """
    ViewSet for case studies
    Supports filtering by category, client, and search
    """
    queryset = CaseStudy.objects.filter(published=True)
    pagination_class = CaseStudyPagination
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ['category__slug', 'client', 'featured']
    search_fields = ['title', 'description', 'excerpt']
    ordering_fields = ['published_at', 'views_count', 'created_at', 'display_order']
    ordering = ['display_order', '-published_at']
    lookup_field = 'slug'

    def get_serializer_class(self):
        if self.action == 'retrieve':
            return CaseStudyDetailSerializer
        return CaseStudyListSerializer

    def get_queryset(self):
        queryset = super().get_queryset()
        
        # Always optimize foreign key lookups
        queryset = queryset.select_related('category', 'client')
        
        # Don't add prefetch_related here for retrieve action - it's handled in retrieve() method
        # to avoid duplicate prefetch lookups
        
        # Filter by category
        category_slug = self.request.query_params.get('category', None)
        if category_slug and category_slug != 'all':
            queryset = queryset.filter(category__slug=category_slug)
        
        # Filter by client
        client_slug = self.request.query_params.get('client', None)
        if client_slug:
            queryset = queryset.filter(client__slug=client_slug)
        
        # Search query
        search = self.request.query_params.get('search', None)
        if search:
            queryset = queryset.filter(
                Q(title__icontains=search) |
                Q(description__icontains=search) |
                Q(excerpt__icontains=search)
            )
        
        return queryset.distinct()

    def retrieve(self, request, *args, **kwargs):
        """Override retrieve to increment view count and ensure optimized queryset"""
        # Get the base queryset (without prefetch_related to avoid duplicates)
        queryset = self.filter_queryset(self.get_queryset())
        
        # Now add prefetch_related for detail view optimization
        queryset = queryset.prefetch_related(
            Prefetch(
                'gallery_images',
                queryset=CaseStudyImage.objects.order_by('display_order', 'created_at')
            ),
            Prefetch(
                'process_steps',
                queryset=CaseStudyProcess.objects.order_by('step_number')
            )
        )
        
        # Get the object using the optimized queryset
        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
        filter_kwargs = {self.lookup_field: kwargs[lookup_url_kwarg]}
        instance = queryset.get(**filter_kwargs)
        
        # Increment view count
        instance.increment_views()
        
        # Serialize and return
        serializer = self.get_serializer(instance)
        return Response(serializer.data)

    @action(detail=False, methods=['get'])
    def featured(self, request):
        """Get featured case studies"""
        featured_case_studies = self.get_queryset().filter(featured=True)[:6]
        serializer = self.get_serializer(featured_case_studies, many=True)
        return Response(serializer.data)

    @action(detail=False, methods=['get'])
    def latest(self, request):
        """Get latest case studies"""
        limit = int(request.query_params.get('limit', 6))
        latest_case_studies = self.get_queryset()[:limit]
        serializer = self.get_serializer(latest_case_studies, many=True)
        return Response(serializer.data)

    @action(detail=False, methods=['get'])
    def popular(self, request):
        """Get popular case studies by views"""
        limit = int(request.query_params.get('limit', 6))
        popular_case_studies = self.get_queryset().order_by('-views_count')[:limit]
        serializer = self.get_serializer(popular_case_studies, many=True)
        return Response(serializer.data)

    @action(detail=True, methods=['get'])
    def related(self, request, slug=None):
        """Get related case studies for a specific case study"""
        case_study = self.get_object()
        related_case_studies = self.get_queryset().filter(
            category=case_study.category
        ).exclude(id=case_study.id)[:4]
        serializer = self.get_serializer(related_case_studies, many=True)
        return Response(serializer.data)


class CaseStudyCategoryViewSet(viewsets.ReadOnlyModelViewSet):
    """ViewSet for case study categories"""
    queryset = CaseStudyCategory.objects.filter(is_active=True)
    serializer_class = CaseStudyCategorySerializer
    lookup_field = 'slug'

    @action(detail=False, methods=['get'])
    def with_case_studies(self, request):
        """Get categories that have published case studies"""
        categories = self.get_queryset().filter(case_studies__published=True).distinct()
        serializer = self.get_serializer(categories, many=True)
        return Response(serializer.data)


class ClientViewSet(viewsets.ReadOnlyModelViewSet):
    """ViewSet for clients"""
    queryset = Client.objects.filter(is_active=True)
    serializer_class = ClientSerializer
    lookup_field = 'slug'

    @action(detail=True, methods=['get'])
    def case_studies(self, request, slug=None):
        """Get all case studies for a specific client"""
        client = self.get_object()
        case_studies = CaseStudy.objects.filter(client=client, published=True)
        page = self.paginate_queryset(case_studies)
        if page is not None:
            serializer = CaseStudyListSerializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = CaseStudyListSerializer(case_studies, many=True)
        return Response(serializer.data)

