from rest_framework import serializers

from .models import SupportTicket, SupportTicketAttachment, SupportTicketMessage


class SupportTicketAttachmentSerializer(serializers.ModelSerializer):
    file_url = serializers.SerializerMethodField()

    class Meta:
        model = SupportTicketAttachment
        fields = (
            "id",
            "ticket",
            "message",
            "uploaded_by",
            "file_name",
            "content_type",
            "file_size",
            "file_url",
            "created_at",
        )
        read_only_fields = fields

    def get_file_url(self, obj):
        request = self.context.get("request")
        if not obj.file:
            return None
        try:
            if request:
                return request.build_absolute_uri(obj.file.url)
            return obj.file.url
        except Exception:
            return None


class SupportTicketMessageSerializer(serializers.ModelSerializer):
    sender_name = serializers.SerializerMethodField()
    attachments = serializers.SerializerMethodField()

    class Meta:
        model = SupportTicketMessage
        fields = (
            "id",
            "ticket",
            "sender",
            "sender_name",
            "message",
            "is_internal",
            "attachments",
            "created_at",
        )
        read_only_fields = ("id", "ticket", "sender", "sender_name", "attachments", "created_at")

    def get_sender_name(self, obj):
        sender = getattr(obj, "sender", None)
        if not sender:
            return ""
        full = f"{getattr(sender, 'first_name', '')} {getattr(sender, 'last_name', '')}".strip()
        return full or getattr(sender, "mobile", "") or getattr(sender, "email", "") or str(sender.id)

    def get_attachments(self, obj):
        request = self.context.get("request")
        qs = obj.attachments.all().order_by("created_at")
        return SupportTicketAttachmentSerializer(qs, many=True, context={"request": request}).data


class SupportTicketListSerializer(serializers.ModelSerializer):
    user_name = serializers.SerializerMethodField()
    assigned_to_name = serializers.SerializerMethodField()
    message_count = serializers.SerializerMethodField()
    sla_state = serializers.SerializerMethodField()

    class Meta:
        model = SupportTicket
        fields = (
            "id",
            "ticket_number",
            "user",
            "user_name",
            "subject",
            "category",
            "priority",
            "status",
            "assigned_to",
            "assigned_to_name",
            "message_count",
            "sla_state",
            "first_response_at",
            "first_response_due_at",
            "resolved_at",
            "resolution_due_at",
            "closed_at",
            "last_user_reply_at",
            "last_admin_reply_at",
            "sla_breached_at",
            "escalated_at",
            "escalation_level",
            "created_at",
            "updated_at",
        )
        read_only_fields = fields

    def get_user_name(self, obj):
        user = getattr(obj, "user", None)
        if not user:
            return ""
        full = f"{getattr(user, 'first_name', '')} {getattr(user, 'last_name', '')}".strip()
        return full or getattr(user, "mobile", "") or getattr(user, "email", "") or str(user.id)

    def get_assigned_to_name(self, obj):
        assignee = getattr(obj, "assigned_to", None)
        if not assignee:
            return ""
        full = f"{getattr(assignee, 'first_name', '')} {getattr(assignee, 'last_name', '')}".strip()
        return full or getattr(assignee, "mobile", "") or getattr(assignee, "email", "") or str(assignee.id)

    def get_message_count(self, obj):
        return int(getattr(obj, "messages_count", 0) or obj.messages.count())

    def get_sla_state(self, obj):
        if obj.sla_breached_at:
            return "breached"
        if obj.status in {"resolved", "closed"}:
            return "met"
        return "active"


class SupportTicketDetailSerializer(serializers.ModelSerializer):
    user_name = serializers.SerializerMethodField()
    assigned_to_name = serializers.SerializerMethodField()
    messages = serializers.SerializerMethodField()
    ticket_attachments = serializers.SerializerMethodField()
    sla_state = serializers.SerializerMethodField()

    class Meta:
        model = SupportTicket
        fields = (
            "id",
            "ticket_number",
            "user",
            "user_name",
            "subject",
            "description",
            "category",
            "priority",
            "status",
            "assigned_to",
            "assigned_to_name",
            "first_response_at",
            "first_response_due_at",
            "resolved_at",
            "resolution_due_at",
            "closed_at",
            "last_user_reply_at",
            "last_admin_reply_at",
            "reopened_count",
            "sla_breached_at",
            "escalated_at",
            "escalation_level",
            "sla_state",
            "created_at",
            "updated_at",
            "ticket_attachments",
            "messages",
        )
        read_only_fields = fields

    def get_user_name(self, obj):
        user = getattr(obj, "user", None)
        if not user:
            return ""
        full = f"{getattr(user, 'first_name', '')} {getattr(user, 'last_name', '')}".strip()
        return full or getattr(user, "mobile", "") or getattr(user, "email", "") or str(user.id)

    def get_assigned_to_name(self, obj):
        assignee = getattr(obj, "assigned_to", None)
        if not assignee:
            return ""
        full = f"{getattr(assignee, 'first_name', '')} {getattr(assignee, 'last_name', '')}".strip()
        return full or getattr(assignee, "mobile", "") or getattr(assignee, "email", "") or str(assignee.id)

    def get_messages(self, obj):
        request = self.context.get("request")
        show_internal = bool(self.context.get("show_internal", False))

        qs = obj.messages.select_related("sender").order_by("created_at")
        if not show_internal:
            qs = qs.filter(is_internal=False)

        # Users should never receive internal messages.
        if request and request.user and obj.user_id == request.user.id:
            qs = qs.filter(is_internal=False)

        return SupportTicketMessageSerializer(qs, many=True, context={"request": request}).data

    def get_ticket_attachments(self, obj):
        request = self.context.get("request")
        qs = obj.attachments.filter(message__isnull=True).order_by("created_at")
        return SupportTicketAttachmentSerializer(qs, many=True, context={"request": request}).data

    def get_sla_state(self, obj):
        if obj.sla_breached_at:
            return "breached"
        if obj.status in {"resolved", "closed"}:
            return "met"
        return "active"
