from .models import Notification, NotificationPreference, UserNotificationPreference, CategoryNotificationPreference
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
from .serializers import NotificationSerializer


def create_notification(recipient, sender, notification_type, content, related_post=None, related_comment=None, related_category=None):
    """
    Create a notification with preference checks

    Args:
        recipient: User who will receive the notification
        sender: User who triggered the notification (can be None)
        notification_type: Type of notification
        content: Notification message
        related_post: Related post object (optional)
        related_comment: Related comment object (optional)
        related_category: Related category object (optional)

    Returns:
        Notification object if created, None if preferences blocked it
    """
    # Get or create user preferences
    preferences, created = NotificationPreference.objects.get_or_create(user=recipient)

    # Check if notification should be sent based on preferences
    should_notify = True

    if notification_type in ['follow', 'follow_request', 'follow_accepted']:
        should_notify = preferences.notify_on_follow
    elif notification_type in ['like_post', 'like_comment']:
        should_notify = preferences.notify_on_like
    elif notification_type == 'comment':
        should_notify = preferences.notify_on_comment
    elif notification_type == 'new_post_user':
        # Check per-user preference first (takes precedence)
        if sender:
            user_pref = UserNotificationPreference.objects.filter(
                user=recipient,
                target_user=sender
            ).first()
            if user_pref:
                # Per-user preference exists, use it
                should_notify = user_pref.notify_on_new_post
            else:
                # No per-user preference, fall back to global
                should_notify = preferences.notify_on_followed_user_post
        else:
            should_notify = preferences.notify_on_followed_user_post
    elif notification_type == 'new_post_category':
        # Check per-category preference first (takes precedence)
        if related_category:
            cat_pref = CategoryNotificationPreference.objects.filter(
                user=recipient,
                category=related_category
            ).first()
            if cat_pref:
                # Per-category preference exists, use it
                should_notify = cat_pref.notify_on_new_post
            else:
                # No per-category preference, fall back to global
                should_notify = preferences.notify_on_followed_category_post
        else:
            should_notify = preferences.notify_on_followed_category_post

    if not should_notify:
        return None

    # Create the notification
    notification = Notification.objects.create(
        recipient=recipient,
        sender=sender,
        notification_type=notification_type,
        content=content,
        related_post=related_post,
        related_comment=related_comment,
        related_category=related_category
    )

    # Broadcast to user's personal room for real-time updates
    channel_layer = get_channel_layer()
    if channel_layer:
        serializer = NotificationSerializer(notification)
        async_to_sync(channel_layer.group_send)(
            f"user_{recipient.id}",
            {
                "type": "new_notification",
                "notification": serializer.data
            }
        )

    return notification


def delete_related_notifications(notification_type, sender=None, recipient=None, related_post=None, related_comment=None):
    """
    Delete notifications when an action is undone (unlike, unfollow, etc.)

    Args:
        notification_type: Type of notification to delete
        sender: User who sent the notification
        recipient: User who received the notification
        related_post: Related post object
        related_comment: Related comment object
    """
    filters = {'notification_type': notification_type}

    if sender:
        filters['sender'] = sender
    if recipient:
        filters['recipient'] = recipient
    if related_post:
        filters['related_post'] = related_post
    if related_comment:
        filters['related_comment'] = related_comment

    Notification.objects.filter(**filters).delete()


def get_unread_count(user):
    """
    Get the count of unread notifications for a user

    Args:
        user: User object

    Returns:
        Integer count of unread notifications
    """
    return Notification.objects.filter(recipient=user, is_read=False).count()
