from rest_framework import generics, status, permissions
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.pagination import PageNumberPagination
from django.db.models import Q, Count, Avg, Case, When, IntegerField, Exists, OuterRef, Value
from django.utils import timezone
from django.core.cache import cache
from .models import Product, ProductImage, Wishlist, Review, ProductLike, ProductDislike, ProductComment, RecentlyViewed
from .serializers import (
    ProductSerializer, ProductDetailSerializer,
    ProductCreateSerializer, ProductUpdateSerializer,
    WishlistSerializer, ReviewSerializer,
    ProductCommentSerializer, ProductLikeSerializer
)


class IsVendor(permissions.BasePermission):
    """Permission class for vendor-only access"""
    def has_permission(self, request, view):
        return (
            request.user.is_authenticated and
            request.user.user_type == 'vendor' and
            hasattr(request.user, 'vendor_profile')
        )


class IsBuyer(permissions.BasePermission):
    """Permission class for buyer-only access"""
    def has_permission(self, request, view):
        return (
            request.user.is_authenticated and
            request.user.user_type == 'buyer'
        )


class IsProductOwner(permissions.BasePermission):
    """Permission to check if user owns the product"""
    def has_object_permission(self, request, view, obj):
        return obj.vendor.user == request.user


# Public Product Views
class ProductListView(generics.ListAPIView):
    """List all active products (public)"""
    serializer_class = ProductSerializer
    permission_classes = [permissions.AllowAny]

    def get_queryset(self):
        queryset = Product.objects.filter(
            status__in=['active', 'coming_soon']
        ).select_related('vendor', 'vendor__user')

        # Filter by vendor slug
        vendor_slug = self.request.query_params.get('vendor_slug')
        if vendor_slug:
            queryset = queryset.filter(vendor__slug=vendor_slug)

        # Filter by category
        category = self.request.query_params.get('category')
        if category:
            queryset = queryset.filter(category=category)

        # Filter by condition
        condition = self.request.query_params.get('condition')
        if condition:
            queryset = queryset.filter(condition=condition)

        # Filter by county (via vendor)
        county = self.request.query_params.get('county')
        if county:
            queryset = queryset.filter(vendor__user__county=county)

        # Filter by price range
        min_price = self.request.query_params.get('min_price')
        max_price = self.request.query_params.get('max_price')
        if min_price:
            queryset = queryset.filter(price__gte=min_price)
        if max_price:
            queryset = queryset.filter(price__lte=max_price)

        # Search by name or description
        search = self.request.query_params.get('search')
        if search:
            queryset = queryset.filter(
                Q(name__icontains=search) |
                Q(description__icontains=search) |
                Q(tags__icontains=search)
            )

        # Filter by featured
        featured = self.request.query_params.get('featured')
        if featured == 'true':
            queryset = queryset.filter(is_featured=True)

        # Filter by negotiable
        negotiable = self.request.query_params.get('negotiable')
        if negotiable == 'true':
            queryset = queryset.filter(is_negotiable=True)

        # Priority annotation: sponsored > verified > pro > default
        from promotions.utils import annotate_priority
        queryset = annotate_priority(queryset, 'product')

        return queryset.order_by('-priority', '-created_at')


class ProductDetailView(generics.RetrieveAPIView):
    """Get product details (public) - supports slug, UUID, and ID lookup"""
    serializer_class = ProductDetailSerializer
    permission_classes = [permissions.AllowAny]
    queryset = Product.objects.filter(status__in=['active', 'coming_soon'])
    lookup_field = 'uuid'

    def get_object(self):
        # Support slug lookup via separate URL pattern
        slug = self.kwargs.get('slug')
        if slug:
            queryset = self.get_queryset()
            try:
                return queryset.get(slug=slug)
            except Product.DoesNotExist:
                from django.http import Http404
                raise Http404("Product not found")

        lookup_value = self.kwargs.get('uuid')
        queryset = self.get_queryset()

        # Try UUID first, then fall back to ID
        try:
            import uuid as uuid_module
            uuid_module.UUID(lookup_value)
            obj = queryset.get(uuid=lookup_value)
        except (ValueError, Product.DoesNotExist):
            # Try as integer ID
            try:
                obj = queryset.get(pk=int(lookup_value))
            except (ValueError, Product.DoesNotExist):
                from django.http import Http404
                raise Http404("Product not found")

        return obj

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        # Increment view count
        instance.views += 1
        instance.save(update_fields=['views'])
        serializer = self.get_serializer(instance)
        return Response(serializer.data)


class VendorProductsView(generics.ListAPIView):
    """List products by a specific vendor (public)"""
    serializer_class = ProductSerializer
    permission_classes = [permissions.AllowAny]

    def get_queryset(self):
        vendor_id = self.kwargs.get('vendor_id')
        return Product.objects.filter(
            vendor_id=vendor_id,
            status__in=['active', 'coming_soon']
        )


# Vendor Product Management Views
class VendorMyProductsView(APIView):
    """List vendor's own products"""
    permission_classes = [IsVendor]

    def get(self, request):
        products = Product.objects.filter(
            vendor=request.user.vendor_profile
        ).exclude(status='deleted')
        serializer = ProductSerializer(products, many=True, context={'request': request})
        return Response({
            'success': True,
            'data': serializer.data
        }, status=status.HTTP_200_OK)


