from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAuthenticated, AllowAny
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from django.shortcuts import get_object_or_404
from django.db.models import Q
from rest_framework.parsers import MultiPartParser, FormParser, JSONParser

from common.pagination.custom_pagination import CustomPageNumberPagination
from service.models.services import ServicesReview, Services
from service.serializers.service_review import ServicesReviewSerializer
from package_details.utils import ensure_user_has_storage_capacity


class ServicesReviewPublicListAPIView(APIView):
    """Public endpoint - anybody can view all non-flagged service reviews"""
    permission_classes = [AllowAny]
    
    @swagger_auto_schema(
        operation_description="Get paginated list of non-flagged service reviews (public access)",
        manual_parameters=[
            openapi.Parameter('page', openapi.IN_QUERY, description="Page number", type=openapi.TYPE_INTEGER),
            openapi.Parameter('page_size', openapi.IN_QUERY, description="Number of items per page", type=openapi.TYPE_INTEGER),
            openapi.Parameter('service', openapi.IN_QUERY, description="Filter by service ID", type=openapi.TYPE_INTEGER),
            openapi.Parameter('rating', openapi.IN_QUERY, description="Filter by rating (1-5)", type=openapi.TYPE_INTEGER),
            openapi.Parameter('created_by', openapi.IN_QUERY, description="Filter by review creator ID", type=openapi.TYPE_INTEGER),
            openapi.Parameter('company', openapi.IN_QUERY, description="Filter by company ID", type=openapi.TYPE_INTEGER),
        ],
        responses={200: ServicesReviewSerializer(many=True)}
    )
    def get(self, request):
        reviews = ServicesReview.objects.filter(
            is_active=True, 
            is_flagged_review=False  
        ).select_related(
            'service', 
            'created_by',
            'service__company',
            'service__company__created_by'
        ).order_by('-created_at')
        
        # Apply filters
        service_id = request.query_params.get('service')
        rating = request.query_params.get('rating')
        created_by_id = request.query_params.get('created_by')
        company_id = request.query_params.get('company')
        
        if service_id:
            reviews = reviews.filter(service_id=service_id)
        if rating:
            reviews = reviews.filter(review_star=rating)
        if created_by_id:
            reviews = reviews.filter(created_by_id=created_by_id)
        if company_id:
            reviews = reviews.filter(service__company_id=company_id)
        
        paginator = CustomPageNumberPagination()
        result_page = paginator.paginate_queryset(reviews, request)
        serializer = ServicesReviewSerializer(result_page, many=True, context={'request': request})
        return paginator.get_paginated_response(serializer.data)


