"""API views for channels app.

This module contains ViewSets and API views for managing channels, zones, shows,
EPG entries, codecs, and jingles through REST API endpoints.
"""

from django.shortcuts import get_object_or_404
from django.db.models import Q, Count, Avg, Sum
from django.utils import timezone
from django.core.cache import cache
from django.http import JsonResponse
from rest_framework import viewsets, status, permissions
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.pagination import PageNumberPagination
from datetime import datetime, timedelta
import logging

from ..models import (
    Channel, Zone, Show, EPGEntry, Codec, Jingle, ChannelZone
)
from ..serializers import (
    ChannelSerializer, ZoneSerializer, ShowSerializer, EPGEntrySerializer,
    CodecSerializer, JingleSerializer, ChannelZoneSerializer,
    ChannelSummarySerializer, ShowSummarySerializer, EPGCalendarSerializer
)
from ..services import ChannelService, EPGService, JingleService, CodecService
from ..views import can_manage_channels, can_view_channels

logger = logging.getLogger(__name__)


class ChannelsPagination(PageNumberPagination):
    """Custom pagination class for channels API."""
    page_size = 20
    page_size_query_param = 'page_size'
    max_page_size = 100


class ChannelPermissionMixin:
    """Mixin to handle channel permissions for API views."""
    
    def get_permissions(self):
        """Return the list of permissions that this view requires."""
        if self.action in ['create', 'update', 'partial_update', 'destroy']:
            # Management actions require channel management permissions
            permission_classes = [permissions.IsAuthenticated]
        else:
            # Read actions require view permissions
            permission_classes = [permissions.IsAuthenticated]
        return [permission() for permission in permission_classes]
    
    def check_management_permission(self, request):
        """Check if user has management permissions."""
        if not can_manage_channels(request.user):
            return Response(
                {'error': 'You do not have permission to manage channels.'},
                status=status.HTTP_403_FORBIDDEN
            )
        return None
    
    def check_view_permission(self, request):
        """Check if user has view permissions."""
        if not can_view_channels(request.user):
            return Response(
                {'error': 'You do not have permission to view channels.'},
                status=status.HTTP_403_FORBIDDEN
            )
        return None