class ProductCreateView(generics.CreateAPIView):
    """Create a new product"""
    serializer_class = ProductCreateSerializer
    permission_classes = [IsVendor]
    parser_classes = [MultiPartParser, FormParser]


class ProductUpdateView(generics.UpdateAPIView):
    """Update a product"""
    serializer_class = ProductUpdateSerializer
    permission_classes = [IsVendor, IsProductOwner]
    parser_classes = [MultiPartParser, FormParser]

    def get_queryset(self):
        return Product.objects.filter(
            vendor=self.request.user.vendor_profile
        ).exclude(status='deleted')


class ProductDeleteView(APIView):
    """Delete (soft) a product"""
    permission_classes = [IsVendor]

    def delete(self, request, pk):
        try:
            product = Product.objects.get(
                pk=pk,
                vendor=request.user.vendor_profile
            )
            product.status = 'deleted'
            product.save()

            # Update vendor's product count
            request.user.vendor_profile.total_products -= 1
            request.user.vendor_profile.save()

            return Response(
                {"message": "Product deleted successfully"},
                status=status.HTTP_200_OK
            )
        except Product.DoesNotExist:
            return Response(
                {"error": "Product not found"},
                status=status.HTTP_404_NOT_FOUND
            )


# Wishlist Views
class WishlistView(APIView):
    """List buyer's wishlist"""
    permission_classes = [IsBuyer]

    def get(self, request):
        wishlists = Wishlist.objects.filter(buyer=request.user).select_related('product', 'product__vendor')
        data = []
        for w in wishlists:
            data.append({
                'id': w.id,
                'product': {
                    'id': w.product.id,
                    'uuid': str(w.product.uuid),
                    'slug': w.product.slug,
                    'name': w.product.name,
                    'price': str(w.product.price),
                    'category': w.product.category,
                    'primary_image': request.build_absolute_uri(w.product.primary_image.url) if w.product.primary_image else None,
                    'vendor_name': w.product.vendor.shop_name,
                    'is_available': w.product.is_available,
                },
                'added_at': w.created_at.isoformat(),
            })
        return Response({
            'success': True,
            'data': data
        }, status=status.HTTP_200_OK)


class WishlistAddView(generics.CreateAPIView):
    """Add product to wishlist"""
    serializer_class = WishlistSerializer
    permission_classes = [IsBuyer]


class WishlistRemoveView(APIView):
    """Remove product from wishlist"""
    permission_classes = [IsBuyer]

    def delete(self, request, product_id):
        try:
            wishlist = Wishlist.objects.get(
                buyer=request.user,
                product_id=product_id
            )
            wishlist.delete()

            # Update buyer's wishlist count
            if hasattr(request.user, 'buyer_profile'):
                request.user.buyer_profile.wishlist_count -= 1
                request.user.buyer_profile.save()

            return Response(
                {"message": "Product removed from wishlist"},
                status=status.HTTP_200_OK
            )
        except Wishlist.DoesNotExist:
            return Response(
                {"error": "Product not in wishlist"},
                status=status.HTTP_404_NOT_FOUND
            )


# Review Views
class MyReviewsView(APIView):
    """List buyer's own reviews"""
    permission_classes = [IsBuyer]

    def get(self, request):
        reviews = Review.objects.filter(buyer=request.user).select_related('product', 'product__vendor')
        data = []
        for r in reviews:
            data.append({
                'id': r.id,
                'product': {
                    'id': r.product.id,
                    'uuid': str(r.product.uuid),
                    'slug': r.product.slug,
                    'name': r.product.name,
                    'category': r.product.category,
                    'primary_image': request.build_absolute_uri(r.product.primary_image.url) if r.product.primary_image else None,
                    'vendor_name': r.product.vendor.shop_name,
                },
                'rating': r.rating,
                'comment': r.comment,
                'created_at': r.created_at.isoformat(),
            })
        return Response({
            'success': True,
            'data': data
        }, status=status.HTTP_200_OK)


class ProductReviewsListView(APIView):
    """List reviews for a specific product"""
    permission_classes = [AllowAny]

    def get(self, request, product_id):
        try:
            product = Product.objects.get(id=product_id)
        except Product.DoesNotExist:
            return Response({'error': 'Product not found'}, status=status.HTTP_404_NOT_FOUND)

        reviews = Review.objects.filter(product=product).select_related('buyer').order_by('-created_at')

        # Check if current user has already reviewed
        user_review = None
        if request.user.is_authenticated:
            user_review = reviews.filter(buyer=request.user).first()

        data = []
        for r in reviews:
            data.append({
                'id': r.id,
                'buyer': {
                    'id': r.buyer.id,
                    'full_name': r.buyer.full_name,
                    'profile_photo': request.build_absolute_uri(r.buyer.profile_photo.url) if r.buyer.profile_photo else None,
                },
                'rating': r.rating,
                'comment': r.comment,
                'created_at': r.created_at.isoformat(),
                'is_own': request.user.is_authenticated and r.buyer.id == request.user.id,
            })

        # Calculate rating stats
        total_reviews = reviews.count()
        avg_rating = reviews.aggregate(avg=Avg('rating'))['avg'] or 0
        rating_breakdown = {}
        for i in range(1, 6):
            rating_breakdown[i] = reviews.filter(rating=i).count()

        return Response({
            'success': True,
            'data': {
                'reviews': data,
                'total_reviews': total_reviews,
                'average_rating': round(avg_rating, 1),
                'rating_breakdown': rating_breakdown,
                'user_has_reviewed': user_review is not None,
            }
        }, status=status.HTTP_200_OK)


