from rest_framework import serializers
from jobs_company.models.jobs import JobReview, Jobs
from django.contrib.auth import get_user_model
from common.storage import StorageFactory
from common.storage.exceptions import StorageError
from common.validators.image_validator import ImageValidator
from common.validators.video_validator import VideoValidator

User = get_user_model()


class JobReviewSerializer(serializers.ModelSerializer):
    """Job review serializer with storage abstraction support for images and videos"""
    # Override model CharField fields to accept File objects on write operations
    review_image = serializers.FileField(write_only=True, required=False, allow_null=True)
    review_video = serializers.FileField(write_only=True, required=False, allow_null=True)
    
    # Read-only fields
    created_by_name = serializers.CharField(source='created_by.username', read_only=True)
    created_by_email = serializers.EmailField(source='created_by.email', read_only=True)
    job_title = serializers.CharField(source='job.title', read_only=True)
    job_id = serializers.IntegerField(source='job.id', read_only=True)
    company_name = serializers.CharField(source='job.company.name', read_only=True)
    review_image_url = serializers.SerializerMethodField(read_only=True)
    review_video_url = serializers.SerializerMethodField(read_only=True)
    review_video_streaming_url = serializers.SerializerMethodField(read_only=True)
    review_video_thumbnail_url = serializers.SerializerMethodField(read_only=True)
    media_type = serializers.SerializerMethodField(read_only=True)

    def __init__(self, *args, **kwargs):
        """Initialize serializer with storage backend and validators."""
        super().__init__(*args, **kwargs)
        self.storage_backend = StorageFactory.get_storage_backend()
        self.image_validator = ImageValidator(
            max_size_bytes=5 * 1024 * 1024,  # 5MB
            allowed_types=['image/jpeg', 'image/jpg', 'image/png', 'image/webp']
        )
        self.video_validator = VideoValidator(
            max_size_bytes=100 * 1024 * 1024,  # 100MB
            allowed_types=['video/mp4', 'video/quicktime', 'video/webm'],
            max_duration_seconds=300  # 5 minutes
        )

    class Meta:
        model = JobReview
        fields = [
            'id', 'job', 'job_id', 'job_title', 'company_name',
            'review_star', 'message',
            'review_image', 'review_image_url',
            'review_video', 'review_video_url', 'review_video_streaming_url', 'review_video_thumbnail_url',
            'video_duration', 'media_type',
            'is_flagged_review',
            'created_by', 'created_by_name', 'created_by_email',
            'created_at', 'updated_at', 'is_active'
        ]
        read_only_fields = ['id', 'created_by', 'created_at', 'updated_at', 'is_active', 'video_duration']
    
    def validate(self, attrs):
        """Ensure only image OR video, not both."""
        review_image = attrs.get('review_image')
        review_video = attrs.get('review_video')
        
        if review_image and review_video:
            raise serializers.ValidationError(
                "Cannot upload both image and video. Please choose one."
            )
        
        return attrs
    
    def validate_job(self, value):
        """Validate job exists and is active"""
        if not value.is_active:
            raise serializers.ValidationError("Cannot review an inactive job")
        return value

    def validate_review_image(self, value):
        """Validate review image using ImageValidator."""
        if not value:
            return value
        
        try:
            self.image_validator.validate(value)
            return value
        except serializers.ValidationError:
            raise
        except Exception as e:
            raise serializers.ValidationError(f"Image validation failed: {str(e)}")

    def validate_review_video(self, value):
        """Validate review video using VideoValidator."""
        if not value:
            return value
        
        try:
            self.video_validator.validate(value)
            return value
        except serializers.ValidationError:
            raise
        except Exception as e:
            raise serializers.ValidationError(f"Video validation failed: {str(e)}")

    def get_media_type(self, obj):
        """Return 'image', 'video', or None"""
        if obj.review_video:
            return 'video'
        elif obj.review_image:
            return 'image'
        return None

    def get_review_image_url(self, obj):
        """Get review image URL using storage backend."""
        if not obj.review_image:
            return None
        
        try:
            url = self.storage_backend.get_url(str(obj.review_image))
            
            if StorageFactory.is_filesystem_backend():
                request = self.context.get("request")
                return request.build_absolute_uri(url) if request else url
            
            return url
            
        except Exception:
            request = self.context.get("request")
            url = obj.review_image.url if hasattr(obj.review_image, 'url') else str(obj.review_image)
            return request.build_absolute_uri(url) if request else url

    def get_review_video_url(self, obj):
        """Get progressive video URL"""
        if not obj.review_video:
            return None
        
        try:
            return self.storage_backend.get_video_url(str(obj.review_video))
        except Exception:
            return None
    
    def get_review_video_streaming_url(self, obj):
        """Get HLS streaming URL"""
        if not obj.review_video:
            return None
        
        try:
            return self.storage_backend.get_streaming_url(str(obj.review_video))
        except Exception:
            return None
    
    def get_review_video_thumbnail_url(self, obj):
        """Get video thumbnail URL"""
        if not obj.review_video:
            return None
        
        try:
            return self.storage_backend.get_thumbnail_url(str(obj.review_video))
        except Exception:
            return None

    def create(self, validated_data):
        """Create job review with image or video upload using storage backend."""
        request = self.context.get('request')
        review_image = validated_data.get("review_image")
        review_video = validated_data.get("review_video")
        
        # Handle image upload
        if review_image:
            try:
                identifier = self.storage_backend.upload(review_image, "reviews/job")
                validated_data["review_image"] = identifier
                
            except StorageError as e:
                raise serializers.ValidationError({
                    "review_image": f"Failed to upload image: {str(e)}"
                })
            except Exception as e:
                raise serializers.ValidationError({
                    "review_image": f"Unexpected error during image upload: {str(e)}"
                })
        
        # Handle video upload
        if review_video:
            try:
                identifier = self.storage_backend.upload_video(review_video, "reviews/job")
                validated_data["review_video"] = identifier
                
                metadata = self.storage_backend.get_video_metadata(identifier)
                validated_data["video_duration"] = int(metadata.get('duration', 0))
                
            except StorageError as e:
                raise serializers.ValidationError({
                    "review_video": f"Failed to upload video: {str(e)}"
                })
            except Exception as e:
                raise serializers.ValidationError({
                    "review_video": f"Unexpected error during video upload: {str(e)}"
                })
        
        # Set user from request
        if request and hasattr(request, 'user'):
            validated_data['created_by'] = request.user
            
        return super().create(validated_data)

    def update(self, instance, validated_data):
        """Update job review with image or video upload using storage backend."""
        review_image = validated_data.get("review_image")
        review_video = validated_data.get("review_video")
        old_image_identifier = str(instance.review_image) if instance.review_image else None
        old_video_identifier = str(instance.review_video) if instance.review_video else None
        
        # Handle image upload
        if review_image:
            try:
                identifier = self.storage_backend.upload(review_image, "reviews/job")
                validated_data["review_image"] = identifier
                
                # Clear video fields if replacing video with image
                if old_video_identifier:
                    validated_data["review_video"] = None
                    validated_data["video_duration"] = None
                    try:
                        self.storage_backend.delete(old_video_identifier)
                    except Exception:
                        pass
                
                # Delete old image if it exists
                if old_image_identifier:
                    try:
                        self.storage_backend.delete(old_image_identifier)
                    except Exception:
                        pass
                
            except StorageError as e:
                raise serializers.ValidationError({
                    "review_image": f"Failed to upload image: {str(e)}"
                })
            except Exception as e:
                raise serializers.ValidationError({
                    "review_image": f"Unexpected error during image upload: {str(e)}"
                })
        
        # Handle video upload
        if review_video:
            try:
                identifier = self.storage_backend.upload_video(review_video, "reviews/job")
                validated_data["review_video"] = identifier
                
                metadata = self.storage_backend.get_video_metadata(identifier)
                validated_data["video_duration"] = int(metadata.get('duration', 0))
                
                # Clear image field if replacing image with video
                if old_image_identifier:
                    validated_data["review_image"] = None
                    try:
                        self.storage_backend.delete(old_image_identifier)
                    except Exception:
                        pass
                
                # Delete old video if it exists
                if old_video_identifier:
                    try:
                        self.storage_backend.delete(old_video_identifier)
                    except Exception:
                        pass
                
            except StorageError as e:
                raise serializers.ValidationError({
                    "review_video": f"Failed to upload video: {str(e)}"
                })
            except Exception as e:
                raise serializers.ValidationError({
                    "review_video": f"Unexpected error during video upload: {str(e)}"
                })
        
        return super().update(instance, validated_data)