class ServicesReviewListCreateAPIView(APIView):
    """
    Authenticated endpoint for creating and listing reviews with role-based filtering:
    - Admin: Can see all reviews
    - Review Creator: Can see reviews they created
    - Service/Company Owner: Can see reviews for their services
    """
    permission_classes = [IsAuthenticated]
    parser_classes = [MultiPartParser, FormParser, JSONParser]
    
    @swagger_auto_schema(
        operation_description="Get paginated list of non-flagged service reviews",
        manual_parameters=[
            openapi.Parameter('page', openapi.IN_QUERY, description="Page number", type=openapi.TYPE_INTEGER),
            openapi.Parameter('page_size', openapi.IN_QUERY, description="Number of items per page", type=openapi.TYPE_INTEGER),
            openapi.Parameter('service', openapi.IN_QUERY, description="Filter by service ID", type=openapi.TYPE_INTEGER),
            openapi.Parameter('rating', openapi.IN_QUERY, description="Filter by rating (1-5)", type=openapi.TYPE_INTEGER),
            openapi.Parameter('created_by', openapi.IN_QUERY, description="Filter by review creator ID", type=openapi.TYPE_INTEGER),
            openapi.Parameter('company', openapi.IN_QUERY, description="Filter by company ID", type=openapi.TYPE_INTEGER),
        ],
        responses={200: ServicesReviewSerializer(many=True)}
    )
    def get(self, request):
        reviews = ServicesReview.objects.filter(
            is_flagged_review=False,
            is_active=True
        ).select_related(
            'service', 
            'created_by',
            'service__company',
            'service__company__created_by'
        ).order_by('-created_at')
        
        user = request.user
        if user.role == 'admin':
            pass
        else:
            
            reviews = reviews.filter(
                Q(created_by=user) |  # Reviews user created
                Q(service__company__created_by=user)  # Reviews for user's company's services
            )
        
        # Apply filters
        service_id = request.query_params.get('service')
        rating = request.query_params.get('rating')
        created_by_id = request.query_params.get('created_by')
        company_id = request.query_params.get('company')
        
        if service_id:
            reviews = reviews.filter(service_id=service_id)
        if rating:
            reviews = reviews.filter(review_star=rating)
        if created_by_id:
            reviews = reviews.filter(created_by_id=created_by_id)
        if company_id:
            reviews = reviews.filter(service__company_id=company_id)
        
        paginator = CustomPageNumberPagination()
        result_page = paginator.paginate_queryset(reviews, request)
        serializer = ServicesReviewSerializer(result_page, many=True, context={'request': request})
        return paginator.get_paginated_response(serializer.data)
    
    @swagger_auto_schema(
        operation_description="Create a new non-flagged service review",
        request_body=ServicesReviewSerializer,
        responses={
            201: ServicesReviewSerializer(),
            400: "Bad Request",
            404: "Service not found"
        }
    )
    def post(self, request):
        # ✅ Enhanced storage capacity check for both image and video
        review_image = request.FILES.get("review_image")
        review_video = request.FILES.get("review_video")
        
        if review_image:
            ensure_user_has_storage_capacity(
                request.user, 
                review_image, 
                field_name="review_image"
            )
        elif review_video:
            ensure_user_has_storage_capacity(
                request.user, 
                review_video, 
                field_name="review_video"
            )

        serializer = ServicesReviewSerializer(data=request.data, context={'request': request})
        
        if serializer.is_valid():
            service_id = serializer.validated_data.get('service')
            service = get_object_or_404(Services, pk=service_id.id, is_active=True)
            
            # Ensure this is not a flagged review (normal reviews only)
            serializer.save(
                created_by=request.user,
                is_flagged_review=False
            )
            
            return Response(
                {"success": "Service review created successfully", "data": serializer.data},
                status=status.HTTP_201_CREATED
            )
        
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class ServicesReviewDetailAPIView(APIView):
    """
    Detail view accessible to:
    - Anyone (public access for GET)
    - Review creator (for PUT/PATCH/DELETE)
    - Admin (for all operations)
    """
    parser_classes = [MultiPartParser, FormParser, JSONParser]
    
    def get_permissions(self):
        """Allow public GET access, but require authentication for other methods"""
        if self.request.method == 'GET':
            return [AllowAny()]
        return [IsAuthenticated()]
    
    def get_object(self, pk):
        """Get review object without permission check (for public GET)"""
        try:
            review = ServicesReview.objects.select_related(
                'service',
                'created_by',
                'service__company',
                'service__company__created_by'
            ).get(pk=pk, is_active=True, is_flagged_review=False)
            return review
        except ServicesReview.DoesNotExist:
            return None
    
    def get_object_with_permission(self, pk, user):
        """Get review object with permission check (for PUT/PATCH/DELETE)"""
        try:
            review = ServicesReview.objects.select_related(
                'service',
                'created_by',
                'service__company',
                'service__company__created_by'
            ).get(pk=pk, is_active=True, is_flagged_review=False)
        except ServicesReview.DoesNotExist:
            return None
        
        if user.role == 'admin':
            return review
        
        # User can modify if they created the review
        if review.created_by == user:
            return review
        
        # Service/company owner can view but not modify
        if review.service.company.created_by == user:
            return review
        
        return None
    
    @swagger_auto_schema(
        operation_description="Retrieve a specific service review (public access)",
        responses={
            200: ServicesReviewSerializer(),
            404: "Not Found"
        }
    )
    def get(self, request, pk):
        """Public GET - anybody can view a specific review"""
        review = self.get_object(pk)
        if review is None:
            return Response(
                {"error": "Service review not found"},
                status=status.HTTP_404_NOT_FOUND
            )
        
        serializer = ServicesReviewSerializer(review, context={'request': request})
        return Response(serializer.data, status=status.HTTP_200_OK)
    
    @swagger_auto_schema(
        operation_description="Update a service review (full update)",
        request_body=ServicesReviewSerializer,
        responses={
            200: ServicesReviewSerializer(),
            400: "Bad Request",
            403: "Forbidden",
            404: "Not Found"
        }
    )
    def put(self, request, pk):
        """Only review creator or admin can update"""
        review = self.get_object_with_permission(pk, request.user)
        if review is None:
            return Response(
                {"error": "Service review not found or you don't have permission to access it"},
                status=status.HTTP_404_NOT_FOUND
            )
        
        # Only the creator can update
        if review.created_by != request.user and request.user.role != 'admin':
            return Response(
                {"error": "Only the review creator can update it"},
                status=status.HTTP_403_FORBIDDEN
            )
        
        serializer = ServicesReviewSerializer(
            review,
            data=request.data,
            context={'request': request}
        )
        
        if serializer.is_valid():
            # Prevent changing to flagged review through normal update
            serializer.save(is_flagged_review=False)
            return Response(
                {"success": "Service review updated successfully", "data": serializer.data},
                status=status.HTTP_200_OK
            )
        
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
    @swagger_auto_schema(
        operation_description="Partially update a service review",
        request_body=ServicesReviewSerializer,
        responses={
            200: ServicesReviewSerializer(),
            400: "Bad Request",
            403: "Forbidden",
            404: "Not Found"
        }
    )
    def patch(self, request, pk):
        """Only review creator or admin can partially update"""
        review = self.get_object_with_permission(pk, request.user)
        if review is None:
            return Response(
                {"error": "Service review not found or you don't have permission to access it"},
                status=status.HTTP_404_NOT_FOUND
            )
        
        # Only the creator can update
        if review.created_by != request.user and request.user.role != 'admin':
            return Response(
                {"error": "Only the review creator can update it"},
                status=status.HTTP_403_FORBIDDEN
            )
        
        serializer = ServicesReviewSerializer(
            review,
            data=request.data,
            partial=True,
            context={'request': request}
        )
        
        if serializer.is_valid():
            # Prevent changing to flagged review through normal update
            serializer.save(is_flagged_review=False)
            return Response(
                {"success": "Service review updated successfully", "data": serializer.data},
                status=status.HTTP_200_OK
            )
        
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
    @swagger_auto_schema(
        operation_description="Soft delete a service review",
        responses={
            204: "No Content",
            403: "Forbidden",
            404: "Not Found"
        }
    )
    def delete(self, request, pk):
        """Only review creator or admin can delete"""
        review = self.get_object_with_permission(pk, request.user)
        if review is None:
            return Response(
                {"error": "Service review not found or you don't have permission to access it"},
                status=status.HTTP_404_NOT_FOUND
            )
        
        # Only the creator or admin can delete
        if request.user.role != 'admin' and review.created_by != request.user:
            return Response(
                {"error": "Only the review creator or admin can delete it"},
                status=status.HTTP_403_FORBIDDEN
            )
        
        review.soft_delete()
        return Response(
            {"success": "Service review deleted successfully"},
            status=status.HTTP_204_NO_CONTENT
        )