class ProductReviewCreateView(APIView):
    """Create or update a review for a product"""
    permission_classes = [IsBuyer]

    def post(self, request, product_id):
        try:
            product = Product.objects.get(id=product_id)
        except Product.DoesNotExist:
            return Response({'error': 'Product not found'}, status=status.HTTP_404_NOT_FOUND)

        rating = request.data.get('rating')
        comment = request.data.get('comment', '').strip()

        if not rating or not isinstance(rating, int) or rating < 1 or rating > 5:
            return Response({'error': 'Rating must be between 1 and 5'}, status=status.HTTP_400_BAD_REQUEST)

        # Check if user has already reviewed this product
        review, created = Review.objects.update_or_create(
            buyer=request.user,
            product=product,
            defaults={
                'rating': rating,
                'comment': comment if comment else None,
            }
        )

        return Response({
            'success': True,
            'message': 'Review submitted successfully' if created else 'Review updated successfully',
            'data': {
                'id': review.id,
                'rating': review.rating,
                'comment': review.comment,
                'created_at': review.created_at.isoformat(),
            }
        }, status=status.HTTP_201_CREATED if created else status.HTTP_200_OK)


class ProductReviewDeleteView(APIView):
    """Delete own review for a product"""
    permission_classes = [IsBuyer]

    def delete(self, request, product_id):
        try:
            review = Review.objects.get(buyer=request.user, product_id=product_id)
            review.delete()
            return Response({
                'success': True,
                'message': 'Review deleted successfully'
            }, status=status.HTTP_200_OK)
        except Review.DoesNotExist:
            return Response({'error': 'Review not found'}, status=status.HTTP_404_NOT_FOUND)


class VendorCapabilitiesView(APIView):
    """Get vendor's current capabilities and limits"""
    permission_classes = [IsVendor]

    def get(self, request):
        vendor_profile = request.user.vendor_profile
        return Response({
            "is_upgraded": vendor_profile.is_upgraded,
            "max_products": vendor_profile.max_products,
            "current_products": vendor_profile.total_products,
            "can_add_product": vendor_profile.can_add_product,
            "max_images_per_product": vendor_profile.max_images_per_product,
            "features": {
                "multiple_images": vendor_profile.is_upgraded,
                "video_upload": vendor_profile.is_upgraded,
                "discount_pricing": vendor_profile.is_upgraded,
                "featured_products": vendor_profile.is_upgraded,
            }
        })


# ============== ADMIN PRODUCT VIEWS ==============

class IsAdmin(permissions.BasePermission):
    """Permission class for admin-only access"""
    def has_permission(self, request, view):
        return (
            request.user.is_authenticated and
            request.user.user_type == 'admin'
        )


class AdminProductsListView(APIView):
    """Admin view to list all products"""
    permission_classes = [IsAdmin]

    def get(self, request):
        # Get query parameters
        search = request.query_params.get('search', None)
        category = request.query_params.get('category', None)
        status_filter = request.query_params.get('status', None)
        vendor_id = request.query_params.get('vendor_id', None)
        page = int(request.query_params.get('page', 1))
        limit = int(request.query_params.get('limit', 20))

        products = Product.objects.select_related('vendor__user').order_by('-created_at')

        if search:
            products = products.filter(
                Q(name__icontains=search) |
                Q(description__icontains=search) |
                Q(vendor__shop_name__icontains=search)
            )

        if category:
            products = products.filter(category=category)

        if status_filter:
            products = products.filter(status=status_filter)

        if vendor_id:
            products = products.filter(vendor_id=vendor_id)

        total = products.count()
        start = (page - 1) * limit
        end = start + limit
        products = products[start:end]

        data = [{
            'id': p.id,
            'name': p.name,
            'price': float(p.price),
            'discount_price': float(p.old_price) if p.old_price else None,
            'category': p.category,
            'condition': p.condition,
            'status': p.status,
            'is_featured': p.is_featured,
            'views': p.views,
            'main_image': request.build_absolute_uri(p.primary_image.url) if p.primary_image else None,
            'vendor': {
                'id': p.vendor.id,
                'shop_name': p.vendor.shop_name,
                'user_id': p.vendor.user.id,
            },
            'created_at': p.created_at,
        } for p in products]

        return Response({
            'success': True,
            'data': data,
            'pagination': {
                'total': total,
                'page': page,
                'limit': limit,
                'pages': (total + limit - 1) // limit
            }
        }, status=status.HTTP_200_OK)


