"""Helpdesk DRF serializers."""

from __future__ import annotations

from rest_framework import serializers

from simorgh.apps.helpdesk.models import (
    AgentTeam,
    AgentTeamMember,
    AgentTeamRole,
    Automation,
    Category,
    Queue,
    SLAPolicy,
    Tag,
    Ticket,
    TicketReply,
    TicketStatus,
    TicketPriority,
    TicketChannel,
)


# ---------------------------------------------------------------------------
# Tag
# ---------------------------------------------------------------------------

class TagSerializer(serializers.ModelSerializer):
    class Meta:
        model = Tag
        fields = ("id", "name", "color", "is_active")
        read_only_fields = ("id",)


# ---------------------------------------------------------------------------
# Category
# ---------------------------------------------------------------------------

class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = ("id", "public_id", "queue_id", "parent_id", "name", "description",
                  "is_active", "sort_order")
        read_only_fields = ("id", "public_id")


# ---------------------------------------------------------------------------
# SLA Policy
# ---------------------------------------------------------------------------

class SLAPolicySerializer(serializers.ModelSerializer):
    class Meta:
        model = SLAPolicy
        fields = (
            "id", "public_id", "name", "description",
            "first_response_hours", "next_response_hours", "resolution_hours",
            "business_hours_only", "is_active",
        )
        read_only_fields = ("id", "public_id")


# ---------------------------------------------------------------------------
# Queue
# ---------------------------------------------------------------------------

class QueueListSerializer(serializers.ModelSerializer):
    class Meta:
        model = Queue
        fields = (
            "id", "public_id", "name", "description", "email_address",
            "is_default", "is_active", "sort_order",
            "default_sla_policy_id",
        )
        read_only_fields = ("id", "public_id")


class QueueCreateSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=128)
    description = serializers.CharField(required=False, allow_blank=True, default="")
    email_address = serializers.EmailField(required=False, allow_blank=True, default="")
    is_default = serializers.BooleanField(required=False, default=False)
    default_sla_policy_id = serializers.IntegerField(required=False, allow_null=True)


# ---------------------------------------------------------------------------
# Ticket
# ---------------------------------------------------------------------------

class TicketTagsField(serializers.PrimaryKeyRelatedField):
    def get_queryset(self):
        request = self.context.get("request")
        if request is None:
            return Tag.objects.none()
        return Tag.objects.filter(tenant=getattr(request, "tenant", None), is_active=True)


class TicketListSerializer(serializers.ModelSerializer):
    tags = TagSerializer(many=True, read_only=True)
    requester_display = serializers.CharField(read_only=True)
    assigned_to_name = serializers.SerializerMethodField()

    class Meta:
        model = Ticket
        fields = (
            "id", "public_id", "subject", "status", "priority", "channel",
            "queue_id", "category_id",
            "requester_id", "requester_display",
            "assigned_to_id", "assigned_to_name",
            "tags",
            "first_response_due_at", "resolution_due_at",
            "first_responded_at", "resolved_at", "closed_at",
            "created_at", "updated_at",
        )
        read_only_fields = fields

    def get_assigned_to_name(self, obj: Ticket) -> str:
        if obj.assigned_to_id is None:
            return ""
        agent = obj.assigned_to
        if agent is None:
            return ""
        full = getattr(agent, "get_full_name", lambda: "")()
        return full or getattr(agent, "email", "")


class TicketDetailSerializer(TicketListSerializer):
    class Meta(TicketListSerializer.Meta):
        fields = TicketListSerializer.Meta.fields + (
            "description",
            "requester_email", "requester_name",
            "escalated_to_id", "escalated_at", "escalation_reason",
            "sla_policy_id",
            "satisfaction_rating", "satisfaction_comment",
            "custom_fields",
        )
        read_only_fields = fields


class TicketCreateSerializer(serializers.Serializer):
    queue_id = serializers.IntegerField(required=False, allow_null=True)
    subject = serializers.CharField(max_length=512)
    description = serializers.CharField(required=False, allow_blank=True, default="")
    priority = serializers.ChoiceField(
        choices=TicketPriority.choices, default=TicketPriority.NORMAL
    )
    channel = serializers.ChoiceField(
        choices=TicketChannel.choices, default=TicketChannel.WEB
    )
    category_id = serializers.IntegerField(required=False, allow_null=True)
    requester_id = serializers.IntegerField(required=False, allow_null=True)
    requester_email = serializers.EmailField(required=False, allow_blank=True, default="")
    requester_name = serializers.CharField(
        max_length=256, required=False, allow_blank=True, default=""
    )
    tag_ids = serializers.ListField(
        child=serializers.IntegerField(), required=False, default=list
    )
    custom_fields = serializers.JSONField(required=False, default=dict)


