from rest_framework import serializers
from django.core.validators import URLValidator
from .models import Formation, Lesson, UserProgress, UserFormationStatus


class AdminLessonSerializer(serializers.ModelSerializer):
    """Serializer simple pour l'admin (création/modification)."""
    class Meta:
        model = Lesson
        fields = ['id', 'formation', 'title', 'order', 'pdf_file', 'video_url', 'video_file']


class AdminFormationSerializer(serializers.ModelSerializer):
    """Serializer admin : création/modification avec image (upload ou lien optionnel) et leçons."""
    image_url = serializers.URLField(required=False, allow_blank=True, allow_null=True)
    lessons = AdminLessonSerializer(many=True, read_only=True)

    class Meta:
        model = Formation
        fields = ['id', 'title', 'description', 'image', 'image_url', 'order', 'lessons']

    def validate_image_url(self, value):
        if not value or not value.strip():
            return None
        value = value.strip()
        URLValidator()(value)
        return value

    def validate_image(self, value):
        if not value:
            return value
        # Vérifier que c'est bien une image (extension ou content-type)
        name = getattr(value, 'name', '') or ''
        allowed = ('.jpg', '.jpeg', '.png', '.gif', '.webp')
        if not any(name.lower().endswith(ext) for ext in allowed):
            raise serializers.ValidationError(
                "Format d'image non accepté. Utilisez JPG, PNG, GIF ou WebP."
            )
        return value

    def _clean_image_fields(self, validated_data):
        """Un seul type d'image : fichier OU lien."""
        if validated_data.get('image'):
            validated_data['image_url'] = None
        if validated_data.get('image_url'):
            validated_data['image'] = None
        return validated_data

    def create(self, validated_data):
        validated_data = self._clean_image_fields(validated_data.copy())
        return super().create(validated_data)

    def update(self, instance, validated_data):
        validated_data = self._clean_image_fields(validated_data.copy())
        return super().update(instance, validated_data)


class LessonSerializer(serializers.ModelSerializer):
    is_locked = serializers.SerializerMethodField()
    is_completed = serializers.SerializerMethodField()

    class Meta:
        model = Lesson
        fields = ['id', 'title', 'order', 'pdf_file', 'video_url', 'video_file', 'is_locked', 'is_completed']

    def get_is_completed(self, obj):
        user = self.context['request'].user
        try:
            progress = UserProgress.objects.get(user=user, lesson=obj)
            return progress.is_completed
        except UserProgress.DoesNotExist:
            return False

    def get_is_locked(self, obj):
        user = self.context['request'].user
        
        # La leçon 1 est toujours débloquée
        if obj.order == 1:
            return False
            
        # Pour la leçon N, on vérifie si la leçon N-1 est complétée
        try:
            previous_lesson = Lesson.objects.get(formation=obj.formation, order=obj.order - 1)
            prev_progress = UserProgress.objects.filter(user=user, lesson=previous_lesson, is_completed=True)
            return not prev_progress.exists() # Si pas de progrès validé, c'est bloqué
        except Lesson.DoesNotExist:
            return True # Cas de sécurité

def _effective_image_url(serializer, obj):
    """URL d'affichage : fichier uploadé ou lien image."""
    if obj.image:
        request = serializer.context.get('request')
        return request.build_absolute_uri(obj.image.url) if request else obj.image.url
    return getattr(obj, 'image_url', None) or None


class FormationListSerializer(serializers.ModelSerializer):
    """Serializer pour la liste des formations (avec progression et verrou, sans leçons)."""
    image = serializers.SerializerMethodField()
    progress_percentage = serializers.SerializerMethodField()
    is_locked = serializers.SerializerMethodField()
    is_formation_completed = serializers.SerializerMethodField()

    class Meta:
        model = Formation
        fields = ['id', 'title', 'description', 'image', 'order', 'progress_percentage', 'is_locked', 'is_formation_completed']

    def get_image(self, obj):
        return _effective_image_url(self, obj)

    def get_is_formation_completed(self, obj):
        user = self.context['request'].user
        total_lessons = obj.lessons.count()
        if total_lessons == 0:
            return False
        completed_lessons = UserProgress.objects.filter(user=user, lesson__formation=obj, is_completed=True).count()
        s = UserFormationStatus.objects.filter(user=user, formation=obj).first()
        return (completed_lessons == total_lessons) and bool(s and s.is_completed)

    def get_is_locked(self, obj):
        if obj.order <= 1:
            return False
        prev = Formation.objects.filter(order=obj.order - 1).first()
        if not prev:
            return True
        user = self.context['request'].user
        return not UserFormationStatus.objects.filter(
            user=user, formation=prev, is_completed=True
        ).exists()

    def get_progress_percentage(self, obj):
        user = self.context['request'].user
        total_lessons = obj.lessons.count()
        if total_lessons == 0:
            return 0
        completed_lessons = UserProgress.objects.filter(user=user, lesson__formation=obj, is_completed=True).count()
        return round((completed_lessons / total_lessons) * 100)


class FormationSerializer(serializers.ModelSerializer):
    lessons = LessonSerializer(many=True, read_only=True)
    image = serializers.SerializerMethodField()
    progress_percentage = serializers.SerializerMethodField()
    is_locked = serializers.SerializerMethodField()
    is_formation_completed = serializers.SerializerMethodField()
    can_retry_quiz_after = serializers.SerializerMethodField()

    class Meta:
        model = Formation
        fields = ['id', 'title', 'description', 'image', 'lessons', 'progress_percentage', 'is_locked', 'is_formation_completed', 'can_retry_quiz_after']

    def get_image(self, obj):
        return _effective_image_url(self, obj)

    def get_is_formation_completed(self, obj):
        user = self.context['request'].user
        total_lessons = obj.lessons.count()
        if total_lessons == 0:
            return False
        completed_lessons = UserProgress.objects.filter(user=user, lesson__formation=obj, is_completed=True).count()
        s = UserFormationStatus.objects.filter(user=user, formation=obj).first()
        return (completed_lessons == total_lessons) and bool(s and s.is_completed)

    def get_can_retry_quiz_after(self, obj):
        from datetime import timedelta
        from django.utils import timezone
        user = self.context['request'].user
        s = UserFormationStatus.objects.filter(user=user, formation=obj).first()
        if not s or s.is_completed or not s.last_attempt_at:
            return None
        retry_at = s.last_attempt_at + timedelta(hours=24)
        if timezone.now() < retry_at:
            return retry_at.isoformat()
        return None

    def get_is_locked(self, obj):
        """Formation N+1 verrouillée si la formation N n'a pas le quiz final validé."""
        if obj.order <= 1:
            return False
        prev = Formation.objects.filter(order=obj.order - 1).first()
        # Si on ne trouve pas de formation précédente avec cet ordre,
        # on préfère VERROUILLER par sécurité (évite de tout débloquer).
        if not prev:
            return True
        user = self.context['request'].user
        return not UserFormationStatus.objects.filter(
            user=user, formation=prev, is_completed=True
        ).exists()

    def get_progress_percentage(self, obj):
        user = self.context['request'].user
        total_lessons = obj.lessons.count()
        if total_lessons == 0:
            return 0
        completed_lessons = UserProgress.objects.filter(user=user, lesson__formation=obj, is_completed=True).count()
        return round((completed_lessons / total_lessons) * 100)