from django.contrib.auth import get_user_model
from rest_framework import serializers
from drf_spectacular.utils import extend_schema_field
from .models import Chat, ChatReadStatus, Message, MessageFile, MessageHistory, MessageReaction



class MessageSenderSerializer(serializers.ModelSerializer):
    avatar = serializers.SerializerMethodField()

    def get_avatar(self, obj):
        from django.conf import settings
        if obj.avatar:
            return settings.MEDIA_URL + obj.avatar.name
        return None

    class Meta:
        model = get_user_model()
        fields = ['id', 'username', 'avatar']
        read_only_fields = ['id', 'username']


class MessageFileSerializer(serializers.ModelSerializer):
    class Meta:
        model = MessageFile
        fields = ['id', 'file', 'media_type', 'uploaded_at']
        read_only_fields = ['uploaded_at']


class MessageReactionSerializer(serializers.ModelSerializer):
    class Meta:
        model = MessageReaction
        fields = ['id', 'user', 'emoji', 'created_at']
        read_only_fields = ['user', 'created_at']


class MessageHistorySerializer(serializers.ModelSerializer):
    class Meta:
        model = MessageHistory
        fields = ['id', 'old_content', 'archived_at']
        read_only_fields = ['archived_at']


class ReplyToSerializer(serializers.ModelSerializer):
    sender = MessageSenderSerializer(read_only=True)
    media_files = MessageFileSerializer(many=True, read_only=True)

    class Meta:
        model = Message
        fields = ['id', 'content', 'sender', 'created_at', 'media_files']
        read_only_fields = ['id', 'content', 'sender', 'created_at', 'media_files']


class MessageSerializer(serializers.ModelSerializer):
    sender = MessageSenderSerializer(read_only=True)
    # reply_to is a SerializerMethodField so we can bypass ActiveManager and
    # still surface a tombstone when the original message is soft-deleted.
    reply_to = serializers.SerializerMethodField()
    media_files = MessageFileSerializer(many=True, read_only=True)
    reactions = MessageReactionSerializer(many=True, read_only=True)

    @extend_schema_field(ReplyToSerializer)
    def get_reply_to(self, obj):
        """
        Fetch the reply-to message via all_objects so soft-deleted originals
        are still accessible. Returns content=None when the message is deleted,
        which the frontend renders as a '(zpráva smazána)' tombstone.
        """
        reply_to_id = obj.reply_to_id
        if not reply_to_id:
            return None
        try:
            msg = Message.all_objects.select_related('sender').prefetch_related('media_files').get(pk=reply_to_id)
        except Message.DoesNotExist:
            return None

        from django.conf import settings
        sender_data = None
        if msg.sender:
            avatar = (settings.MEDIA_URL + msg.sender.avatar.name) if msg.sender.avatar else None
            sender_data = {'id': msg.sender.id, 'username': msg.sender.username, 'avatar': avatar}
        else:
            sender_data = {'id': 0, 'username': '…', 'avatar': None}

        media_files_data = []
        if not msg.is_deleted:
            for f in msg.media_files.all():
                media_files_data.append({
                    'id': f.id,
                    'file': settings.MEDIA_URL + f.file.name if f.file else '',
                    'media_type': f.media_type,
                    'uploaded_at': f.uploaded_at.isoformat(),
                })

        return {
            'id': msg.id,
            'content': None if msg.is_deleted else msg.content,
            'sender': sender_data,
            'created_at': msg.created_at.isoformat(),
            'media_files': media_files_data,
        }

    class Meta:
        model = Message
        fields = [
            'id', 'chat', 'sender', 'reply_to',
            'content', 'is_edited', 'edited_at',
            'created_at', 'updated_at',
            'media_files', 'reactions',
        ]
        read_only_fields = ['sender', 'chat', 'reply_to', 'is_edited', 'edited_at', 'created_at', 'updated_at']


class MessageSendSerializer(serializers.Serializer):
    """Used for the HTTP send endpoint (text + optional files)."""
    chat = serializers.PrimaryKeyRelatedField(queryset=Chat.objects.all())
    content = serializers.CharField(required=False, allow_blank=True, default='')
    reply_to = serializers.PrimaryKeyRelatedField(
        queryset=Message.objects.all(), required=False, allow_null=True
    )
    # files come via request.FILES - declared here for schema documentation only
    files = serializers.ListField(
        child=serializers.FileField(allow_empty_file=False, use_url=False),
        required=False,
        default=list,
        write_only=True,
    )

    def validate(self, attrs):
        if not attrs.get('content') and not attrs.get('files'):
            raise serializers.ValidationError('A message must have content or at least one file.')
        return attrs


class ChatSerializer(serializers.ModelSerializer):
    unread_count = serializers.SerializerMethodField(read_only=True)
    members_detail = MessageSenderSerializer(source='members', many=True, read_only=True)

    @extend_schema_field(serializers.IntegerField())
    def get_unread_count(self, obj):
        request = self.context.get('request')
        if not request or not request.user.is_authenticated:
            return 0
        last_read = ChatReadStatus.objects.filter(
            user=request.user, chat=obj
        ).values_list('last_read_at', flat=True).first()
        if last_read is None:
            return obj.messages.filter(is_deleted=False).count()
        return obj.messages.filter(created_at__gt=last_read, is_deleted=False).count()

    class Meta:
        model = Chat
        fields = [
            'id', 'chat_type', 'owner', 'name',
            'icon', 'banner', 'members', 'moderators',
            'hub', 'created_at', 'updated_at', 'unread_count',
            'members_detail',
        ]
        read_only_fields = ['owner', 'created_at', 'updated_at', 'unread_count', 'members_detail']


class ChatMemberSerializer(serializers.Serializer):
    user_id = serializers.IntegerField(help_text='PK of the user to add or remove.')
