from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
from django.shortcuts import get_object_or_404
from django.contrib.auth import get_user_model

from .models import Notification, NotificationPreference, UserNotificationPreference, CategoryNotificationPreference, FollowRequest
from .serializers import NotificationSerializer, NotificationPreferenceSerializer, UserNotificationPreferenceSerializer, CategoryNotificationPreferenceSerializer, FollowRequestSerializer
from .utils import create_notification, delete_related_notifications, get_unread_count
from follows.models import FollowUser

User = get_user_model()


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def list_notifications(request):
    """List all notifications for the current user"""
    notifications = Notification.objects.filter(recipient=request.user)

    # Pagination
    paginator = PageNumberPagination()
    paginator.page_size = 20
    result_page = paginator.paginate_queryset(notifications, request)

    serializer = NotificationSerializer(result_page, many=True)
    return paginator.get_paginated_response(serializer.data)


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_unread_count_view(request):
    """Get count of unread notifications"""
    count = get_unread_count(request.user)
    return Response({'unread_count': count})


@api_view(['PUT'])
@permission_classes([IsAuthenticated])
def mark_notification_as_read(request, notification_id):
    """Mark a specific notification as read"""
    notification = get_object_or_404(Notification, id=notification_id, recipient=request.user)
    notification.is_read = True
    notification.save()

    serializer = NotificationSerializer(notification)
    return Response(serializer.data)


@api_view(['PUT'])
@permission_classes([IsAuthenticated])
def mark_all_as_read(request):
    """Mark all notifications as read for the current user"""
    Notification.objects.filter(recipient=request.user, is_read=False).update(is_read=True)
    return Response({'message': 'All notifications marked as read'})


@api_view(['DELETE'])
@permission_classes([IsAuthenticated])
def delete_notification(request, notification_id):
    """Delete a specific notification"""
    notification = get_object_or_404(Notification, id=notification_id, recipient=request.user)
    notification.delete()
    return Response({'message': 'Notification deleted successfully'}, status=status.HTTP_200_OK)


@api_view(['GET', 'PUT'])
@permission_classes([IsAuthenticated])
def notification_preferences(request):
    """Get or update global notification preferences"""
    preferences, created = NotificationPreference.objects.get_or_create(user=request.user)

    if request.method == 'GET':
        serializer = NotificationPreferenceSerializer(preferences)
        return Response(serializer.data)

    elif request.method == 'PUT':
        serializer = NotificationPreferenceSerializer(preferences, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(['GET', 'PUT'])
@permission_classes([IsAuthenticated])
def user_notification_preference(request, user_id):
    """Get or update notification preference for a specific user"""
    target_user = get_object_or_404(User, id=user_id)

    # Check if user follows the target user
    is_following = FollowUser.objects.filter(follower=request.user, followed=target_user).exists()
    if not is_following:
        return Response({'error': 'You must follow this user to set notification preferences'}, status=status.HTTP_400_BAD_REQUEST)

    preference, created = UserNotificationPreference.objects.get_or_create(
        user=request.user,
        target_user=target_user
    )

    if request.method == 'GET':
        serializer = UserNotificationPreferenceSerializer(preference)
        return Response(serializer.data)

    elif request.method == 'PUT':
        notify_on_new_post = request.data.get('notify_on_new_post', False)
        preference.notify_on_new_post = notify_on_new_post
        preference.save()

        serializer = UserNotificationPreferenceSerializer(preference)
        return Response(serializer.data)


@api_view(['GET', 'PUT'])
@permission_classes([IsAuthenticated])
def category_notification_preference(request, category_id):
    """Get or update notification preference for a specific category"""
    from categories.models import Category
    from follows.models import FollowCategory

    category = get_object_or_404(Category, id=category_id)

    # Check if user follows the category
    is_following = FollowCategory.objects.filter(user=request.user, category=category).exists()
    if not is_following:
        return Response({'error': 'You must follow this category to set notification preferences'}, status=status.HTTP_400_BAD_REQUEST)

    preference, created = CategoryNotificationPreference.objects.get_or_create(
        user=request.user,
        category=category
    )

    if request.method == 'GET':
        serializer = CategoryNotificationPreferenceSerializer(preference)
        return Response(serializer.data)

    elif request.method == 'PUT':
        notify_on_new_post = request.data.get('notify_on_new_post', False)
        preference.notify_on_new_post = notify_on_new_post
        preference.save()

        serializer = CategoryNotificationPreferenceSerializer(preference)
        return Response(serializer.data)


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def list_follow_requests(request):
    """List all pending follow requests for the current user"""
    follow_requests = FollowRequest.objects.filter(target=request.user, status='pending')

    # Pagination
    paginator = PageNumberPagination()
    paginator.page_size = 20
    result_page = paginator.paginate_queryset(follow_requests, request)

    serializer = FollowRequestSerializer(result_page, many=True)
    return paginator.get_paginated_response(serializer.data)


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def list_sent_follow_requests(request):
    """List all pending follow requests sent by the current user"""
    follow_requests = FollowRequest.objects.filter(requester=request.user, status='pending')

    # Pagination
    paginator = PageNumberPagination()
    paginator.page_size = 20
    result_page = paginator.paginate_queryset(follow_requests, request)

    serializer = FollowRequestSerializer(result_page, many=True)
    return paginator.get_paginated_response(serializer.data)


@api_view(['POST'])
@permission_classes([IsAuthenticated])
def accept_follow_request(request, request_id):
    """Accept a follow request"""
    follow_request = get_object_or_404(FollowRequest, id=request_id, target=request.user, status='pending')

    # Update status
    follow_request.status = 'accepted'
    follow_request.save()

    # Create the actual follow relationship
    FollowUser.objects.create(
        follower=follow_request.requester,
        followed=follow_request.target
    )

    # Create notification for requester
    create_notification(
        recipient=follow_request.requester,
        sender=request.user,
        notification_type='follow_accepted',
        content=f'{request.user.first_name} {request.user.last_name} accepted your follow request'
    )

    # Delete the follow_request notification and replace with follow notification
    delete_related_notifications(
        notification_type='follow_request',
        sender=follow_request.requester,
        recipient=request.user
    )

    return Response({'message': 'Follow request accepted'}, status=status.HTTP_200_OK)


@api_view(['POST'])
@permission_classes([IsAuthenticated])
def reject_follow_request(request, request_id):
    """Reject a follow request"""
    follow_request = get_object_or_404(FollowRequest, id=request_id, target=request.user, status='pending')

    # Update status
    follow_request.status = 'rejected'
    follow_request.save()

    # Delete the follow_request notification
    delete_related_notifications(
        notification_type='follow_request',
        sender=follow_request.requester,
        recipient=request.user
    )

    return Response({'message': 'Follow request rejected'}, status=status.HTTP_200_OK)


@api_view(['DELETE'])
@permission_classes([IsAuthenticated])
def cancel_follow_request(request, request_id):
    """Cancel a sent follow request"""
    follow_request = get_object_or_404(FollowRequest, id=request_id, requester=request.user, status='pending')

    # Delete the follow_request notification
    delete_related_notifications(
        notification_type='follow_request',
        sender=request.user,
        recipient=follow_request.target
    )

    # Delete the follow request
    follow_request.delete()

    return Response({'message': 'Follow request cancelled'}, status=status.HTTP_200_OK)
