"""
Monitoring Views for Stream Processor Application

This module contains views for the monitoring dashboard, system health,
and real-time status updates using HTMX for dynamic content loading.
"""

from django.shortcuts import render
from django.http import JsonResponse, HttpResponse
from django.views.generic import TemplateView
from django.views.decorators.cache import cache_page
from django.utils.decorators import method_decorator
from django.utils import timezone
from django.db.models import Count, Q
from datetime import timedelta
from django.contrib.auth.mixins import LoginRequiredMixin 

from apps.streams.models import Channel, StreamSession, HLSSegment
from apps.jingles.models import JingleDetection, AdBreak
from apps.notifications.models import Notification


class DashboardView(LoginRequiredMixin, TemplateView):
    """
    Main dashboard view showing system overview and real-time statistics.
    
    This view provides a comprehensive overview of the stream processing
    system including active streams, recent detections, and system health.
    """
    
    template_name = 'monitoring/dashboard.html'
    
    def get_context_data(self, **kwargs):
        """
        Get dashboard context data including statistics and recent activity.
        
        Returns:
            dict: Context data for the dashboard template
        """
        context = super().get_context_data(**kwargs)
        
        # Get current time for calculations
        now = timezone.now()
        last_24h = now - timedelta(hours=24)
        last_hour = now - timedelta(hours=1)
        
        # Stream statistics
        active_sessions = StreamSession.objects.filter(
            status__in=['active', 'processing']
        )
        
        context['stats'] = {
            'active_streams': active_sessions.count(),
            'total_channels': Channel.objects.filter(is_active=True).count(),
            'sessions_today': StreamSession.objects.filter(
                started_at__gte=last_24h
            ).count(),
            'detections_today': JingleDetection.objects.filter(
                detection_time__gte=last_24h
            ).count(),
            'ad_breaks_today': AdBreak.objects.filter(
                start_time__gte=last_24h
            ).count(),
            'notifications_sent_today': Notification.objects.filter(
                sent_at__gte=last_24h,
                status='completed'
            ).count(),
        }
        
        # Recent activity
        context['recent_sessions'] = StreamSession.objects.select_related(
            'channel'
        ).order_by('-started_at')[:5]
        
        context['recent_detections'] = JingleDetection.objects.select_related(
            'template', 'session__channel'
        ).order_by('-detection_time')[:5]
        
        context['recent_ad_breaks'] = AdBreak.objects.select_related(
            'session__channel'
        ).order_by('-start_time')[:5]
        
        # Active streams with details
        context['active_streams'] = active_sessions.select_related(
            'channel', 'video_config', 'audio_config'
        )
        
        return context