class AdminProductDetailView(APIView):
    """Admin view to manage a specific product"""
    permission_classes = [IsAdmin]

    def get(self, request, product_id):
        try:
            product = Product.objects.select_related('vendor__user').get(id=product_id)

            images = ProductImage.objects.filter(product=product)
            images_data = [{'id': img.id, 'image': request.build_absolute_uri(img.image.url)} for img in images]

            data = {
                'id': product.id,
                'name': product.name,
                'description': product.description,
                'price': float(product.price),
                'discount_price': float(product.old_price) if product.old_price else None,
                'category': product.category,
                'condition': product.condition,
                'status': product.status,
                'is_featured': product.is_featured,
                'is_negotiable': product.is_negotiable,
                'views': product.views,
                'main_image': request.build_absolute_uri(product.primary_image.url) if product.primary_image else None,
                'images': images_data,
                'tags': product.tags,
                'vendor': {
                    'id': product.vendor.id,
                    'shop_name': product.vendor.shop_name,
                    'user_id': product.vendor.user.id,
                    'user_name': product.vendor.user.full_name,
                },
                'created_at': product.created_at,
                'updated_at': product.updated_at,
            }

            return Response({
                'success': True,
                'data': data
            }, status=status.HTTP_200_OK)

        except Product.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Product not found'
            }, status=status.HTTP_404_NOT_FOUND)

    def patch(self, request, product_id):
        try:
            product = Product.objects.get(id=product_id)

            # Update allowed fields
            if 'status' in request.data:
                product.status = request.data['status']
            if 'is_featured' in request.data:
                product.is_featured = request.data['is_featured']

            product.save()

            return Response({
                'success': True,
                'message': 'Product updated successfully'
            }, status=status.HTTP_200_OK)

        except Product.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Product not found'
            }, status=status.HTTP_404_NOT_FOUND)

    def delete(self, request, product_id):
        try:
            product = Product.objects.get(id=product_id)
            vendor_profile = product.vendor

            # Hard delete or soft delete based on query param
            hard_delete = request.query_params.get('hard', 'false').lower() == 'true'

            if hard_delete:
                product.delete()
            else:
                product.status = 'deleted'
                product.save()

            # Update vendor's product count
            vendor_profile.total_products = max(0, vendor_profile.total_products - 1)
            vendor_profile.save()

            return Response({
                'success': True,
                'message': 'Product deleted successfully'
            }, status=status.HTTP_200_OK)

        except Product.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Product not found'
            }, status=status.HTTP_404_NOT_FOUND)


# ============== PRODUCT SOCIAL FEATURES ==============

class CommentPagination(PageNumberPagination):
    page_size = 20
    page_size_query_param = 'page_size'
    max_page_size = 50


class ProductLikeToggleView(APIView):
    """Toggle like on a product"""
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, product_id):
        try:
            product = Product.objects.get(id=product_id, status__in=['active', 'coming_soon'])
        except Product.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Product not found'
            }, status=status.HTTP_404_NOT_FOUND)

        like, created = ProductLike.objects.get_or_create(
            user=request.user,
            product=product
        )

        if not created:
            # Unlike - remove the like
            like.delete()
            liked = False
        else:
            # Remove any existing dislike (mutual exclusivity)
            ProductDislike.objects.filter(user=request.user, product=product).delete()
            liked = True

        like_count = ProductLike.objects.filter(product=product).count()
        dislike_count = ProductDislike.objects.filter(product=product).count()
        disliked = ProductDislike.objects.filter(user=request.user, product=product).exists()

        return Response({
            'success': True,
            'liked': liked,
            'like_count': like_count,
            'disliked': disliked,
            'dislike_count': dislike_count
        }, status=status.HTTP_200_OK)


class ProductLikeStatusView(APIView):
    """Get like/dislike status and counts for a product"""
    permission_classes = [permissions.AllowAny]

    def get(self, request, product_id):
        try:
            product = Product.objects.get(id=product_id, status__in=['active', 'coming_soon'])
        except Product.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Product not found'
            }, status=status.HTTP_404_NOT_FOUND)

        like_count = ProductLike.objects.filter(product=product).count()
        dislike_count = ProductDislike.objects.filter(product=product).count()
        liked = False
        disliked = False

        if request.user.is_authenticated:
            liked = ProductLike.objects.filter(
                user=request.user,
                product=product
            ).exists()
            disliked = ProductDislike.objects.filter(
                user=request.user,
                product=product
            ).exists()

        return Response({
            'success': True,
            'liked': liked,
            'like_count': like_count,
            'disliked': disliked,
            'dislike_count': dislike_count
        }, status=status.HTTP_200_OK)


class ProductDislikeToggleView(APIView):
    """Toggle dislike on a product"""
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, product_id):
        try:
            product = Product.objects.get(id=product_id, status__in=['active', 'coming_soon'])
        except Product.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Product not found'
            }, status=status.HTTP_404_NOT_FOUND)

        dislike, created = ProductDislike.objects.get_or_create(
            user=request.user,
            product=product
        )

        if not created:
            # Un-dislike - remove the dislike
            dislike.delete()
            disliked = False
        else:
            # Remove any existing like (mutual exclusivity)
            ProductLike.objects.filter(user=request.user, product=product).delete()
            disliked = True

        like_count = ProductLike.objects.filter(product=product).count()
        dislike_count = ProductDislike.objects.filter(product=product).count()
        liked = ProductLike.objects.filter(user=request.user, product=product).exists()

        return Response({
            'success': True,
            'liked': liked,
            'like_count': like_count,
            'disliked': disliked,
            'dislike_count': dislike_count
        }, status=status.HTTP_200_OK)


