"""
Notification API Views.
"""
from django.shortcuts import get_object_or_404
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

from apps.core.tenant.middleware import get_current_tenant

from .models import (
    NotificationCategory,
    NotificationTemplate,
    Notification,
    NotificationLog,
    UserNotificationPreference,
    NotificationChannel,
)
from .serializers import (
    NotificationCategorySerializer,
    NotificationTemplateSerializer,
    NotificationTemplatePreviewSerializer,
    NotificationSerializer,
    NotificationListSerializer,
    NotificationLogSerializer,
    SendNotificationSerializer,
    ScheduleNotificationSerializer,
    UserNotificationPreferenceSerializer,
    UpdatePreferencesSerializer,
    UnreadCountSerializer,
)
from .services import notification_service
from .template_engine import template_engine, TemplateRenderError
from .tasks import send_notification_task


def get_tenant_from_request(request):
    """Get tenant from request or thread local."""
    tenant = getattr(request, 'tenant', None) or get_current_tenant()
    return tenant


def require_tenant(request):
    """Get tenant or raise ValidationError."""
    tenant = get_tenant_from_request(request)
    if tenant is None:
        raise ValidationError({'detail': 'Tenant not found'})
    return tenant


class NotificationCategoryViewSet(viewsets.ModelViewSet):
    """
    ViewSet for managing notification categories.
    
    list: List all categories
    create: Create a new category
    retrieve: Get category details
    update: Update category
    partial_update: Partially update category
    destroy: Delete category
    """
    serializer_class = NotificationCategorySerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [SearchFilter, OrderingFilter]
    search_fields = ['name', 'label']
    ordering_fields = ['name', 'created_at']
    ordering = ['name']
    
    def get_queryset(self):
        tenant = get_tenant_from_request(self.request)
        if tenant is None:
            return NotificationCategory.objects.none()
        return NotificationCategory.objects.filter(tenant=tenant)
    
    def perform_create(self, serializer):
        tenant = require_tenant(self.request)
        serializer.save(tenant=tenant)


class NotificationTemplateViewSet(viewsets.ModelViewSet):
    """
    ViewSet for managing notification templates.
    
    list: List all templates
    create: Create a new template
    retrieve: Get template details
    update: Update template
    partial_update: Partially update template
    destroy: Delete template
    preview: Preview rendered template
    """
    serializer_class = NotificationTemplateSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['channel', 'category', 'is_active']
    search_fields = ['name', 'title', 'content']
    ordering_fields = ['name', 'created_at']
    ordering = ['-created_at']
    
    def get_queryset(self):
        tenant = get_tenant_from_request(self.request)
        if tenant is None:
            return NotificationTemplate.objects.none()
        return NotificationTemplate.objects.filter(tenant=tenant)
    
    def perform_create(self, serializer):
        tenant = require_tenant(self.request)
        serializer.save(tenant=tenant)
    
    @action(detail=True, methods=['post'])
    def preview(self, request, pk=None):
        """Preview a template with sample variables."""
        template = self.get_object()
        serializer = NotificationTemplatePreviewSerializer(data=request.data)
        
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        
        variables = serializer.validated_data.get('variables', {})
        
        try:
            rendered = template_engine.preview(template.content, variables)
            return Response({
                'title': template.title,
                'subject': template.subject,
                'content': rendered,
            })
        except TemplateRenderError as e:
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
    
    @action(detail=False, methods=['post'])
    def validate_template(self, request):
        """Validate template syntax."""
        content = request.data.get('content', '')
        
        is_valid, error = template_engine.validate(content)
        
        return Response({
            'valid': is_valid,
            'error': error,
            'variables': template_engine.extract_variables(content) if is_valid else [],
        })


class NotificationViewSet(viewsets.ReadOnlyModelViewSet):
    """
    ViewSet for viewing notifications.
    Read-only - notifications are created via send endpoints.
    
    list: List user's notifications
    retrieve: Get notification details
    mark_read: Mark notification as read
    mark_all_read: Mark all notifications as read
    """
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, OrderingFilter]
    filterset_fields = ['channel', 'is_read', 'category', 'priority']
    ordering_fields = ['created_at', 'priority']
    ordering = ['-created_at']
    
    def get_queryset(self):
        tenant = get_tenant_from_request(self.request)
        if tenant is None:
            return Notification.objects.none()
        return Notification.objects.filter(
            tenant=tenant,
            user=self.request.user,
        )
    
    def get_serializer_class(self):
        if self.action == 'list':
            return NotificationListSerializer
        return NotificationSerializer
    
    @action(detail=True, methods=['post'])
    def mark_read(self, request, pk=None):
        """Mark a notification as read."""
        notification = self.get_object()
        notification_service.mark_as_read(notification)
        return Response({'status': 'marked as read'})
    
    @action(detail=False, methods=['post'])
    def mark_all_read(self, request):
        """Mark all notifications as read."""
        tenant = get_tenant_from_request(request)
        count = notification_service.mark_all_as_read(request.user, tenant)
        return Response({'status': 'success', 'count': count})
    
    @action(detail=False, methods=['get'])
    def unread_count(self, request):
        """Get count of unread notifications."""
        tenant = get_tenant_from_request(request)
        count = notification_service.get_unread_count(request.user, tenant)
        serializer = UnreadCountSerializer({'count': count})
        return Response(serializer.data)


