"""
REST API Views for Notifications Application

This module contains Django REST Framework views for managing
notifications, channels, templates, and rules through a RESTful API.
"""

from rest_framework import viewsets, status, permissions
from rest_framework.decorators import api_view, permission_classes, action
from rest_framework.response import Response
from django_filters.rest_framework import DjangoFilterBackend
from django.utils import timezone
from django.db.models import Count, Avg
from datetime import timedelta

from ..models import NotificationChannel, NotificationTemplate, Notification, NotificationRule
from ..services import NotificationService
from ..tasks import process_notification, send_notification_via_rule
from apps.core.throttling import NotificationAPIThrottle
from .serializers import (
    NotificationChannelSerializer, NotificationTemplateSerializer,
    NotificationSerializer, NotificationRuleSerializer, NotificationStatsSerializer
)


class NotificationChannelViewSet(viewsets.ModelViewSet):
    """
    ViewSet for managing notification channels.
    
    Provides CRUD operations for notification channels with
    configuration validation and testing capabilities.
    """
    
    queryset = NotificationChannel.objects.all().select_related('created_by')
    serializer_class = NotificationChannelSerializer
    permission_classes = [permissions.IsAuthenticated]
    throttle_classes = [NotificationAPIThrottle]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['channel_type', 'is_active']
    ordering_fields = ['name', 'created_at']
    ordering = ['name']

    def perform_create(self, serializer):
        """Set the current user as the channel creator."""
        serializer.save(created_by=self.request.user)

    @action(detail=True, methods=['post'])
    def test(self, request, pk=None):
        """Send a test notification through this channel."""
        channel = self.get_object()
        
        try:
            notification_service = NotificationService()
            success = notification_service.send_test_notification(channel)
            
            if success:
                return Response({
                    'success': True,
                    'message': f'Test notification sent via {channel.name}'
                })
            else:
                return Response({
                    'success': False,
                    'error': 'Failed to send test notification'
                }, status=status.HTTP_400_BAD_REQUEST)
                
        except Exception as e:
            return Response({
                'success': False,
                'error': str(e)
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class NotificationTemplateViewSet(viewsets.ModelViewSet):
    """
    ViewSet for managing notification templates.
    
    Provides CRUD operations for templates with usage statistics
    and validation capabilities.
    """
    
    queryset = NotificationTemplate.objects.all()
    serializer_class = NotificationTemplateSerializer
    permission_classes = [permissions.IsAuthenticated]
    throttle_classes = [NotificationAPIThrottle]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['template_type', 'is_active']
    search_fields = ['name', 'template_type']
    ordering_fields = ['name', 'created_at']
    ordering = ['name']

    @action(detail=True, methods=['get'])
    def preview(self, request, pk=None):
        """Preview template with sample data."""
        template = self.get_object()
        
        # Sample context data for preview
        sample_context = {
            'channel_name': 'Sample Channel',
            'jingle_name': 'Sample Jingle',
            'confidence_score': 0.95,
            'detection_time': timezone.now(),
            'duration_seconds': 30,
            'region': 'US-EAST'
        }
        
        try:
            rendered_subject = template.render_subject(sample_context)
            rendered_message = template.render_message(sample_context)
            
            return Response({
                'subject': rendered_subject,
                'message': rendered_message,
                'sample_context': sample_context
            })
            
        except Exception as e:
            return Response({
                'error': f'Template rendering failed: {str(e)}'
            }, status=status.HTTP_400_BAD_REQUEST)


class NotificationViewSet(viewsets.ModelViewSet):
    """
    ViewSet for managing notifications.
    
    Provides access to notification history with filtering
    and retry capabilities.
    """
    
    queryset = Notification.objects.all().select_related(
        'channel', 'template'
    )
    serializer_class = NotificationSerializer
    permission_classes = [permissions.IsAuthenticated]
    throttle_classes = [NotificationAPIThrottle]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['status', 'channel', 'template']
    ordering_fields = ['created_at', 'sent_at']
    ordering = ['-created_at']

    @action(detail=True, methods=['post'])
    def retry(self, request, pk=None):
        """Retry a failed notification."""
        notification = self.get_object()
        
        if not notification.can_retry():
            return Response({
                'error': 'Notification cannot be retried'
            }, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            # Queue for retry
            task = process_notification.delay(str(notification.id))
            
            return Response({
                'success': True,
                'message': 'Notification queued for retry',
                'task_id': task.id
            }, status=status.HTTP_202_ACCEPTED)
            
        except Exception as e:
            return Response({
                'error': str(e)
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    @action(detail=False, methods=['get'])
    def statistics(self, request):
        """Get notification system statistics."""
        # Time ranges
        now = timezone.now()
        last_24h = now - timedelta(hours=24)
        last_7d = now - timedelta(days=7)
        
        # Basic counts
        total_notifications = self.queryset.count()
        notifications_24h = self.queryset.filter(created_at__gte=last_24h).count()
        sent_notifications = self.queryset.filter(status='completed').count()
        failed_notifications = self.queryset.filter(status='failed').count()
        pending_notifications = self.queryset.filter(status='pending').count()
        
        # Delivery rate
        delivery_rate = 0
        if total_notifications > 0:
            delivery_rate = (sent_notifications / total_notifications) * 100
        
        # Average delivery time
        completed_notifications = self.queryset.filter(
            status='completed',
            sent_at__isnull=False
        )
        
        avg_delivery_time = 0
        if completed_notifications.exists():
            delivery_times = []
            for notification in completed_notifications:
                if notification.sent_at and notification.created_at:
                    delta = notification.sent_at - notification.created_at
                    delivery_times.append(delta.total_seconds())
            
            if delivery_times:
                avg_delivery_time = sum(delivery_times) / len(delivery_times)
        
        # Channel performance
        channel_performance = {}
        for channel in NotificationChannel.objects.filter(is_active=True):
            channel_notifications = self.queryset.filter(channel=channel)
            total = channel_notifications.count()
            sent = channel_notifications.filter(status='completed').count()
            
            channel_performance[channel.name] = {
                'total': total,
                'sent': sent,
                'success_rate': (sent / total * 100) if total > 0 else 0
            }
        
        # Recent activity
        recent_activity = list(
            self.queryset.filter(
                created_at__gte=last_24h
            ).order_by('-created_at')[:10].values(
                'channel__name', 'template__name', 'status',
                'created_at', 'sent_at'
            )
        )
        
        stats_data = {
            'total_notifications': total_notifications,
            'sent_notifications': sent_notifications,
            'failed_notifications': failed_notifications,
            'pending_notifications': pending_notifications,
            'delivery_rate': round(delivery_rate, 2),
            'avg_delivery_time': round(avg_delivery_time, 2),
            'channel_performance': channel_performance,
            'recent_activity': recent_activity
        }
        
        serializer = NotificationStatsSerializer(stats_data)
        return Response(serializer.data)


class NotificationRuleViewSet(viewsets.ModelViewSet):
    """
    ViewSet for managing notification rules.
    
    Provides CRUD operations for rules with testing
    and activation capabilities.
    """
    
    queryset = NotificationRule.objects.all().select_related(
        'channel', 'template'
    )
    serializer_class = NotificationRuleSerializer
    permission_classes = [permissions.IsAuthenticated]
    throttle_classes = [NotificationAPIThrottle]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['event_type', 'is_active', 'channel']
    ordering_fields = ['name', 'priority', 'created_at']
    ordering = ['priority', 'name']

    @action(detail=True, methods=['post'])
    def test(self, request, pk=None):
        """Test a notification rule with sample data."""
        rule = self.get_object()
        
        # Sample context for testing
        sample_context = {
            'channel_name': 'Test Channel',
            'event_type': rule.event_type,
            'timestamp': timezone.now(),
            'test_mode': True
        }
        
        try:
            # Send test notification
            task = send_notification_via_rule.delay(
                event_type=rule.event_type,
                context=sample_context
            )
            
            return Response({
                'success': True,
                'message': f'Test notification sent for rule: {rule.name}',
                'task_id': task.id
            }, status=status.HTTP_202_ACCEPTED)
            
        except Exception as e:
            return Response({
                'error': str(e)
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['POST'])
@permission_classes([permissions.IsAuthenticated])
def send_notification(request):
    """
    API endpoint to send custom notifications.
    
    Allows sending notifications with custom content through
    specified channels and templates.
    """
    required_fields = ['channel_id', 'template_id', 'context']
    
    # Validate required fields
    for field in required_fields:
        if field not in request.data:
            return Response({
                'error': f'Missing required field: {field}'
            }, status=status.HTTP_400_BAD_REQUEST)
    
    try:
        # Get channel and template
        channel = NotificationChannel.objects.get(id=request.data['channel_id'])
        template = NotificationTemplate.objects.get(id=request.data['template_id'])
        
        # Create notification
        notification = Notification.objects.create(
            channel=channel,
            template=template,
            context=request.data['context'],
            scheduled_at=request.data.get('scheduled_at', timezone.now())
        )
        
        # Queue for processing
        task = process_notification.delay(str(notification.id))
        
        return Response({
            'success': True,
            'notification_id': str(notification.id),
            'task_id': task.id
        }, status=status.HTTP_202_ACCEPTED)
        
    except (NotificationChannel.DoesNotExist, NotificationTemplate.DoesNotExist) as e:
        return Response({
            'error': 'Channel or template not found'
        }, status=status.HTTP_404_NOT_FOUND)
    except Exception as e:
        return Response({
            'error': str(e)
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['GET'])
@permission_classes([permissions.IsAuthenticated])
def live_notifications(request):
    """
    API endpoint for live notification updates.
    
    Returns recent notifications for real-time dashboard updates.
    """
    # Get recent notifications from last 5 minutes
    recent_time = timezone.now() - timedelta(minutes=5)
    recent_notifications = Notification.objects.filter(
        created_at__gte=recent_time
    ).select_related('channel', 'template').order_by('-created_at')[:20]
    
    serializer = NotificationSerializer(recent_notifications, many=True)
    return Response(serializer.data)
