"""DMS collaboration — REST serializers.

Read serializers (ModelSerializer)
    CommentSerializer         — full comment with author info and reply count
    AnnotationSerializer      — full annotation with author info
    MentionSerializer         — mention with user info

Write serializers (Serializer)
    CommentWriteSerializer    — create/update a comment
    AnnotationWriteSerializer — create/update an annotation
    CommentResolveSerializer  — no payload required (empty write)
"""

from __future__ import annotations

from rest_framework import serializers

from simorgh.apps.dms.collaboration.models import Annotation, AnnotationType, Comment, Mention


# ---------------------------------------------------------------------------
# Helper
# ---------------------------------------------------------------------------

def _user_display(user) -> str | None:
    if user is None:
        return None
    fn = getattr(user, "get_full_name", None)
    name = fn() if callable(fn) else ""
    return name or str(user)


# ---------------------------------------------------------------------------
# Mention
# ---------------------------------------------------------------------------

class MentionSerializer(serializers.ModelSerializer):
    mentioned_user_id = serializers.IntegerField(
        source="mentioned_user.pk", read_only=True
    )
    mentioned_user_name = serializers.SerializerMethodField()

    class Meta:
        model = Mention
        fields = (
            "id",
            "public_id",
            "mentioned_user_id",
            "mentioned_user_name",
            "is_notified",
            "created_at",
        )
        read_only_fields = fields

    def get_mentioned_user_name(self, obj):
        return _user_display(obj.mentioned_user)


# ---------------------------------------------------------------------------
# Comment (read)
# ---------------------------------------------------------------------------

class CommentSerializer(serializers.ModelSerializer):
    author_id = serializers.IntegerField(
        source="author.pk", read_only=True, allow_null=True
    )
    author_name = serializers.SerializerMethodField()
    resolved_by_id = serializers.IntegerField(
        source="resolved_by.pk", read_only=True, allow_null=True
    )
    document_id = serializers.UUIDField(
        source="document.public_id", read_only=True
    )
    version_id = serializers.SerializerMethodField()
    parent_id = serializers.SerializerMethodField()
    reply_count = serializers.SerializerMethodField()
    mention_count = serializers.SerializerMethodField()

    class Meta:
        model = Comment
        fields = (
            "id",
            "public_id",
            "document_id",
            "version_id",
            "parent_id",
            "author_id",
            "author_name",
            "body",
            "is_resolved",
            "resolved_by_id",
            "resolved_at",
            "reply_count",
            "mention_count",
            "is_deleted",
            "created_at",
            "updated_at",
        )
        read_only_fields = fields

    def get_author_name(self, obj):
        return _user_display(obj.author)

    def get_version_id(self, obj):
        if obj.version is None:
            return None
        return str(obj.version.public_id)

    def get_parent_id(self, obj):
        if obj.parent is None:
            return None
        return str(obj.parent.public_id)

    def get_reply_count(self, obj):
        # Use prefetched data if available to avoid N+1
        if hasattr(obj, "_prefetched_objects_cache") and "replies" in obj._prefetched_objects_cache:
            return sum(1 for r in obj.replies.all() if not r.is_deleted)
        return obj.replies.filter(is_deleted=False).count()

    def get_mention_count(self, obj):
        if hasattr(obj, "_prefetched_objects_cache") and "mentions" in obj._prefetched_objects_cache:
            return len(obj.mentions.all())
        return obj.mentions.count()


# ---------------------------------------------------------------------------
# Comment (write)
# ---------------------------------------------------------------------------

class CommentWriteSerializer(serializers.Serializer):
    body = serializers.CharField(min_length=1, max_length=10000)
    version_id = serializers.UUIDField(required=False, allow_null=True, default=None)
    parent_id = serializers.UUIDField(required=False, allow_null=True, default=None)
    mention_user_ids = serializers.ListField(
        child=serializers.IntegerField(min_value=1),
        required=False,
        allow_empty=True,
        default=list,
    )


class CommentUpdateSerializer(serializers.Serializer):
    body = serializers.CharField(min_length=1, max_length=10000)
    mention_user_ids = serializers.ListField(
        child=serializers.IntegerField(min_value=1),
        required=False,
        allow_empty=True,
        default=list,
    )


# ---------------------------------------------------------------------------
# Annotation (read)
# ---------------------------------------------------------------------------

class AnnotationSerializer(serializers.ModelSerializer):
    author_id = serializers.IntegerField(
        source="author.pk", read_only=True, allow_null=True
    )
    author_name = serializers.SerializerMethodField()
    document_id = serializers.UUIDField(
        source="document.public_id", read_only=True
    )
    version_id = serializers.UUIDField(
        source="version.public_id", read_only=True
    )
    linked_comment_id = serializers.SerializerMethodField()

    class Meta:
        model = Annotation
        fields = (
            "id",
            "public_id",
            "document_id",
            "version_id",
            "author_id",
            "author_name",
            "annotation_type",
            "page_number",
            "position_data",
            "body",
            "color",
            "linked_comment_id",
            "is_deleted",
            "created_at",
            "updated_at",
        )
        read_only_fields = fields

    def get_author_name(self, obj):
        return _user_display(obj.author)

    def get_linked_comment_id(self, obj):
        if obj.linked_comment is None:
            return None
        return str(obj.linked_comment.public_id)


# ---------------------------------------------------------------------------
# Annotation (write)
# ---------------------------------------------------------------------------

class AnnotationWriteSerializer(serializers.Serializer):
    annotation_type = serializers.ChoiceField(
        choices=AnnotationType.choices,
        default=AnnotationType.NOTE,
        required=False,
    )
    body = serializers.CharField(allow_blank=True, max_length=5000, default="")
    page_number = serializers.IntegerField(
        min_value=1, required=False, allow_null=True, default=None
    )
    position_data = serializers.DictField(
        child=serializers.JSONField(), required=False, default=dict
    )
    color = serializers.RegexField(
        r"^#[0-9A-Fa-f]{6}$",
        required=False,
        default="#FFFF00",
        error_messages={"invalid": "Color must be a CSS hex color (e.g. #FFFF00)."},
    )
    linked_comment_id = serializers.UUIDField(
        required=False, allow_null=True, default=None
    )


class AnnotationUpdateSerializer(serializers.Serializer):
    body = serializers.CharField(allow_blank=True, max_length=5000, required=False)
    color = serializers.RegexField(
        r"^#[0-9A-Fa-f]{6}$",
        required=False,
        error_messages={"invalid": "Color must be a CSS hex color (e.g. #FFFF00)."},
    )
    position_data = serializers.DictField(
        child=serializers.JSONField(), required=False
    )
    page_number = serializers.IntegerField(
        min_value=1, required=False, allow_null=True
    )