class MetricsView(LoginRequiredMixin, TemplateView):
    """
    Detailed metrics view with charts and performance data.
    """
    
    template_name = 'monitoring/metrics.html'
    
    def get_context_data(self, **kwargs):
        """Get detailed metrics data for charts and analysis."""
        context = super().get_context_data(**kwargs)
        
        # Time ranges for analysis
        now = timezone.now()
        last_24h = now - timedelta(hours=24)
        last_7d = now - timedelta(days=7)
        
        # Detection performance over time
        hourly_detections = []
        for i in range(24):
            hour_start = now - timedelta(hours=i+1)
            hour_end = now - timedelta(hours=i)
            
            count = JingleDetection.objects.filter(
                detection_time__gte=hour_start,
                detection_time__lt=hour_end
            ).count()
            
            hourly_detections.append({
                'hour': hour_start.strftime('%H:00'),
                'count': count
            })
        
        context['hourly_detections'] = list(reversed(hourly_detections))
        
        # Channel performance
        channel_stats = []
        for channel in Channel.objects.filter(is_active=True):
            sessions = channel.sessions.filter(started_at__gte=last_7d)
            detections = JingleDetection.objects.filter(
                session__channel=channel,
                detection_time__gte=last_7d
            )
            
            channel_stats.append({
                'name': channel.name,
                'sessions': sessions.count(),
                'detections': detections.count(),
                'avg_confidence': detections.aggregate(
                    avg=models.Avg('confidence_score')
                )['avg'] or 0,
            })
        
        context['channel_stats'] = channel_stats
        
        # System performance trends
        context['performance_data'] = {
            'detection_accuracy': self._calculate_detection_accuracy(last_7d),
            'stream_uptime': self._calculate_stream_uptime(last_7d),
            'notification_delivery_rate': self._calculate_notification_rate(last_7d),
        }
        
        return context
    
    def _calculate_detection_accuracy(self, since):
        """Calculate detection accuracy percentage."""
        total_detections = JingleDetection.objects.filter(
            detection_time__gte=since
        ).count()
        
        if total_detections == 0:
            return 0
        
        confirmed_detections = JingleDetection.objects.filter(
            detection_time__gte=since,
            is_confirmed=True
        ).count()
        
        return (confirmed_detections / total_detections) * 100
    
    def _calculate_stream_uptime(self, since):
        """Calculate average stream uptime percentage."""
        sessions = StreamSession.objects.filter(started_at__gte=since)
        
        if not sessions.exists():
            return 0
        
        total_uptime = 0
        total_sessions = 0
        
        for session in sessions:
            if session.duration():
                # Calculate uptime based on successful vs failed time
                duration = session.duration().total_seconds()
                if session.status in ['active', 'completed']:
                    total_uptime += duration
                total_sessions += 1
        
        if total_sessions == 0:
            return 0
        
        return (total_uptime / (total_sessions * 3600)) * 100  # Assuming 1 hour target
    
    def _calculate_notification_rate(self, since):
        """Calculate notification delivery success rate."""
        notifications = Notification.objects.filter(created_at__gte=since)
        
        if not notifications.exists():
            return 0
        
        sent_notifications = notifications.filter(status='completed').count()
        return (sent_notifications / notifications.count()) * 100



def system_status(request):
    """
    HTMX endpoint for real-time system status updates.
    
    Returns system health information in HTML format for dynamic updates.
    
    Args:
        request: HTTP request object
        
    Returns:
        HttpResponse: HTML fragment with system status
    """
    # Check system health
    active_streams = StreamSession.objects.filter(
        status__in=['active', 'processing']
    ).count()
    
    failed_streams = StreamSession.objects.filter(
        status='failed',
        updated_at__gte=timezone.now() - timedelta(minutes=5)
    ).count()
    
    # Determine system status
    if failed_streams > 0:
        status = 'warning'
        message = f'{failed_streams} failed streams'
        color = 'yellow'
    elif active_streams > 0:
        status = 'healthy'
        message = f'{active_streams} active streams'
        color = 'green'
    else:
        status = 'idle'
        message = 'No active streams'
        color = 'gray'
    
    html = f'''
    <div class="flex items-center space-x-2">
        <div class="pulse-dot w-3 h-3 bg-{color}-500 rounded-full"></div>
        <span class="text-sm text-gray-600">{message}</span>
    </div>
    '''
    
    return HttpResponse(html)


def system_info(request):
    """
    HTMX endpoint for system information updates.
    
    Returns basic system information for the sidebar.
    
    Args:
        request: HTTP request object
        
    Returns:
        HttpResponse: HTML fragment with system info
    """
    import psutil
    import os
    
    try:
        # Get system metrics
        cpu_percent = psutil.cpu_percent(interval=1)
        memory = psutil.virtual_memory()
        disk = psutil.disk_usage('/')
        
        html = f'''
        <div class="text-xs space-y-1">
            <div>CPU: {cpu_percent:.1f}%</div>
            <div>RAM: {memory.percent:.1f}%</div>
            <div>Disk: {(disk.percent):.1f}%</div>
        </div>
        '''
    except:
        html = '<div class="text-xs text-gray-500">Metrics unavailable</div>'
    
    return HttpResponse(html)


