from django.db import IntegrityError from django.db.models import Count from rest_framework import status from rest_framework.exceptions import NotFound from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView from apps.reviews.models import Review, ReviewLike from .serializers import ReviewSerializer, ReviewWriteSerializer class ReviewListView(APIView): """فهرستِ عمومیِ نظراتِ تاییدشده — پرلایک‌ترین‌ها اول.""" permission_classes = [IsAuthenticated] def get(self, request): reviews = ( Review.objects.filter(is_approved=True) .select_related("user") .annotate(like_count=Count("likes")) .order_by("-like_count", "-created_at") ) liked_ids = set( ReviewLike.objects.filter(user=request.user, review__in=reviews).values_list( "review_id", flat=True ) ) serializer = ReviewSerializer( reviews, many=True, context={"request": request, "liked_ids": liked_ids} ) return Response(serializer.data) class MyReviewView(APIView): """نظرِ خودِ کاربر — صرف‌نظر از تایید یا نبودنِ آن. یک کاربر همیشه دقیقا صفر یا یک نظر دارد؛ نوشتنِ دوباره همان نظر را جایگزین و تاییدش را ریست می‌کند.""" permission_classes = [IsAuthenticated] def get(self, request): review = Review.objects.filter(user=request.user).first() if review is None: return Response(None) return Response(ReviewSerializer(review, context={"request": request}).data) def patch(self, request): serializer = ReviewWriteSerializer(data=request.data) serializer.is_valid(raise_exception=True) review, _created = Review.objects.update_or_create( user=request.user, defaults={ "body": serializer.validated_data["body"], "is_approved": False, }, ) return Response( ReviewSerializer(review, context={"request": request}).data, status=status.HTTP_200_OK, ) def delete(self, request): Review.objects.filter(user=request.user).delete() return Response(status=status.HTTP_204_NO_CONTENT) class ReviewLikeToggleView(APIView): """لایک/آن‌لایکِ یک نظرِ تاییدشده — لایکِ نظرِ تاییدنشده‌ی خودِ کسی معنی ندارد، چون در فهرستِ عمومی اصلا دیده نمی‌شود.""" permission_classes = [IsAuthenticated] def post(self, request, pk): review = Review.objects.filter(pk=pk, is_approved=True).first() if review is None: raise NotFound("نظر یافت نشد.") deleted, _ = ReviewLike.objects.filter(review=review, user=request.user).delete() if not deleted: try: ReviewLike.objects.create(review=review, user=request.user) except IntegrityError: pass # درخواستِ هم‌زمانِ دوم — بی‌ضرر، نتیجه هرحال «لایک‌شده» است. like_count = review.likes.count() liked_by_me = review.likes.filter(user=request.user).exists() return Response({"like_count": like_count, "liked_by_me": liked_by_me})