from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework import status
from django.db import models
from django.shortcuts import get_object_or_404
from .models import FriendRequest, Friendship
from .serializers import FriendRequestSerializer, FriendshipSerializer
from account.models import User


def auto_follow(user_a, user_b):
    from followers.models import Follow
    Follow.objects.get_or_create(follower=user_a, following=user_b)
    Follow.objects.get_or_create(follower=user_b, following=user_a)
    for u in [user_a, user_b]:
        u.followers_count = Follow.objects.filter(following=u).count()
        u.following_count = Follow.objects.filter(follower=u).count()
        u.save(update_fields=["followers_count", "following_count"])


def notify(recipient, notif_type, title, body="", link="", sender=None):
    try:
        from notifications.utils import create_notification
        create_notification(
            recipient=recipient, notif_type=notif_type,
            title=title, body=body, link=link, sender=sender
        )
    except Exception:
        pass


class SendFriendRequestView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request, user_id):
        receiver = get_object_or_404(User, id=user_id)
        if receiver == request.user:
            return Response({"detail": "You cannot send a request to yourself."}, status=400)
        if Friendship.are_friends(request.user, receiver):
            return Response({"detail": "Already friends."}, status=400)
        existing = FriendRequest.objects.filter(
            sender=request.user, receiver=receiver
        ).first()
        if existing:
            return Response({"detail": "Request already sent.", "status": existing.status}, status=400)

        # Check reverse — auto-accept
        reverse = FriendRequest.objects.filter(
            sender=receiver, receiver=request.user, status="pending"
        ).first()
        if reverse:
            reverse.status = "accepted"
            reverse.save()
            u1, u2 = sorted([request.user, receiver], key=lambda u: u.id)
            Friendship.objects.get_or_create(user1=u1, user2=u2)
            auto_follow(request.user, receiver)
            try:
                notify(
                    recipient=receiver,
                    notif_type="friend_accepted",
                    title=request.user.username + " accepted your friend request",
                    link="/user/userlist",
                    sender=request.user,
                )
            except Exception:
                pass
            return Response({"detail": "Friend request accepted! You are now friends."})

        fr = FriendRequest.objects.create(sender=request.user, receiver=receiver)
        try:
            notify(
                recipient=receiver,
                notif_type="friend_request",
                title=request.user.username + " sent you a friend request",
                link="/user/userlist",
                sender=request.user,
            )
        except Exception:
            pass

        serializer = FriendRequestSerializer(fr, context={"request": request})
        return Response(serializer.data, status=201)


class RespondFriendRequestView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request, request_id):
        fr = get_object_or_404(
            FriendRequest, id=request_id,
            receiver=request.user, status="pending"
        )
        action = request.data.get("action")
        if action == "accept":
            fr.status = "accepted"
            fr.save()
            u1, u2 = sorted([fr.sender, fr.receiver], key=lambda u: u.id)
            Friendship.objects.get_or_create(user1=u1, user2=u2)
            auto_follow(fr.sender, fr.receiver)
            try:
                notify(
                    recipient=fr.sender,
                    notif_type="friend_accepted",
                    title=request.user.username + " accepted your friend request",
                    body="You are now friends with " + request.user.username,
                    link="/user/userlist",
                    sender=request.user,
                )
            except Exception:
                pass
            return Response({"detail": "You are now friends with " + fr.sender.username + "."})
        elif action == "decline":
            fr.status = "declined"
            fr.save()
            return Response({"detail": "Friend request declined."})
        return Response({"detail": "Invalid action."}, status=400)


class FriendRequestListView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        requests = FriendRequest.objects.filter(
            receiver=request.user, status="pending"
        ).select_related("sender")
        serializer = FriendRequestSerializer(
            requests, many=True, context={"request": request}
        )
        return Response(serializer.data)


class FriendListView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        friendships = Friendship.objects.filter(
            models.Q(user1=request.user) | models.Q(user2=request.user)
        ).select_related("user1", "user2")
        serializer = FriendshipSerializer(
            friendships, many=True, context={"request": request}
        )
        return Response(serializer.data)


class UnfriendView(APIView):
    permission_classes = [IsAuthenticated]

    def delete(self, request, user_id):
        other = get_object_or_404(User, id=user_id)
        u1, u2 = sorted([request.user, other], key=lambda u: u.id)
        Friendship.objects.filter(user1=u1, user2=u2).delete()
        return Response({"detail": "Unfriended."})


class FriendStatusView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, user_id):
        other = get_object_or_404(User, id=user_id)
        are_friends = Friendship.are_friends(request.user, other)
        pending_sent = FriendRequest.objects.filter(
            sender=request.user, receiver=other, status="pending"
        ).exists()
        pending_received = FriendRequest.objects.filter(
            sender=other, receiver=request.user, status="pending"
        ).exists()
        return Response({
            "are_friends":       are_friends,
            "pending_sent":      pending_sent,
            "pending_received":  pending_received,
        })