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 django.db import transaction
from rest_framework.parsers import MultiPartParser, FormParser, JSONParser

from jobs_company.models.jobs import JobReview, Jobs
from jobs_company.serializers.job_review_serializer import JobReviewSerializer
from common.pagination.custom_pagination import CustomPageNumberPagination
from package_details.utils import ensure_user_has_storage_capacity


class JobReviewPublicListAPIView(APIView):
    """Public endpoint - anybody can view all non-flagged job reviews"""
    permission_classes = [AllowAny]
    
    @swagger_auto_schema(
        operation_description="Get all non-flagged job reviews (public)",
        manual_parameters=[
            openapi.Parameter('job', openapi.IN_QUERY, description="Filter by job 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('job_owner', openapi.IN_QUERY, description="Filter by job creator/owner ID", type=openapi.TYPE_INTEGER),
            openapi.Parameter('company', openapi.IN_QUERY, description="Filter by company ID", type=openapi.TYPE_INTEGER),
            openapi.Parameter('page', openapi.IN_QUERY, description="Page number", type=openapi.TYPE_INTEGER),
            openapi.Parameter('page_size', openapi.IN_QUERY, description="Items per page", type=openapi.TYPE_INTEGER),
        ]
    )
    def get(self, request):
        reviews = JobReview.objects.filter(
            is_active=True, 
            is_flagged_review=False  
        ).select_related(
            'job', 
            'created_by',
            'job__created_by',
            'job__company'
        ).order_by('-created_at')
        
        # Apply filters
        job_id = request.query_params.get('job')  
        rating = request.query_params.get('rating')  
        created_by_id = request.query_params.get('created_by') 
        job_owner_id = request.query_params.get('job_owner')
        company_id = request.query_params.get('company')
        
        if job_id:
            reviews = reviews.filter(job_id=job_id)
        if rating:
            reviews = reviews.filter(review_star=rating)
        if created_by_id:
            reviews = reviews.filter(created_by_id=created_by_id)
        if job_owner_id:
            reviews = reviews.filter(job__created_by_id=job_owner_id)
        if company_id:
            reviews = reviews.filter(job__company_id=company_id)
        
        paginator = CustomPageNumberPagination()
        result_page = paginator.paginate_queryset(reviews, request)
        serializer = JobReviewSerializer(result_page, many=True, context={'request': request})
        return paginator.get_paginated_response(serializer.data)


class JobReviewListCreateAPIView(APIView):
    """
    Authenticated endpoint for creating and listing reviews with role-based filtering:
    - Admin: Can see all reviews
    - Review Creator: Can see reviews they created
    - Job Owner: Can see reviews for their jobs
    """
    permission_classes = [IsAuthenticated]
    parser_classes = [MultiPartParser, FormParser, JSONParser]
    
    @swagger_auto_schema(
        operation_description="Create a new job review",
        request_body=JobReviewSerializer
    )
    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 = JobReviewSerializer(data=request.data, context={'request': request})
        serializer.is_valid(raise_exception=True)
        serializer.save(is_flagged_review=False)
        return Response(
            {"success": "Job review created successfully", "data": serializer.data}, 
            status=status.HTTP_201_CREATED
        )
    
    @swagger_auto_schema(
        operation_description="Get job reviews based on user role and permissions",
        manual_parameters=[
            openapi.Parameter('job', openapi.IN_QUERY, description="Filter by job 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('job_owner', openapi.IN_QUERY, description="Filter by job creator/owner ID", type=openapi.TYPE_INTEGER),
            openapi.Parameter('company', openapi.IN_QUERY, description="Filter by company ID", type=openapi.TYPE_INTEGER),
            openapi.Parameter('page', openapi.IN_QUERY, description="Page number", type=openapi.TYPE_INTEGER),
            openapi.Parameter('page_size', openapi.IN_QUERY, description="Items per page", type=openapi.TYPE_INTEGER),
        ]
    )
    def get(self, request):
        reviews = JobReview.objects.filter(
            is_active=True, 
            is_flagged_review=False
        ).select_related(
            'job', 
            'created_by',
            'job__created_by',
            'job__company'
        ).order_by('-created_at')
        
        user = request.user
        if user.role == 'admin':
            # Admin can see all reviews
            pass
        else:
            # Filter to only show reviews created by user OR reviews for jobs created by user
            reviews = reviews.filter(
                Q(created_by=user) |  
                Q(job__created_by=user) 
            )
        
        # Apply filters
        job_id = request.query_params.get('job')  
        rating = request.query_params.get('rating')  
        created_by_id = request.query_params.get('created_by')  
        job_owner_id = request.query_params.get('job_owner')
        company_id = request.query_params.get('company')
        
        if job_id:
            reviews = reviews.filter(job_id=job_id)
        if rating:
            reviews = reviews.filter(review_star=rating)
        if created_by_id:
            reviews = reviews.filter(created_by_id=created_by_id)
        if job_owner_id:
            reviews = reviews.filter(job__created_by_id=job_owner_id)
        if company_id:
            reviews = reviews.filter(job__company_id=company_id)
        
        paginator = CustomPageNumberPagination()
        result_page = paginator.paginate_queryset(reviews, request)
        serializer = JobReviewSerializer(result_page, many=True, context={'request': request})
        return paginator.get_paginated_response(serializer.data)


class JobReviewDetailAPIView(APIView):
    """
    Detail view accessible to:
    - Anyone (public access for GET)
    - Review creator (for PUT/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 = JobReview.objects.select_related(
                'job', 
                'created_by',
                'job__created_by',
                'job__company'
            ).get(pk=pk, is_active=True, is_flagged_review=False)
            return review
        except JobReview.DoesNotExist:
            return None
    
    def get_object_with_permission(self, pk, user):
        """Get review object with permission check (for PUT/DELETE)"""
        try:
            review = JobReview.objects.select_related(
                'job', 
                'created_by',
                'job__created_by',
                'job__company'
            ).get(pk=pk)
        except JobReview.DoesNotExist:
            return None
        
        # Admin can access any review
        if user.role == 'admin':
            return review
        
        # Review creator can access their own review
        if review.created_by == user:
            return review
        
        # Job owner can access reviews for their jobs
        if review.job.created_by == user:
            return review
        
        return None
    
    @swagger_auto_schema(
        operation_description="Get a specific job review by ID (public access)"
    )
    def get(self, request, pk):
        """Public GET - anybody can view a specific review"""
        review = self.get_object(pk)
        if not review:
            return Response(
                {"error": "Job review not found"}, 
                status=status.HTTP_404_NOT_FOUND
            )
        
        serializer = JobReviewSerializer(review, context={'request': request})
        return Response(serializer.data)
    
    @swagger_auto_schema(
        operation_description="Update a job review (only review creator or admin)",
        request_body=JobReviewSerializer
    )
    def put(self, request, pk):
        """Only review creator or admin can update"""
        review = self.get_object_with_permission(pk, request.user)
        if not review:
            return Response(
                {"error": "Job review not found or you don't have permission to access it"}, 
                status=status.HTTP_404_NOT_FOUND
            )
        
        # Only the review creator can update their own review
        if review.created_by != request.user and request.user.role != 'admin':
            return Response(
                {"error": "You do not have permission to update this review"}, 
                status=status.HTTP_403_FORBIDDEN
            )
        
        serializer = JobReviewSerializer(review, data=request.data, context={'request': request})
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(
            {"success": "Job review updated successfully", "data": serializer.data}, 
            status=status.HTTP_200_OK
        )

    @swagger_auto_schema(
        operation_description="Delete a job review (only review creator or admin)"
    )
    def delete(self, request, pk):
        """Only review creator or admin can delete"""
        review = self.get_object_with_permission(pk, request.user)
        if not review:
            return Response(
                {"error": "Job review not found or you don't have permission to access it"}, 
                status=status.HTTP_404_NOT_FOUND
            )
        
        # Only the review creator can delete their own review
        if review.created_by != request.user and request.user.role != 'admin':
            return Response(
                {"error": "You do not have permission to delete this review"}, 
                status=status.HTTP_403_FORBIDDEN
            )
        
        review.is_active = False
        review.save(update_fields=['is_active'])
        return Response(
            {"success": "Job review deleted successfully"}, 
            status=status.HTTP_200_OK
        )
