"""
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,
    NotificationPreference, NotificationSubscription, NotificationHistory
)
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,
    NotificationPreferenceSerializer, NotificationSubscriptionSerializer,
    NotificationHistorySerializer
)


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)
