"""
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
import json

from apps.streams.models import Channel, StreamSession, HLSSegment
from apps.jingles.models import JingleDetection, AdBreak
from apps.notifications.models import Notification


@method_decorator(cache_page(30), name='dispatch')  # Cache for 30 seconds
class MetricsView(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 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)