class ProductCommentsListView(APIView):
    """List comments for a product (paginated)"""
    permission_classes = [permissions.AllowAny]

    def get(self, request, product_id):
        try:
            product = Product.objects.get(id=product_id, status__in=['active', 'coming_soon'])
        except Product.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Product not found'
            }, status=status.HTTP_404_NOT_FOUND)

        # Get only top-level comments (no parent)
        comments = ProductComment.objects.filter(
            product=product,
            parent__isnull=True,
            is_deleted=False
        ).select_related('user').prefetch_related('replies__user').order_by('-created_at')

        # Pagination
        paginator = CommentPagination()
        page = paginator.paginate_queryset(comments, request)

        serializer = ProductCommentSerializer(page, many=True, context={'request': request})

        return Response({
            'success': True,
            'data': serializer.data,
            'count': comments.count(),
            'next': paginator.get_next_link(),
            'previous': paginator.get_previous_link()
        }, status=status.HTTP_200_OK)


class ProductCommentCreateView(APIView):
    """Create a new comment or reply"""
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request):
        product_id = request.data.get('product_id')
        parent_id = request.data.get('parent_id')
        content = request.data.get('content', '').strip()

        if not product_id:
            return Response({
                'success': False,
                'message': 'Product ID is required'
            }, status=status.HTTP_400_BAD_REQUEST)

        if not content:
            return Response({
                'success': False,
                'message': 'Comment content is required'
            }, status=status.HTTP_400_BAD_REQUEST)

        if len(content) > 1000:
            return Response({
                'success': False,
                'message': 'Comment must be less than 1000 characters'
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            product = Product.objects.get(id=product_id, status__in=['active', 'coming_soon'])
        except Product.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Product not found'
            }, status=status.HTTP_404_NOT_FOUND)

        parent = None
        if parent_id:
            try:
                parent = ProductComment.objects.get(id=parent_id, product=product, is_deleted=False)
            except ProductComment.DoesNotExist:
                return Response({
                    'success': False,
                    'message': 'Parent comment not found'
                }, status=status.HTTP_404_NOT_FOUND)

        comment = ProductComment.objects.create(
            user=request.user,
            product=product,
            parent=parent,
            content=content
        )

        serializer = ProductCommentSerializer(comment, context={'request': request})

        return Response({
            'success': True,
            'message': 'Comment created successfully',
            'data': serializer.data
        }, status=status.HTTP_201_CREATED)


class ProductCommentDeleteView(APIView):
    """Delete own comment (soft delete)"""
    permission_classes = [permissions.IsAuthenticated]

    def delete(self, request, comment_id):
        try:
            comment = ProductComment.objects.get(id=comment_id)
        except ProductComment.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Comment not found'
            }, status=status.HTTP_404_NOT_FOUND)

        # Only allow comment owner or admin to delete
        if comment.user != request.user and request.user.user_type != 'admin':
            return Response({
                'success': False,
                'message': 'You can only delete your own comments'
            }, status=status.HTTP_403_FORBIDDEN)

        comment.is_deleted = True
        comment.save()

        return Response({
            'success': True,
            'message': 'Comment deleted successfully'
        }, status=status.HTTP_200_OK)


class ProductCommentRepliesView(APIView):
    """Get all replies for a specific comment"""
    permission_classes = [permissions.AllowAny]

    def get(self, request, comment_id):
        try:
            comment = ProductComment.objects.get(id=comment_id, is_deleted=False)
        except ProductComment.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Comment not found'
            }, status=status.HTTP_404_NOT_FOUND)

        replies = comment.replies.filter(is_deleted=False).order_by('created_at')
        serializer = ProductCommentSerializer(replies, many=True, context={'request': request})

        return Response({
            'success': True,
            'data': serializer.data
        }, status=status.HTTP_200_OK)


# ============== DISCOVERY FEATURES ==============

class TopShopsView(APIView):
    """Get top shops by follower count"""
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        from accounts.models import VendorProfile, Follow
        from accounts.serializers import VendorProfileSerializer

        limit = int(request.query_params.get('limit', 20))
        verified_only = request.query_params.get('verified', '').lower() in ('true', '1', 'yes')

        # Cache the shops queryset (public data)
        cache_key = f'top_shops_{limit}_v{verified_only}'
        shops = cache.get(cache_key)
        if shops is None:
            qs = VendorProfile.objects.filter(
                user__is_active=True
            ).select_related('user')
            if verified_only:
                verified_qs = qs.filter(is_verified_vendor=True)
                shops = list(verified_qs.order_by('-total_followers')[:limit])
                # Fallback: if no verified vendors, return all vendors
                if not shops:
                    shops = list(qs.order_by('-total_followers')[:limit])
            else:
                shops = list(qs.order_by('-total_followers')[:limit])
            cache.set(cache_key, shops, 120)  # 2 min

        # Get list of vendor IDs the current user follows (per-user, not cached)
        followed_ids = set()
        if request.user.is_authenticated and request.user.user_type == 'buyer':
            followed_ids = set(
                Follow.objects.filter(buyer=request.user)
                .values_list('vendor_id', flat=True)
            )

        serializer = VendorProfileSerializer(
            shops, many=True,
            context={'request': request, 'followed_vendor_ids': followed_ids}
        )

        return Response({
            'success': True,
            'data': serializer.data
        }, status=status.HTTP_200_OK)