class ChannelViewSet(ChannelPermissionMixin, viewsets.ModelViewSet):
    """ViewSet for managing channels."""
    
    queryset = Channel.objects.select_related('country').prefetch_related(
        'zones', 'jingles', 'epg_entries__show'
    )
    serializer_class = ChannelSerializer
    pagination_class = ChannelsPagination
    
    def get_queryset(self):
        """Filter queryset based on query parameters."""
        queryset = self.queryset
        
        # Filter by channel type
        channel_type = self.request.query_params.get('type')
        if channel_type:
            queryset = queryset.filter(channel_type=channel_type)
        
        # Filter by country
        country = self.request.query_params.get('country')
        if country:
            queryset = queryset.filter(country__code=country)
        
        # Filter by language
        language = self.request.query_params.get('language')
        if language:
            queryset = queryset.filter(language=language)
        
        # Filter by active status
        is_active = self.request.query_params.get('active')
        if is_active is not None:
            queryset = queryset.filter(is_active=is_active.lower() == 'true')
        
        # Search by name or description
        search = self.request.query_params.get('search')
        if search:
            queryset = queryset.filter(
                Q(name__icontains=search) |
                Q(description__icontains=search) |
                Q(slug__icontains=search)
            )
        
        return queryset.distinct()
    
    def create(self, request, *args, **kwargs):
        """Create a new channel."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().create(request, *args, **kwargs)
    
    def update(self, request, *args, **kwargs):
        """Update an existing channel."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().update(request, *args, **kwargs)
    
    def destroy(self, request, *args, **kwargs):
        """Delete a channel."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().destroy(request, *args, **kwargs)
    
    @action(detail=True, methods=['get'])
    def zones(self, request, pk=None):
        """Get zones for a specific channel."""
        channel = self.get_object()
        zones = channel.zones.all()
        serializer = ZoneSerializer(zones, many=True)
        return Response(serializer.data)
    
    @action(detail=True, methods=['get'])
    def epg(self, request, pk=None):
        """Get EPG entries for a specific channel."""
        channel = self.get_object()
        
        # Filter by date range
        start_date = request.query_params.get('start_date')
        end_date = request.query_params.get('end_date')
        
        epg_entries = channel.epg_entries.select_related('show')
        
        if start_date:
            try:
                start_date = datetime.fromisoformat(start_date)
                epg_entries = epg_entries.filter(start_time__gte=start_date)
            except ValueError:
                pass
        
        if end_date:
            try:
                end_date = datetime.fromisoformat(end_date)
                epg_entries = epg_entries.filter(end_time__lte=end_date)
            except ValueError:
                pass
        
        epg_entries = epg_entries.order_by('start_time')
        
        page = self.paginate_queryset(epg_entries)
        if page is not None:
            serializer = EPGEntrySerializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        
        serializer = EPGEntrySerializer(epg_entries, many=True)
        return Response(serializer.data)
    
    @action(detail=True, methods=['get'])
    def jingles(self, request, pk=None):
        """Get jingles for a specific channel."""
        channel = self.get_object()
        jingles = channel.jingles.all().order_by('-priority', 'jingle_type')
        serializer = JingleSerializer(jingles, many=True)
        return Response(serializer.data)
    
    @action(detail=True, methods=['post'])
    def assign_zone(self, request, pk=None):
        """Assign a zone to a channel."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        channel = self.get_object()
        zone_id = request.data.get('zone_id')
        
        if not zone_id:
            return Response(
                {'error': 'zone_id is required'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        try:
            zone = Zone.objects.get(id=zone_id)
            channel_service = ChannelService()
            success = channel_service.assign_zone_to_channel(channel, zone, request.data)
            
            if success:
                return Response({'message': 'Zone assigned successfully'})
            else:
                return Response(
                    {'error': 'Failed to assign zone'},
                    status=status.HTTP_400_BAD_REQUEST
                )
        except Zone.DoesNotExist:
            return Response(
                {'error': 'Zone not found'},
                status=status.HTTP_404_NOT_FOUND
            )
        except Exception as e:
            logger.error(f"Error assigning zone to channel: {e}")
            return Response(
                {'error': 'Internal server error'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )


class ZoneViewSet(ChannelPermissionMixin, viewsets.ModelViewSet):
    """ViewSet for managing zones."""
    
    queryset = Zone.objects.prefetch_related('channels')
    serializer_class = ZoneSerializer
    
    def get_queryset(self):
        """Filter queryset based on query parameters."""
        queryset = self.queryset
        
        # Filter by active status
        is_active = self.request.query_params.get('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)
            )
        
        return queryset
    
    def create(self, request, *args, **kwargs):
        """Create a new zone."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().create(request, *args, **kwargs)
    
    def update(self, request, *args, **kwargs):
        """Update an existing zone."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().update(request, *args, **kwargs)
    
    def destroy(self, request, *args, **kwargs):
        """Delete a zone."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().destroy(request, *args, **kwargs)
    
    @action(detail=True, methods=['get'])
    def channels(self, request, pk=None):
        """Get channels for a specific zone."""
        zone = self.get_object()
        channels = zone.channels.all()
        serializer = ChannelSummarySerializer(channels, many=True)
        return Response(serializer.data)


class ShowViewSet(ChannelPermissionMixin, viewsets.ModelViewSet):
    """ViewSet for managing shows."""
    
    queryset = Show.objects.prefetch_related('epg_entries__channel')
    serializer_class = ShowSerializer
    pagination_class = ChannelsPagination
    
    def get_queryset(self):
        """Filter queryset based on query parameters."""
        queryset = self.queryset
        
        # Filter by show type
        show_type = self.request.query_params.get('type')
        if show_type:
            queryset = queryset.filter(show_type=show_type)
        
        # Filter by content rating
        content_rating = self.request.query_params.get('rating')
        if content_rating:
            queryset = queryset.filter(content_rating=content_rating)
        
        # Filter by genre
        genre = self.request.query_params.get('genre')
        if genre:
            queryset = queryset.filter(genre__icontains=genre)
        
        # Search by title or description
        search = self.request.query_params.get('search')
        if search:
            queryset = queryset.filter(
                Q(title__icontains=search) |
                Q(description__icontains=search) |
                Q(genre__icontains=search) |
                Q(cast__icontains=search)
            )
        
        return queryset.distinct()
    
    def create(self, request, *args, **kwargs):
        """Create a new show."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().create(request, *args, **kwargs)
    
    def update(self, request, *args, **kwargs):
        """Update an existing show."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().update(request, *args, **kwargs)
    
    def destroy(self, request, *args, **kwargs):
        """Delete a show."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().destroy(request, *args, **kwargs)
    
    @action(detail=True, methods=['get'])
    def epg(self, request, pk=None):
        """Get EPG entries for a specific show."""
        show = self.get_object()
        epg_entries = show.epg_entries.select_related('channel').order_by('start_time')
        
        page = self.paginate_queryset(epg_entries)
        if page is not None:
            serializer = EPGEntrySerializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        
        serializer = EPGEntrySerializer(epg_entries, many=True)
        return Response(serializer.data)


class EPGEntryViewSet(ChannelPermissionMixin, viewsets.ModelViewSet):
    """ViewSet for managing EPG entries."""
    
    queryset = EPGEntry.objects.select_related('channel', 'show')
    serializer_class = EPGEntrySerializer
    pagination_class = ChannelsPagination
    
    def get_queryset(self):
        """Filter queryset based on query parameters."""
        queryset = self.queryset
        
        # Filter by channel
        channel_id = self.request.query_params.get('channel')
        if channel_id:
            queryset = queryset.filter(channel_id=channel_id)
        
        # Filter by show
        show_id = self.request.query_params.get('show')
        if show_id:
            queryset = queryset.filter(show_id=show_id)
        
        # Filter by date range
        start_date = self.request.query_params.get('start_date')
        end_date = self.request.query_params.get('end_date')
        
        if start_date:
            try:
                start_date = datetime.fromisoformat(start_date)
                queryset = queryset.filter(start_time__gte=start_date)
            except ValueError:
                pass
        
        if end_date:
            try:
                end_date = datetime.fromisoformat(end_date)
                queryset = queryset.filter(end_time__lte=end_date)
            except ValueError:
                pass
        
        # Filter by currently airing
        currently_airing = self.request.query_params.get('currently_airing')
        if currently_airing and currently_airing.lower() == 'true':
            now = timezone.now()
            queryset = queryset.filter(start_time__lte=now, end_time__gte=now)
        
        return queryset.order_by('start_time')
    
    def create(self, request, *args, **kwargs):
        """Create a new EPG entry."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().create(request, *args, **kwargs)
    
    def update(self, request, *args, **kwargs):
        """Update an existing EPG entry."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().update(request, *args, **kwargs)
    
    def destroy(self, request, *args, **kwargs):
        """Delete an EPG entry."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().destroy(request, *args, **kwargs)


class CodecViewSet(ChannelPermissionMixin, viewsets.ModelViewSet):
    """ViewSet for managing codecs."""
    
    queryset = Codec.objects.all()
    serializer_class = CodecSerializer
    
    def get_queryset(self):
        """Filter queryset based on query parameters."""
        queryset = self.queryset
        
        # Filter by codec type
        codec_type = self.request.query_params.get('type')
        if codec_type:
            queryset = queryset.filter(codec_type=codec_type)
        
        # Filter by active status
        is_active = self.request.query_params.get('active')
        if is_active is not None:
            queryset = queryset.filter(is_active=is_active.lower() == 'true')
        
        # Search by name
        search = self.request.query_params.get('search')
        if search:
            queryset = queryset.filter(name__icontains=search)
        
        return queryset
    
    def create(self, request, *args, **kwargs):
        """Create a new codec."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().create(request, *args, **kwargs)
    
    def update(self, request, *args, **kwargs):
        """Update an existing codec."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().update(request, *args, **kwargs)
    
    def destroy(self, request, *args, **kwargs):
        """Delete a codec."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().destroy(request, *args, **kwargs)


class JingleViewSet(ChannelPermissionMixin, viewsets.ModelViewSet):
    """ViewSet for managing jingles."""
    
    queryset = Jingle.objects.select_related('channel')
    serializer_class = JingleSerializer
    
    def get_queryset(self):
        """Filter queryset based on query parameters."""
        queryset = self.queryset
        
        # Filter by channel
        channel_id = self.request.query_params.get('channel')
        if channel_id:
            queryset = queryset.filter(channel_id=channel_id)
        
        # Filter by jingle type
        jingle_type = self.request.query_params.get('type')
        if jingle_type:
            queryset = queryset.filter(jingle_type=jingle_type)
        
        # Filter by active status
        is_active = self.request.query_params.get('active')
        if is_active is not None:
            queryset = queryset.filter(is_active=is_active.lower() == 'true')
        
        return queryset.order_by('-priority', 'jingle_type')
    
    def create(self, request, *args, **kwargs):
        """Create a new jingle."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().create(request, *args, **kwargs)
    
    def update(self, request, *args, **kwargs):
        """Update an existing jingle."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().update(request, *args, **kwargs)
    
    def destroy(self, request, *args, **kwargs):
        """Delete a jingle."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().destroy(request, *args, **kwargs)


class ChannelZoneViewSet(ChannelPermissionMixin, viewsets.ModelViewSet):
    """ViewSet for managing channel-zone relationships."""
    
    queryset = ChannelZone.objects.select_related(
        'channel', 'zone', 'video_codec', 'audio_codec', 'container_format'
    )
    serializer_class = ChannelZoneSerializer
    
    def get_queryset(self):
        """Filter queryset based on query parameters."""
        queryset = self.queryset
        
        # Filter by channel
        channel_id = self.request.query_params.get('channel')
        if channel_id:
            queryset = queryset.filter(channel_id=channel_id)
        
        # Filter by zone
        zone_id = self.request.query_params.get('zone')
        if zone_id:
            queryset = queryset.filter(zone_id=zone_id)
        
        # Filter by active status
        is_active = self.request.query_params.get('active')
        if is_active is not None:
            queryset = queryset.filter(is_active=is_active.lower() == 'true')
        
        return queryset
    
    def create(self, request, *args, **kwargs):
        """Create a new channel-zone relationship."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().create(request, *args, **kwargs)
    
    def update(self, request, *args, **kwargs):
        """Update an existing channel-zone relationship."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().update(request, *args, **kwargs)
    
    def destroy(self, request, *args, **kwargs):
        """Delete a channel-zone relationship."""
        permission_check = self.check_management_permission(request)
        if permission_check:
            return permission_check
        
        return super().destroy(request, *args, **kwargs)


# Custom API Views

class ChannelZonesAPIView(APIView):
    """API view for getting channel zones configuration."""
    
    permission_classes = [permissions.IsAuthenticated]
    
    def get(self, request, channel_id):
        """Get zones configuration for a specific channel."""
        permission_check = can_view_channels(request.user)
        if not permission_check:
            return Response(
                {'error': 'You do not have permission to view channels.'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        try:
            channel = Channel.objects.get(id=channel_id)
            channel_zones = ChannelZone.objects.filter(
                channel=channel, is_active=True
            ).select_related('zone', 'video_codec', 'audio_codec', 'container_format')
            
            serializer = ChannelZoneSerializer(channel_zones, many=True)
            return Response(serializer.data)
        
        except Channel.DoesNotExist:
            return Response(
                {'error': 'Channel not found'},
                status=status.HTTP_404_NOT_FOUND
            )


class EPGCalendarAPIView(APIView):
    """API view for EPG calendar data."""
    
    permission_classes = [permissions.IsAuthenticated]
    
    def get(self, request):
        """Get EPG data formatted for calendar display."""
        permission_check = can_view_channels(request.user)
        if not permission_check:
            return Response(
                {'error': 'You do not have permission to view channels.'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # Get date range from query parameters
        start_date = request.query_params.get('start')
        end_date = request.query_params.get('end')
        channel_id = request.query_params.get('channel')
        
        epg_entries = EPGEntry.objects.select_related('channel', 'show')
        
        if start_date:
            try:
                start_date = datetime.fromisoformat(start_date.replace('Z', '+00:00'))
                epg_entries = epg_entries.filter(start_time__gte=start_date)
            except ValueError:
                pass
        
        if end_date:
            try:
                end_date = datetime.fromisoformat(end_date.replace('Z', '+00:00'))
                epg_entries = epg_entries.filter(end_time__lte=end_date)
            except ValueError:
                pass
        
        if channel_id:
            epg_entries = epg_entries.filter(channel_id=channel_id)
        
        serializer = EPGCalendarSerializer(epg_entries, many=True)
        return Response(serializer.data)


class ChannelEPGAPIView(APIView):
    """API view for channel EPG data."""
    
    permission_classes = [permissions.IsAuthenticated]
    
    def get(self, request, channel_id):
        """Get EPG entries for a specific channel."""
        permission_check = can_view_channels(request.user)
        if not permission_check:
            return Response(
                {'error': 'You do not have permission to view channels.'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        try:
            channel = Channel.objects.get(id=channel_id)
            
            # Get date range from query parameters
            start_date = request.query_params.get('start_date')
            end_date = request.query_params.get('end_date')
            
            epg_entries = channel.epg_entries.select_related('show')
            
            if start_date:
                try:
                    start_date = datetime.fromisoformat(start_date)
                    epg_entries = epg_entries.filter(start_time__gte=start_date)
                except ValueError:
                    pass
            
            if end_date:
                try:
                    end_date = datetime.fromisoformat(end_date)
                    epg_entries = epg_entries.filter(end_time__lte=end_date)
                except ValueError:
                    pass
            
            epg_entries = epg_entries.order_by('start_time')
            serializer = EPGEntrySerializer(epg_entries, many=True)
            return Response(serializer.data)
        
        except Channel.DoesNotExist:
            return Response(
                {'error': 'Channel not found'},
                status=status.HTTP_404_NOT_FOUND
            )


class ZoneChannelsAPIView(APIView):
    """API view for zone channels data."""
    
    permission_classes = [permissions.IsAuthenticated]
    
    def get(self, request, zone_id):
        """Get channels for a specific zone."""
        permission_check = can_view_channels(request.user)
        if not permission_check:
            return Response(
                {'error': 'You do not have permission to view channels.'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        try:
            zone = Zone.objects.get(id=zone_id)
            channels = zone.channels.filter(is_active=True)
            serializer = ChannelSummarySerializer(channels, many=True)
            return Response(serializer.data)
        
        except Zone.DoesNotExist:
            return Response(
                {'error': 'Zone not found'},
                status=status.HTTP_404_NOT_FOUND
            )


class ShowEPGAPIView(APIView):
    """API view for show EPG data."""
    
    permission_classes = [permissions.IsAuthenticated]
    
    def get(self, request, show_id):
        """Get EPG entries for a specific show."""
        permission_check = can_view_channels(request.user)
        if not permission_check:
            return Response(
                {'error': 'You do not have permission to view channels.'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        try:
            show = Show.objects.get(id=show_id)
            epg_entries = show.epg_entries.select_related('channel').order_by('start_time')
            serializer = EPGEntrySerializer(epg_entries, many=True)
            return Response(serializer.data)
        
        except Show.DoesNotExist:
            return Response(
                {'error': 'Show not found'},
                status=status.HTTP_404_NOT_FOUND
            )


class ChannelJinglesAPIView(APIView):
    """API view for channel jingles data."""
    
    permission_classes = [permissions.IsAuthenticated]
    
    def get(self, request, channel_id):
        """Get jingles for a specific channel."""
        permission_check = can_view_channels(request.user)
        if not permission_check:
            return Response(
                {'error': 'You do not have permission to view channels.'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        try:
            channel = Channel.objects.get(id=channel_id)
            jingles = channel.jingles.filter(is_active=True).order_by('-priority', 'jingle_type')
            serializer = JingleSerializer(jingles, many=True)
            return Response(serializer.data)
        
        except Channel.DoesNotExist:
            return Response(
                {'error': 'Channel not found'},
                status=status.HTTP_404_NOT_FOUND
            )


class EPGConflictsAPIView(APIView):
    """API view for EPG scheduling conflicts."""
    
    permission_classes = [permissions.IsAuthenticated]
    
    def get(self, request):
        """Get EPG scheduling conflicts."""
        permission_check = can_view_channels(request.user)
        if not permission_check:
            return Response(
                {'error': 'You do not have permission to view channels.'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # Get conflicts from cache or calculate
        cache_key = 'epg_conflicts'
        conflicts = cache.get(cache_key)
        
        if conflicts is None:
            epg_service = EPGService()
            conflicts = epg_service.get_scheduling_conflicts()
            cache.set(cache_key, conflicts, 300)  # Cache for 5 minutes
        
        return Response(conflicts)


class ChannelStatisticsAPIView(APIView):
    """API view for channel statistics."""
    
    permission_classes = [permissions.IsAuthenticated]
    
    def get(self, request):
        """Get channel statistics."""
        permission_check = can_view_channels(request.user)
        if not permission_check:
            return Response(
                {'error': 'You do not have permission to view channels.'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # Get statistics from cache or calculate
        cache_key = 'channel_statistics'
        stats = cache.get(cache_key)
        
        if stats is None:
            stats = {
                'total_channels': Channel.objects.count(),
                'active_channels': Channel.objects.filter(is_active=True).count(),
                'total_zones': Zone.objects.count(),
                'active_zones': Zone.objects.filter(is_active=True).count(),
                'total_shows': Show.objects.count(),
                'total_epg_entries': EPGEntry.objects.count(),
                'total_jingles': Jingle.objects.count(),
                'active_jingles': Jingle.objects.filter(is_active=True).count(),
                'channels_by_type': dict(
                    Channel.objects.values('channel_type').annotate(
                        count=Count('id')
                    ).values_list('channel_type', 'count')
                ),
                'shows_by_type': dict(
                    Show.objects.values('show_type').annotate(
                        count=Count('id')
                    ).values_list('show_type', 'count')
                ),
                'avg_show_duration': Show.objects.aggregate(
                    avg_duration=Avg('duration')
                )['avg_duration'] or 0,
            }
            cache.set(cache_key, stats, 3600)  # Cache for 1 hour
        
        return Response(stats)


class UpcomingProgramsAPIView(APIView):
    """API view for upcoming programs."""
    
    permission_classes = [permissions.IsAuthenticated]
    
    def get(self, request):
        """Get upcoming programs."""
        permission_check = can_view_channels(request.user)
        if not permission_check:
            return Response(
                {'error': 'You do not have permission to view channels.'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # Get upcoming programs within next 2 hours
        now = timezone.now()
        upcoming_time = now + timedelta(hours=2)
        
        upcoming_programs = EPGEntry.objects.filter(
            start_time__gte=now,
            start_time__lte=upcoming_time
        ).select_related('channel', 'show').order_by('start_time')
        
        # Filter by channel if specified
        channel_id = request.query_params.get('channel')
        if channel_id:
            upcoming_programs = upcoming_programs.filter(channel_id=channel_id)
        
        serializer = EPGEntrySerializer(upcoming_programs, many=True)
        return Response(serializer.data)