import re
from rest_framework import generics, permissions, status
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Post, Like, Love, Comment, CommentLike, CommentDislike, Poll, PollOption, PollVote, Bookmark
from .serializers import PostSerializer, PostDetailSerializer, CommentSerializer, PollSerializer
from django.shortcuts import get_object_or_404
from django.contrib.auth import get_user_model

User = get_user_model()


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


# ========================================
# POST VIEWS
# ========================================

class PostCreateView(generics.CreateAPIView):
    serializer_class = PostSerializer
    permission_classes = [permissions.IsAuthenticated]

    def perform_create(self, serializer):
        post = serializer.save(author=self.request.user)
        try:
            from wallet.utils import award_points
            award_points(self.request.user, 20, "post", "Created a post")
        except Exception:
            pass

        # Handle poll creation
        question = self.request.data.get("poll_question", "").strip() if hasattr(self.request.data, "get") else ""
        if question:
            options_raw = self.request.data.get("poll_options", "")
            # options_raw is expected as comma or newline separated, or multiple form fields poll_option_0, poll_option_1...
            options = []
            if options_raw:
                options = [o.strip() for o in options_raw.replace("\n", ",").split(",") if o.strip()]
            else:
                i = 0
                while True:
                    val = self.request.data.get(f"poll_option_{i}")
                    if not val:
                        break
                    options.append(val.strip())
                    i += 1
            if len(options) >= 2:
                poll = Poll.objects.create(post=post, question=question)
                for idx, opt in enumerate(options[:6]):
                    PollOption.objects.create(poll=poll, text=opt, order=idx)

        # Handle @mentions -> notify mentioned users
        try:
            usernames = set(re.findall(r"@(\w+)", post.content or ""))
            if usernames:
                for u in User.objects.filter(username__in=usernames).exclude(id=self.request.user.id):
                    notify(u, "mention", f"{self.request.user.username} mentioned you in a post", link=f"/user/posts", sender=self.request.user)
        except Exception:
            pass


class PostListView(generics.ListAPIView):
    serializer_class = PostSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        from django.db.models import Case, When, Value, BooleanField
        from django.utils import timezone
        user = self.request.user
        following_ids = user.following_relations.values_list("following_id", flat=True)
        now = timezone.now()
        return Post.objects.filter(
            author__id__in=list(following_ids) + [user.id]
        ).select_related("author").prefetch_related(
            "likes", "loves", "comments"
        ).annotate(
            is_boosted=Case(
                When(boosted_until__gt=now, then=Value(True)),
                default=Value(False),
                output_field=BooleanField(),
            )
        ).order_by("-is_boosted", "-created_at")


class PostDetailView(generics.RetrieveAPIView):
    serializer_class = PostDetailSerializer
    permission_classes = [permissions.IsAuthenticated]
    queryset = Post.objects.all()
    lookup_field = "id"
    lookup_url_kwarg = "post_id"

    def get_queryset(self):
        return Post.objects.select_related("author").prefetch_related(
            "likes", "loves", "comments", "comments__user",
            "comments__comment_likes", "comments__comment_dislikes"
        )


class PostUpdateView(generics.UpdateAPIView):
    serializer_class = PostSerializer
    permission_classes = [permissions.IsAuthenticated]
    queryset = Post.objects.all()
    lookup_field = "id"
    lookup_url_kwarg = "post_id"

    def get_queryset(self):
        return Post.objects.filter(author=self.request.user)


class PostDeleteView(generics.DestroyAPIView):
    permission_classes = [permissions.IsAuthenticated]
    queryset = Post.objects.all()
    lookup_field = "id"
    lookup_url_kwarg = "post_id"

    def get_queryset(self):
        return Post.objects.filter(author=self.request.user)

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response({"message": "Post deleted successfully"}, status=status.HTTP_200_OK)


# ========================================
# POST ENGAGEMENT VIEWS
# ========================================

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

    def post(self, request, post_id):
        post = get_object_or_404(Post, id=post_id)
        like, created = Like.objects.get_or_create(user=request.user, post=post)
        if not created:
            like.delete()
            return Response({"liked": False, "likes_count": post.likes.count(), "message": "Like removed"})
        try:
            if post.author != request.user:
                notify(
                    recipient=post.author,
                    notif_type="post_reaction",
                    title=request.user.username + " liked your post 👍",
                    body=post.content[:60] if post.content else "",
                    link="/user/userposts",
                    sender=request.user,
                )
        except Exception:
            pass
        return Response({"liked": True, "likes_count": post.likes.count(), "message": "Post liked"})


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

    def post(self, request, post_id):
        post = get_object_or_404(Post, id=post_id)
        love, created = Love.objects.get_or_create(user=request.user, post=post)
        if not created:
            love.delete()
            return Response({"loved": False, "loves_count": post.loves.count(), "message": "Love removed"})
        try:
            if post.author != request.user:
                notify(
                    recipient=post.author,
                    notif_type="post_reaction",
                    title=request.user.username + " loved your post ❤️",
                    body=post.content[:60] if post.content else "",
                    link="/user/userposts",
                    sender=request.user,
                )
        except Exception:
            pass
        return Response({"loved": True, "loves_count": post.loves.count(), "message": "Post loved"})