class UnderPriceView(APIView):
    """Get products under a certain price"""
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        max_price = request.query_params.get('max', 1000)
        try:
            max_price = float(max_price)
        except ValueError:
            max_price = 1000

        cache_key = f'under_price_{int(max_price)}'
        cached = cache.get(cache_key)
        if cached is not None:
            return Response(cached, status=status.HTTP_200_OK)

        products = Product.objects.filter(
            status__in=['active', 'coming_soon'],
            price__lte=max_price
        ).select_related('vendor').order_by('-created_at')[:50]

        serializer = ProductSerializer(products, many=True, context={'request': request})

        response_data = {
            'success': True,
            'data': serializer.data,
            'max_price': max_price
        }
        cache.set(cache_key, response_data, 180)  # 3 min
        return Response(response_data, status=status.HTTP_200_OK)


class CategoriesView(APIView):
    """Get all categories with product counts"""
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        cached = cache.get('categories_list')
        if cached is not None:
            return Response(cached, status=status.HTTP_200_OK)

        categories = []
        for code, name in Product.CATEGORY_CHOICES:
            count = Product.objects.filter(status__in=['active', 'coming_soon'], category=code).count()
            categories.append({
                'code': code,
                'name': name,
                'product_count': count
            })

        categories.sort(key=lambda x: x['product_count'], reverse=True)

        response_data = {
            'success': True,
            'data': categories
        }
        cache.set('categories_list', response_data, 300)  # 5 min
        return Response(response_data, status=status.HTTP_200_OK)


class ForYouView(APIView):
    """Get personalized products for authenticated users with pagination"""
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        from accounts.models import Follow

        page = int(request.query_params.get('page', 1))
        limit = int(request.query_params.get('limit', 20))
        offset = (page - 1) * limit

        from promotions.utils import annotate_priority
        products_qs = Product.objects.filter(status__in=['active', 'coming_soon']).select_related('vendor')
        products_qs = annotate_priority(products_qs, 'product')

        if request.user.is_authenticated:
            # Follow.vendor_id stores User IDs; convert to VendorProfile IDs for Product filtering
            from accounts.models import VendorProfile
            followed_user_ids = list(
                Follow.objects.filter(buyer=request.user)
                .values_list('vendor_id', flat=True)
            )
            following_profile_ids = list(
                VendorProfile.objects.filter(user_id__in=followed_user_ids)
                .values_list('id', flat=True)
            ) if followed_user_ids else []

            if following_profile_ids:
                following_products = products_qs.filter(
                    vendor_id__in=following_profile_ids
                ).order_by('-priority', '-created_at')
                other_products = products_qs.exclude(
                    vendor_id__in=following_profile_ids
                ).order_by('-priority', '-created_at', '-views')

                all_products = list(following_products) + list(other_products)
                total = len(all_products)
                products = all_products[offset:offset + limit]
            else:
                total = products_qs.count()
                products = list(products_qs.order_by('-priority', '-created_at', '-views')[offset:offset + limit])
        else:
            total = products_qs.count()
            products = list(products_qs.order_by('-priority', '-created_at', '-views')[offset:offset + limit])

        serializer = ProductSerializer(products, many=True, context={'request': request})

        return Response({
            'success': True,
            'data': serializer.data,
            'pagination': {
                'page': page,
                'limit': limit,
                'total': total,
                'has_more': offset + limit < total,
            }
        }, status=status.HTTP_200_OK)


class FollowingVerifiedProductsView(APIView):
    """Products from verified vendors the user follows — one per vendor.
    Fallback chain: followed+verified -> any verified -> followed -> any active."""
    permission_classes = [permissions.IsAuthenticated]

    def get(self, request):
        from accounts.models import Follow, VendorProfile

        # Follow.vendor_id stores User IDs (Follow.vendor FK -> User)
        followed_user_ids = set(
            Follow.objects.filter(buyer=request.user)
            .values_list('vendor_id', flat=True)
        )

        # Product.vendor_id stores VendorProfile PKs (Product.vendor FK -> VendorProfile)
        # So we must convert User IDs -> VendorProfile IDs for product filtering
        vendor_profile_ids = None

        # 1. Try followed + verified
        if followed_user_ids:
            verified_followed = set(
                VendorProfile.objects.filter(
                    user_id__in=followed_user_ids,
                    is_verified_vendor=True,
                ).values_list('id', flat=True)
            )
            if verified_followed:
                vendor_profile_ids = verified_followed

        # 2. Fallback: any verified vendor
        if vendor_profile_ids is None:
            any_verified = set(
                VendorProfile.objects.filter(
                    is_verified_vendor=True,
                ).values_list('id', flat=True)[:20]
            )
            if any_verified:
                vendor_profile_ids = any_verified

        # 3. Fallback: followed vendors (not necessarily verified)
        if vendor_profile_ids is None and followed_user_ids:
            followed_profiles = set(
                VendorProfile.objects.filter(
                    user_id__in=followed_user_ids,
                ).values_list('id', flat=True)
            )
            if followed_profiles:
                vendor_profile_ids = followed_profiles

        from promotions.utils import annotate_priority

        # 4. Fallback: any active products (no vendor filter)
        if vendor_profile_ids is None:
            products = annotate_priority(
                Product.objects.filter(
                    status__in=['active', 'coming_soon'],
                ).select_related('vendor'),
                'product'
            ).order_by('-priority', '-created_at')
        else:
            products = annotate_priority(
                Product.objects.filter(
                    status__in=['active', 'coming_soon'],
                    vendor_id__in=vendor_profile_ids,
                ).select_related('vendor'),
                'product'
            ).order_by('-priority', '-created_at')

        if not products.exists():
            # Final fallback: just get any active products
            products = annotate_priority(
                Product.objects.filter(
                    status__in=['active', 'coming_soon'],
                ).select_related('vendor'),
                'product'
            ).order_by('-priority', '-created_at')

        # One per vendor
        seen_vendors = set()
        unique_products = []
        for p in products:
            if p.vendor_id not in seen_vendors:
                seen_vendors.add(p.vendor_id)
                unique_products.append(p)

        serializer = ProductSerializer(unique_products, many=True, context={'request': request})
        return Response({'success': True, 'data': serializer.data}, status=status.HTTP_200_OK)