class TicketUpdateSerializer(serializers.Serializer):
    subject = serializers.CharField(max_length=512, required=False)
    description = serializers.CharField(required=False, allow_blank=True)
    priority = serializers.ChoiceField(choices=TicketPriority.choices, required=False)
    category_id = serializers.IntegerField(required=False, allow_null=True)
    queue_id = serializers.IntegerField(required=False)
    custom_fields = serializers.JSONField(required=False)


class TicketTransitionSerializer(serializers.Serializer):
    status = serializers.ChoiceField(choices=TicketStatus.choices)
    note = serializers.CharField(required=False, allow_blank=True, default="")


class TicketAssignSerializer(serializers.Serializer):
    assigned_to_id = serializers.IntegerField(allow_null=True)


class TicketEscalateSerializer(serializers.Serializer):
    escalated_to_id = serializers.IntegerField()
    reason = serializers.CharField(required=False, allow_blank=True, default="")


# ---------------------------------------------------------------------------
# TicketReply
# ---------------------------------------------------------------------------

class TicketReplySerializer(serializers.ModelSerializer):
    author_display = serializers.CharField(read_only=True)

    class Meta:
        model = TicketReply
        fields = (
            "id", "public_id",
            "author_id", "author_display",
            "author_email", "author_name",
            "body", "html_body",
            "is_internal", "channel",
            "created_at",
        )
        read_only_fields = fields


class TicketReplyCreateSerializer(serializers.Serializer):
    body = serializers.CharField()
    is_internal = serializers.BooleanField(default=False)
    channel = serializers.ChoiceField(
        choices=[c[0] for c in TicketReply._meta.get_field("channel").choices],
        default="web",
    )
    author_email = serializers.EmailField(required=False, allow_blank=True, default="")
    author_name = serializers.CharField(
        max_length=256, required=False, allow_blank=True, default=""
    )


# ---------------------------------------------------------------------------
# Automation
# ---------------------------------------------------------------------------

class AutomationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Automation
        fields = (
            "id", "public_id", "name", "description",
            "trigger", "conditions", "actions",
            "is_active", "sort_order",
            "run_count", "last_run_at",
            "created_at", "updated_at",
        )
        read_only_fields = ("id", "public_id", "run_count", "last_run_at",
                            "created_at", "updated_at")


# ---------------------------------------------------------------------------
# Agent Team
# ---------------------------------------------------------------------------

class AgentTeamMemberSerializer(serializers.ModelSerializer):
    user_display = serializers.SerializerMethodField()
    mobile = serializers.SerializerMethodField()

    class Meta:
        model = AgentTeamMember
        fields = ("id", "user_id", "user_display", "mobile", "role", "added_at")
        read_only_fields = ("id", "user_display", "mobile", "added_at")

    def get_user_display(self, obj: AgentTeamMember) -> str:
        u = obj.user
        full = getattr(u, "get_full_name", lambda: "")()
        return full or getattr(u, "mobile", "") or ""

    def get_mobile(self, obj: AgentTeamMember) -> str:
        return getattr(obj.user, "mobile", "") or ""

    # Expose created_at as added_at for clarity.
    added_at = serializers.DateTimeField(source="created_at", read_only=True)


class AgentTeamListSerializer(serializers.ModelSerializer):
    member_count = serializers.SerializerMethodField()
    category_ids = serializers.PrimaryKeyRelatedField(
        source="categories", many=True, read_only=True
    )

    class Meta:
        model = AgentTeam
        fields = (
            "id", "public_id", "name", "description",
            "is_active", "sort_order",
            "member_count", "category_ids",
            "created_at", "updated_at",
        )
        read_only_fields = fields

    def get_member_count(self, obj: AgentTeam) -> int:
        return obj.memberships.count()


class AgentTeamDetailSerializer(AgentTeamListSerializer):
    members = AgentTeamMemberSerializer(source="memberships", many=True, read_only=True)

    class Meta(AgentTeamListSerializer.Meta):
        fields = AgentTeamListSerializer.Meta.fields + ("members",)
        read_only_fields = fields


class AgentTeamWriteSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=128)
    description = serializers.CharField(required=False, allow_blank=True, default="")
    is_active = serializers.BooleanField(required=False, default=True)
    sort_order = serializers.IntegerField(required=False, default=0)
    category_ids = serializers.ListField(
        child=serializers.IntegerField(), required=False, default=list
    )


class AgentTeamAddMemberSerializer(serializers.Serializer):
    user_id = serializers.IntegerField()
    role = serializers.ChoiceField(choices=AgentTeamRole.choices, default=AgentTeamRole.MEMBER)