# ========================================
# COMMENT VIEWS
# ========================================

class CommentCreateView(generics.CreateAPIView):
    serializer_class = CommentSerializer
    permission_classes = [permissions.IsAuthenticated]

    def perform_create(self, serializer):
        post_id = self.kwargs.get("post_id")
        post = get_object_or_404(Post, id=post_id)
        comment = serializer.save(user=self.request.user, post=post)
        try:
            if post.author != self.request.user:
                notify(
                    recipient=post.author,
                    notif_type="post_comment",
                    title=self.request.user.username + " commented on your post 💬",
                    body=comment.text[:60] if comment.text else "",
                    link="/user/userposts",
                    sender=self.request.user,
                )
        except Exception:
            pass

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(
            {"message": "Comment added successfully", "comment": serializer.data},
            status=status.HTTP_201_CREATED,
            headers=headers
        )


class CommentListView(generics.ListAPIView):
    serializer_class = CommentSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        post_id = self.kwargs.get("post_id")
        return Comment.objects.filter(post__id=post_id).select_related(
            "user", "post"
        ).prefetch_related(
            "comment_likes", "comment_dislikes"
        ).order_by("created_at")


class CommentUpdateView(generics.UpdateAPIView):
    serializer_class = CommentSerializer
    permission_classes = [permissions.IsAuthenticated]
    queryset = Comment.objects.all()
    lookup_field = "id"
    lookup_url_kwarg = "comment_id"

    def get_queryset(self):
        return Comment.objects.filter(user=self.request.user)

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop("partial", False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        return Response({"message": "Comment updated successfully", "comment": serializer.data})


class CommentDeleteView(generics.DestroyAPIView):
    permission_classes = [permissions.IsAuthenticated]
    queryset = Comment.objects.all()
    lookup_field = "id"
    lookup_url_kwarg = "comment_id"

    def get_queryset(self):
        return Comment.objects.filter(user=self.request.user)

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response({"message": "Comment deleted successfully"}, status=status.HTTP_200_OK)


# ========================================
# COMMENT ENGAGEMENT VIEWS
# ========================================

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

    def post(self, request, comment_id):
        comment = get_object_or_404(Comment, id=comment_id)
        CommentDislike.objects.filter(user=request.user, comment=comment).delete()
        like, created = CommentLike.objects.get_or_create(user=request.user, comment=comment)
        if not created:
            like.delete()
            return Response({
                "liked": False,
                "likes_count": comment.comment_likes.count(),
                "dislikes_count": comment.comment_dislikes.count(),
                "message": "Like removed"
            })
        return Response({
            "liked": True,
            "likes_count": comment.comment_likes.count(),
            "dislikes_count": comment.comment_dislikes.count(),
            "message": "Comment liked"
        })


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

    def post(self, request, comment_id):
        comment = get_object_or_404(Comment, id=comment_id)
        CommentLike.objects.filter(user=request.user, comment=comment).delete()
        dislike, created = CommentDislike.objects.get_or_create(user=request.user, comment=comment)
        if not created:
            dislike.delete()
            return Response({
                "disliked": False,
                "likes_count": comment.comment_likes.count(),
                "dislikes_count": comment.comment_dislikes.count(),
                "message": "Dislike removed"
            })
        return Response({
            "disliked": True,
            "likes_count": comment.comment_likes.count(),
            "dislikes_count": comment.comment_dislikes.count(),
            "message": "Comment disliked"
        })


# ========================================
# USER'S OWN POSTS VIEW
# ========================================

class UserPostsView(generics.ListAPIView):
    serializer_class = PostSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        from django.utils import timezone
        from django.db.models import Case, When, Value, BooleanField
        now = timezone.now()
        return Post.objects.filter(
            author=self.request.user
        ).select_related("author").prefetch_related(
            "likes", "loves", "comments"
        ).annotate(
            is_boosted=Case(
                When(boosted_until__gt=now, then=Value(True)),
                default=Value(False),
                output_field=BooleanField(),
            )
        ).order_by("-is_boosted", "-created_at")


# ========================================
# POLL VIEWS
# ========================================
class PollVoteView(APIView):
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, option_id):
        option = get_object_or_404(PollOption, pk=option_id)
        poll = option.poll

        PollVote.objects.filter(user=request.user, option__poll=poll).delete()
        PollVote.objects.create(user=request.user, option=option)

        return Response(PollSerializer(poll, context={"request": request}).data)


# ========================================
# BOOKMARK VIEWS
# ========================================
class BookmarkToggleView(APIView):
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, post_id):
        post = get_object_or_404(Post, pk=post_id)
        bm, created = Bookmark.objects.get_or_create(user=request.user, post=post)
        if not created:
            bm.delete()
            return Response({"bookmarked": False})
        return Response({"bookmarked": True})


class BookmarkListView(generics.ListAPIView):
    serializer_class = PostSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        post_ids = Bookmark.objects.filter(user=self.request.user).values_list("post_id", flat=True)
        return Post.objects.filter(id__in=post_ids).select_related("author").prefetch_related("likes","loves","comments")