class NotFollowingTopShopsView(APIView):
    """Top shops by followers that the user is NOT following.
    Also excludes the user themselves if they are a vendor."""
    permission_classes = [permissions.IsAuthenticated]

    def get(self, request):
        from accounts.models import VendorProfile, Follow

        limit = int(request.query_params.get('limit', 10))

        followed_vendor_ids = set(
            Follow.objects.filter(buyer=request.user)
            .values_list('vendor_id', flat=True)
        )

        # Also exclude the user themselves
        exclude_ids = set(followed_vendor_ids)
        exclude_ids.add(request.user.id)

        shops = VendorProfile.objects.filter(
            user__is_active=True,
        ).select_related('user').order_by('-total_followers')

        # Exclude vendors the user already follows + self
        not_following = [s for s in shops if s.user_id not in exclude_ids][:limit]

        from accounts.serializers import VendorProfileSerializer
        serializer = VendorProfileSerializer(
            not_following, many=True,
            context={'request': request, 'followed_vendor_ids': followed_vendor_ids}
        )
        return Response({'success': True, 'data': serializer.data}, status=status.HTTP_200_OK)


class NearYouView(APIView):
    """Get products from vendors in the same county"""
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        county = request.query_params.get('county')

        # Use user's county if authenticated and no county specified
        if not county and request.user.is_authenticated:
            county = request.user.county

        if not county:
            return Response({
                'success': False,
                'message': 'County is required'
            }, status=status.HTTP_400_BAD_REQUEST)

        from promotions.utils import annotate_priority
        products = annotate_priority(
            Product.objects.filter(
                status__in=['active', 'coming_soon'],
                vendor__user__county__iexact=county
            ).select_related('vendor'),
            'product'
        ).order_by('-priority', '-created_at')[:50]

        serializer = ProductSerializer(products, many=True, context={'request': request})

        return Response({
            'success': True,
            'data': serializer.data,
            'county': county
        }, status=status.HTTP_200_OK)


# ============== YOU MAY ALSO LIKE ==============

class YouMayAlsoLikeView(APIView):
    """Get recommended products based on same category or same vendor"""
    permission_classes = [permissions.AllowAny]

    def get(self, request, product_id):
        try:
            product = Product.objects.get(id=product_id)
        except Product.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Product not found'
            }, status=status.HTTP_404_NOT_FOUND)

        # Get products from the same category (sorted by views)
        same_category = Product.objects.filter(
            status__in=['active', 'coming_soon'],
            category=product.category,
        ).exclude(id=product.id).order_by('-views')[:6]

        # Get products from the same vendor
        same_vendor = Product.objects.filter(
            status__in=['active', 'coming_soon'],
            vendor=product.vendor,
        ).exclude(id=product.id).order_by('-views')[:4]

        # Combine and deduplicate, limit to 8
        seen_ids = set()
        combined = []
        for p in list(same_category) + list(same_vendor):
            if p.id not in seen_ids and len(combined) < 8:
                seen_ids.add(p.id)
                combined.append(p)

        serializer = ProductSerializer(combined, many=True, context={'request': request})

        return Response({
            'success': True,
            'data': serializer.data
        }, status=status.HTTP_200_OK)


# ============== RECENTLY VIEWED ==============

class RecentlyViewedListView(APIView):
    """Get user's recently viewed products"""
    permission_classes = [permissions.IsAuthenticated]

    def get(self, request):
        limit = int(request.query_params.get('limit', 20))

        recently_viewed = RecentlyViewed.objects.filter(
            user=request.user
        ).select_related('product', 'product__vendor').order_by('-viewed_at')[:limit]

        data = []
        for rv in recently_viewed:
            p = rv.product
            data.append({
                'id': p.id,
                'uuid': str(p.uuid),
                'slug': p.slug,
                'name': p.name,
                'price': str(p.price),
                'primary_image': request.build_absolute_uri(p.primary_image.url) if p.primary_image else None,
                'vendor_name': p.vendor.shop_name,
                'vendor_slug': p.vendor.slug,
                'category': p.category,
                'is_available': p.is_available,
                'viewed_at': rv.viewed_at.isoformat(),
            })

        return Response({
            'success': True,
            'data': data
        }, status=status.HTTP_200_OK)


