from rest_framework.generics import ListAPIView, RetrieveAPIView from django.shortcuts import get_object_or_404 from utils.pagination import NoPagination from rest_framework.response import Response from django.db.models import Count from django.db.models import Prefetch from ..models import HadisCategory, Hadis, HadisCollection,HadisTransmitter , HadisCorrection from ..serializers import HadisListSerializer, HadisBasicSerializer, HadisDetailSerializer, HadisCollectionListSerializer, HadisSyncSerializer,HadisCorrectionSerializer,HadisTransmitterListSerializer from ..docs import hadis_list_swagger, hadis_detail_swagger, hadis_collections_swagger, hadis_sync_swagger, hadis_transmitters_swagger, hadis_corrections_swagger, hadis_basic_swagger class HadisCollectionListView(ListAPIView): """ API view to list all hadis collections """ queryset = HadisCollection.objects.filter(status=True).order_by('order') serializer_class = HadisCollectionListSerializer pagination_class = NoPagination @hadis_collections_swagger def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) class HadisSyncView(ListAPIView): """ API view to sync all hadis data for offline mode """ serializer_class = HadisSyncSerializer pagination_class = NoPagination def get_queryset(self): return Hadis.objects.filter(status=True).select_related( 'category', 'hadis_status' ).prefetch_related( 'tags', 'transmitters__transmitter', 'references__images', 'references__book_reference', 'hadiscorrection_set' ).order_by('id') @hadis_sync_swagger def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def list(self, request, *args, **kwargs): queryset = self.get_queryset() serializer = self.get_serializer(queryset, many=True) response_data = { 'count': queryset.count(), 'results': serializer.data } return Response(response_data) class HadisListView(ListAPIView): """ API view to list Hadis by category_id """ serializer_class = HadisListSerializer @hadis_list_swagger def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def get_queryset(self): category_id = self.kwargs.get('category_id') if not HadisCategory.objects.filter(id=category_id).exists(): return Hadis.objects.none() return Hadis.objects.filter( category_id=category_id, status=True ).order_by('number').annotate( # distinct=True is CRITICAL here. # Without it, if 3 narrators are from "Layer 1", it counts as 3. # With it, it counts as 1 (unique layer). layer_count=Count('transmitters__narrator_layer', distinct=True) ).select_related('category') class HadisBasicView(RetrieveAPIView): """ API view to retrieve basic Hadis information by hadis_slug """ serializer_class = HadisBasicSerializer lookup_field = 'slug' lookup_url_kwarg = 'hadis_slug' @hadis_basic_swagger def get(self, request, *args, **kwargs): return self.retrieve(request, *args, **kwargs) def get_queryset(self): return Hadis.objects.filter(status=True) class HadisDetailView(RetrieveAPIView): """ API view to retrieve detailed Hadis information by hadis_slug (excluding transmitters and corrections) """ serializer_class = HadisDetailSerializer lookup_field = 'slug' lookup_url_kwarg = 'hadis_slug' @hadis_detail_swagger def get(self, request, *args, **kwargs): return self.retrieve(request, *args, **kwargs) def get_queryset(self): return Hadis.objects.filter(status=True).select_related( 'category', 'hadis_status' ).prefetch_related( 'tags', 'references__book_reference__title', 'references__book_reference__images', 'references__book_reference__authors', 'references__book_reference__id', 'references__book_reference__description', ) class HadisTransmittersView(RetrieveAPIView): """ Fetches a single Hadis but filters the nested Transmitters list if a ?layer=slug param is provided. """ serializer_class = HadisTransmitterListSerializer lookup_field = 'slug' lookup_url_kwarg = 'hadis_slug' @hadis_transmitters_swagger def get(self, request, *args, **kwargs): return self.retrieve(request, *args, **kwargs) def get_queryset(self): # 1. Get the filter param layer_slug = self.request.query_params.get('layer') # 2. Build the query for the "Child" (Transmitters) # We start with the base optimization (select_related) transmitter_qs = HadisTransmitter.objects.select_related( 'transmitter', 'narrator_layer' ).order_by('order') # 3. Apply the filter to the Child Query (if param exists) if layer_slug: # Assumes 'NarratorLayer' has a 'slug' field. # If not, use 'narrator_layer__name' or 'narrator_layer__id'. transmitter_qs = transmitter_qs.filter(narrator_layer__slug=layer_slug) # 4. Use the Prefetch object to inject this filtered list into the Parent return Hadis.objects.filter(status=True).prefetch_related( Prefetch('transmitters', queryset=transmitter_qs) ) class HadisCorrectionsView(ListAPIView): """ API view to retrieve corrections for a specific hadis """ serializer_class = HadisCorrectionSerializer lookup_field = 'slug' lookup_url_kwarg = 'hadis_slug' @hadis_corrections_swagger def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) # hadis = self.get_object() # corrections_data = [] # for correction in hadis.hadiscorrection_set.all(): # correction_info = { # 'id': correction.id, # 'title': correction.title, # 'description': correction.description, # 'translation': correction.translation # } # corrections_data.append(correction_info) # return Response({ # 'hadis_id': hadis.id, # 'corrections_count': len(corrections_data), # 'corrections': corrections_data # }) def get_queryset(self): hadis_slug = self.kwargs.get('hadis_slug') try: hadis = Hadis.objects.get(slug=hadis_slug, status=True) if not HadisCorrection.objects.filter(hadis=hadis).exists(): return Hadis.objects.none() return HadisCorrection.objects.filter(hadis=hadis) except Hadis.DoesNotExist: return HadisCorrection.objects.none()