from rest_framework import status, permissions
from rest_framework.views import APIView
from .models import Notification
from .serializers import NotificationSerializer
from apps.users.views import api_response
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
from django.utils.html import strip_tags
from django.conf import settings


class NotificationListView(APIView):
    permission_classes = [permissions.IsAuthenticated]

    def get(self, request):
        notifications = Notification.objects.filter(user=request.user)[:50]
        unread_count = Notification.objects.filter(user=request.user, is_read=False).count()
        serializer = NotificationSerializer(notifications, many=True)
        return api_response(data={
            'notifications': serializer.data,
            'unread_count': unread_count
        })


class NotificationMarkReadView(APIView):
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, pk):
        try:
            notification = Notification.objects.get(pk=pk, user=request.user)
        except Notification.DoesNotExist:
            return api_response(message='Not found', status_code=status.HTTP_404_NOT_FOUND)

        notification.is_read = True
        notification.save()
        return api_response(message='Marked as read')


class NotificationMarkAllReadView(APIView):
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request):
        Notification.objects.filter(user=request.user, is_read=False).update(is_read=True)
        return api_response(message='All notifications marked as read')


class NotificationUnreadCountView(APIView):
    permission_classes = [permissions.IsAuthenticated]

    def get(self, request):
        count = Notification.objects.filter(user=request.user, is_read=False).count()
        return api_response(data={'unread_count': count})



def create_notification(user, notif_type, title, message, link=''):
    """Helper to create a notification and push via WebSocket"""
    notification = Notification.objects.create(
        user=user,
        type=notif_type,
        title=title,
        message=message,
        link=link
    )
    
    # Push to WebSocket (wrapped in try-except to prevent crash if Redis/Channels down)
    try:
        channel_layer = get_channel_layer()
        async_to_sync(channel_layer.group_send)(
            f'notifications_{user.id}',
            {
                'type': 'notification_message',
                'data': NotificationSerializer(notification).data
            }
        )
        
        # Push unread count update
        unread_count = Notification.objects.filter(user=user, is_read=False).count()
        async_to_sync(channel_layer.group_send)(
            f'notifications_{user.id}',
            {
                'type': 'unread_update',
                'count': unread_count
            }
        )
    except Exception as e:
        print(f"WebSocket Notification failed: {e}")
    
    # Send Email Notification
    send_notification_email(notification)
    
    return notification


def send_notification_email(notification):
    """Helper to send HTML email for a notification"""
    user = notification.user
    if not user.email:
        return

    subject = f"🔔 {notification.title} | CyberArsenals"
    context = {
        'title': notification.title,
        'message': notification.message,
        'link': notification.link or '/',
        'type_label': notification.get_type_display(),
    }
    
    html_content = render_to_string('emails/notification_email.html', context)
    text_content = strip_tags(html_content)

    email = EmailMultiAlternatives(
        subject,
        text_content,
        settings.DEFAULT_FROM_EMAIL,
        [user.email]
    )
    email.attach_alternative(html_content, "text/html")
    
    try:
        # In a real production app, this would be a Celery task
        email.send(fail_silently=False)
    except Exception as e:
        print(f"Failed to send notification email to {user.email}: {e}")



def notify_users(users, notif_type, title, message, link=''):
    """Bulk notify multiple users and push via WebSocket"""
    notifications = []
    for user in users:
        notifications.append(Notification(
            user=user, type=notif_type, title=title, message=message, link=link
        ))
    
    # Using a simple loop for bulk creation to ensure IDs are generated correctly for serialization
    # or just use create_notification for simplicity if small volume
    for n in notifications:
        create_notification(n.user, n.type, n.title, n.message, n.link)