class NotificationLogViewSet(viewsets.ReadOnlyModelViewSet):
    """
    ViewSet for viewing notification logs.
    Read-only - logs are created automatically.
    
    list: List notification logs
    retrieve: Get log details
    """
    serializer_class = NotificationLogSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, OrderingFilter]
    filterset_fields = ['channel', 'status', 'notification']
    ordering_fields = ['created_at']
    ordering = ['-created_at']
    
    def get_queryset(self):
        tenant = get_tenant_from_request(self.request)
        if tenant is None:
            return NotificationLog.objects.none()
        return NotificationLog.objects.filter(tenant=tenant)


class SendNotificationView(APIView):
    """
    API endpoint for sending notifications.
    """
    permission_classes = [IsAuthenticated]
    
    def post(self, request):
        """Send a notification to one or more users."""
        serializer = SendNotificationSerializer(data=request.data)
        
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        
        data = serializer.validated_data
        tenant = get_tenant_from_request(request)
        
        # Import User model
        from django.contrib.auth import get_user_model
        User = get_user_model()
        
        # Single user
        if data.get('user_id'):
            user = get_object_or_404(User, id=data['user_id'])
            notification = notification_service.send(
                user=user,
                template_name=data.get('template_name'),
                channel=data.get('channel'),
                title=data.get('title'),
                content=data.get('content'),
                variables=data.get('variables', {}),
                priority=data.get('priority'),
                metadata=data.get('metadata', {}),
                tenant=tenant,
            )
            
            if notification:
                return Response(
                    NotificationSerializer(notification).data,
                    status=status.HTTP_201_CREATED
                )
            else:
                return Response(
                    {'error': 'Failed to create notification'},
                    status=status.HTTP_400_BAD_REQUEST
                )
        
        # Bulk send
        if data.get('user_ids'):
            users = User.objects.filter(id__in=data['user_ids'])
            notifications = notification_service.send_bulk(
                users=users,
                template_name=data.get('template_name'),
                variables=data.get('variables', {}),
                priority=data.get('priority'),
                tenant=tenant,
            )
            
            return Response({
                'status': 'success',
                'count': len(notifications),
                'notification_ids': [str(n.id) for n in notifications],
            }, status=status.HTTP_201_CREATED)
        
        return Response(
            {'error': 'Invalid request'},
            status=status.HTTP_400_BAD_REQUEST
        )


class ScheduleNotificationView(APIView):
    """
    API endpoint for scheduling notifications.
    """
    permission_classes = [IsAuthenticated]
    
    def post(self, request):
        """Schedule a notification for later delivery."""
        serializer = ScheduleNotificationSerializer(data=request.data)
        
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        
        data = serializer.validated_data
        tenant = get_tenant_from_request(request)
        
        from django.contrib.auth import get_user_model
        User = get_user_model()
        
        user = get_object_or_404(User, id=data['user_id'])
        
        notification = notification_service.send(
            user=user,
            template_name=data.get('template_name'),
            channel=data.get('channel'),
            title=data.get('title'),
            content=data.get('content'),
            variables=data.get('variables', {}),
            priority=data.get('priority'),
            metadata=data.get('metadata', {}),
            scheduled_at=data['scheduled_at'],
            tenant=tenant,
        )
        
        if notification:
            return Response(
                NotificationSerializer(notification).data,
                status=status.HTTP_201_CREATED
            )
        else:
            return Response(
                {'error': 'Failed to schedule notification'},
                status=status.HTTP_400_BAD_REQUEST
            )


class UserNotificationPreferenceViewSet(viewsets.ModelViewSet):
    """
    ViewSet for managing user notification preferences.
    """
    serializer_class = UserNotificationPreferenceSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        tenant = get_tenant_from_request(self.request)
        if tenant is None:
            return UserNotificationPreference.objects.none()
        return UserNotificationPreference.objects.filter(
            tenant=tenant,
            user=self.request.user,
        )
    
    def perform_create(self, serializer):
        tenant = require_tenant(self.request)
        serializer.save(tenant=tenant, user=self.request.user)
    
    @action(detail=False, methods=['post'])
    def bulk_update(self, request):
        """Bulk update preferences."""
        serializer = UpdatePreferencesSerializer(data=request.data)
        
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        
        tenant = require_tenant(request)
        preferences = serializer.validated_data['preferences']
        
        updated = []
        for pref_data in preferences:
            category_id = pref_data.pop('category_id')
            
            pref, created = UserNotificationPreference.objects.update_or_create(
                tenant=tenant,
                user=request.user,
                category_id=category_id,
                defaults=pref_data,
            )
            updated.append(pref)
        
        return Response(
            UserNotificationPreferenceSerializer(updated, many=True).data
        )