class TrackProductViewView(APIView):
    """Track that a user viewed a product"""
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, product_id):
        try:
            product = Product.objects.get(id=product_id, status__in=['active', 'coming_soon'])
        except Product.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Product not found'
            }, status=status.HTTP_404_NOT_FOUND)

        # Update or create recently viewed entry
        rv, created = RecentlyViewed.objects.update_or_create(
            user=request.user,
            product=product,
            defaults={}  # viewed_at auto-updates
        )

        # Keep only last 50 recently viewed items
        old_views = RecentlyViewed.objects.filter(
            user=request.user
        ).order_by('-viewed_at')[50:]
        RecentlyViewed.objects.filter(id__in=[rv.id for rv in old_views]).delete()

        return Response({
            'success': True,
            'message': 'View tracked'
        }, status=status.HTTP_200_OK)


class ClearRecentlyViewedView(APIView):
    """Clear user's recently viewed history"""
    permission_classes = [permissions.IsAuthenticated]

    def delete(self, request):
        RecentlyViewed.objects.filter(user=request.user).delete()

        return Response({
            'success': True,
            'message': 'Recently viewed history cleared'
        }, status=status.HTTP_200_OK)


# ============== BUYER DASHBOARD ==============

class BuyerDashboardView(APIView):
    """Get buyer dashboard statistics and data"""
    permission_classes = [IsBuyer]

    def get(self, request):
        user = request.user

        # Get profile stats
        profile_data = {
            'total_orders': 0,
            'wishlist_count': 0,
            'following_count': 0,
            'reward_points': 0,
            'recent_views_count': 0,
            'reviews_count': 0,
        }

        if hasattr(user, 'buyer_profile'):
            bp = user.buyer_profile
            profile_data['wishlist_count'] = bp.wishlist_count
            profile_data['following_count'] = bp.following_count
            profile_data['reward_points'] = bp.reward_points if hasattr(bp, 'reward_points') else 0

        # Count actual data
        profile_data['wishlist_count'] = Wishlist.objects.filter(buyer=user).count()
        profile_data['reviews_count'] = Review.objects.filter(buyer=user).count()
        profile_data['recent_views_count'] = RecentlyViewed.objects.filter(user=user).count()

        # Get recent wishlist items (last 4)
        recent_wishlist = Wishlist.objects.filter(
            buyer=user
        ).select_related('product', 'product__vendor').order_by('-created_at')[:4]

        wishlist_data = []
        for w in recent_wishlist:
            p = w.product
            wishlist_data.append({
                'id': p.id,
                'uuid': str(p.uuid),
                'slug': p.slug,
                'name': p.name,
                'price': str(p.price),
                'category': p.category,
                'primary_image': request.build_absolute_uri(p.primary_image.url) if p.primary_image else None,
                'vendor_name': p.vendor.shop_name,
                'is_available': p.is_available,
            })

        # Get recently viewed (last 4)
        recent_views = RecentlyViewed.objects.filter(
            user=user
        ).select_related('product', 'product__vendor').order_by('-viewed_at')[:4]

        recent_views_data = []
        for rv in recent_views:
            p = rv.product
            recent_views_data.append({
                'id': p.id,
                'uuid': str(p.uuid),
                'slug': p.slug,
                'name': p.name,
                'price': str(p.price),
                'category': p.category,
                'primary_image': request.build_absolute_uri(p.primary_image.url) if p.primary_image else None,
                'vendor_name': p.vendor.shop_name,
            })

        # Get recommended products (latest from followed vendors or trending)
        from accounts.models import Follow, VendorProfile

        # Follow.vendor_id stores User IDs; convert to VendorProfile IDs
        followed_user_ids = list(
            Follow.objects.filter(buyer=user).values_list('vendor_id', flat=True)
        )
        following_profile_ids = list(
            VendorProfile.objects.filter(user_id__in=followed_user_ids)
            .values_list('id', flat=True)
        ) if followed_user_ids else []

        if following_profile_ids:
            recommended = Product.objects.filter(
                status__in=['active', 'coming_soon'],
                vendor_id__in=following_profile_ids
            ).order_by('-created_at')[:4]
        else:
            recommended = Product.objects.filter(
                status__in=['active', 'coming_soon']
            ).order_by('-views')[:4]

        recommended_data = []
        for p in recommended:
            recommended_data.append({
                'id': p.id,
                'uuid': str(p.uuid),
                'slug': p.slug,
                'name': p.name,
                'price': str(p.price),
                'category': p.category,
                'primary_image': request.build_absolute_uri(p.primary_image.url) if p.primary_image else None,
                'vendor_name': p.vendor.shop_name,
                'views': p.views,
            })

        return Response({
            'success': True,
            'data': {
                'stats': profile_data,
                'wishlist': wishlist_data,
                'recently_viewed': recent_views_data,
                'recommended': recommended_data,
            }
        }, status=status.HTTP_200_OK)