def health_check(request):
    """
    Health check endpoint for load balancers and monitoring systems.
    
    Args:
        request: HTTP request object
        
    Returns:
        JsonResponse: Health status and system information
    """
    health_data = {
        'status': 'healthy',
        'timestamp': timezone.now().isoformat(),
        'version': '1.0.0',
        'checks': {}
    }
    
    try:
        # Database health check
        from django.db import connection
        with connection.cursor() as cursor:
            cursor.execute("SELECT 1")
        health_data['checks']['database'] = 'healthy'
    except Exception as e:
        health_data['checks']['database'] = f'unhealthy: {str(e)}'
        health_data['status'] = 'unhealthy'
    
    try:
        # Redis health check
        import redis
        from django.conf import settings
        r = redis.from_url(settings.CELERY_BROKER_URL)
        r.ping()
        health_data['checks']['redis'] = 'healthy'
    except Exception as e:
        health_data['checks']['redis'] = f'unhealthy: {str(e)}'
        health_data['status'] = 'degraded'
    
    # Active streams check
    active_streams = StreamSession.objects.filter(
        status__in=['active', 'processing']
    ).count()
    health_data['checks']['active_streams'] = active_streams
    
    # Recent failures check
    recent_failures = StreamSession.objects.filter(
        status='failed',
        updated_at__gte=timezone.now() - timedelta(minutes=5)
    ).count()
    
    if recent_failures > 5:  # More than 5 failures in 5 minutes
        health_data['status'] = 'degraded'
        health_data['checks']['recent_failures'] = f'high: {recent_failures}'
    else:
        health_data['checks']['recent_failures'] = f'normal: {recent_failures}'
    
    # Return appropriate HTTP status code
    status_code = 200 if health_data['status'] == 'healthy' else 503
    
    return JsonResponse(health_data, status=status_code)


def live_stream_data(request):
    """
    HTMX endpoint for live stream data updates.
    
    Returns real-time stream information for dashboard widgets.
    
    Args:
        request: HTTP request object
        
    Returns:
        HttpResponse: HTML fragment with live stream data
    """
    active_sessions = StreamSession.objects.filter(
        status__in=['active', 'processing']
    ).select_related('channel')
    
    context = {
        'active_sessions': active_sessions,
        'total_active': active_sessions.count()
    }
    
    return render(request, 'monitoring/partials/live_streams.html', context)


def recent_activity(request):
    """
    HTMX endpoint for recent activity updates.
    
    Returns recent detections and events for the activity feed.
    
    Args:
        request: HTTP request object
        
    Returns:
        HttpResponse: HTML fragment with recent activity
    """
    # Get recent activity from the last hour
    last_hour = timezone.now() - timedelta(hours=1)
    
    recent_detections = JingleDetection.objects.filter(
        detection_time__gte=last_hour
    ).select_related('template', 'session__channel').order_by('-detection_time')[:10]
    
    recent_ad_breaks = AdBreak.objects.filter(
        start_time__gte=last_hour
    ).select_related('session__channel').order_by('-start_time')[:5]
    
    context = {
        'recent_detections': recent_detections,
        'recent_ad_breaks': recent_ad_breaks
    }
    
    return render(request, 'monitoring/partials/recent_activity.html', context)


def dashboard_stats(request):
    """
    HTMX endpoint for dashboard statistics updates.
    
    Returns real-time dashboard statistics for the stats grid.
    
    Args:
        request: HTTP request object
        
    Returns:
        HttpResponse: HTML fragment with dashboard stats
    """
    # Get current time for calculations
    now = timezone.now()
    last_24h = now - timedelta(hours=24)
    
    # Calculate statistics
    stats = {
        'active_streams': StreamSession.objects.filter(
            status__in=['active', 'processing']
        ).count(),
        'total_channels': Channel.objects.filter(is_active=True).count(),
        'sessions_today': StreamSession.objects.filter(
            started_at__gte=last_24h
        ).count(),
        'detections_today': JingleDetection.objects.filter(
            detection_time__gte=last_24h
        ).count(),
        'ad_breaks_today': AdBreak.objects.filter(
            start_time__gte=last_24h
        ).count(),
        'notifications_sent_today': Notification.objects.filter(
            sent_at__gte=last_24h,
            status='completed'
        ).count(),
    }
    
    context = {'stats': stats}
    
    return render(request, 'monitoring/partials/dashboard_stats.html', context)


def stream_stats(request):
    """
    HTMX endpoint for active streams count updates.
    
    Returns the current count of active streams for real-time updates.
    
    Args:
        request: HTTP request object
        
    Returns:
        HttpResponse: HTML fragment with active streams count
    """
    active_streams = StreamSession.objects.filter(
        status__in=['active', 'processing']
    ).count()
    
    return HttpResponse(str(active_streams))
