from rest_framework import serializers

from apps.accounts.serializers import UserSerializer
from apps.core.choices.serializers import RichChoiceSerializerField

from .models import EmailThread, Ticket


class SubmitterProfileSerializer(serializers.Serializer):
    """Nested serializer for submitter profile data."""

    display_name = serializers.CharField(source="profile.display_name", allow_null=True)
    created_at = serializers.DateTimeField(source="date_joined", allow_null=True)
    coaster_count = serializers.IntegerField(source="profile.coaster_credit_count", allow_null=True, default=0)
    ride_count = serializers.IntegerField(source="profile.ride_credit_count", allow_null=True, default=0)
    park_count = serializers.IntegerField(source="profile.park_credit_count", allow_null=True, default=0)
    review_count = serializers.IntegerField(source="profile.review_count", allow_null=True, default=0)
    avatar_url = serializers.CharField(source="profile.avatar_url", allow_null=True)


class TicketSerializer(serializers.ModelSerializer):
    """Serializer for Ticket model with full frontend compatibility."""

    # User fields
    user = UserSerializer(read_only=True)
    user_id = serializers.UUIDField(source="user.id", read_only=True, allow_null=True)
    submitter_username = serializers.CharField(source="user.username", read_only=True, allow_null=True)
    submitter_reputation = serializers.SerializerMethodField()
    submitter_profile = serializers.SerializerMethodField()

    # Choice display fields
    category_display = serializers.CharField(source="get_category_display", read_only=True)
    status_display = serializers.CharField(source="get_status_display", read_only=True)

    # Computed fields
    thread_id = serializers.CharField(read_only=True)
    response_count = serializers.IntegerField(read_only=True)
    last_admin_response_at = serializers.DateTimeField(read_only=True, allow_null=True)

    # Resolution tracking (alias resolved_by username)
    resolved_by_username = serializers.CharField(source="resolved_by.username", read_only=True, allow_null=True)

    # Admin fields
    assigned_to_username = serializers.CharField(source="assigned_to.username", read_only=True, allow_null=True)
    archived_by_username = serializers.CharField(source="archived_by.username", read_only=True, allow_null=True)

    class Meta:
        model = Ticket
        fields = [
            # Core fields
            "id",
            "created_at",
            "updated_at",
            # User/submitter fields
            "user",
            "user_id",
            "submitter_username",
            "submitter_reputation",
            "submitter_profile",
            "name",
            "email",
            # Ticket content
            "subject",
            "message",
            "category",
            "category_display",
            # Status
            "status",
            "status_display",
            # Ticket number
            "ticket_number",
            # Admin management
            "admin_notes",
            "assigned_to",
            "assigned_to_username",
            # Resolution
            "resolved_at",
            "resolved_by",
            "resolved_by_username",
            # Thread info
            "thread_id",
            "last_admin_response_at",
            "response_count",
            # Archive
            "archived_at",
            "archived_by",
            "archived_by_username",
        ]
        read_only_fields = [
            "id",
            "created_at",
            "updated_at",
            "user",
            "user_id",
            "submitter_username",
            "submitter_reputation",
            "submitter_profile",
            "ticket_number",
            "thread_id",
            "response_count",
            "last_admin_response_at",
        ]

    def get_submitter_reputation(self, obj):
        """Get the submitter's reputation score."""
        if obj.user and hasattr(obj.user, "profile"):
            return getattr(obj.user.profile, "reputation", 0)
        return None

    def get_submitter_profile(self, obj):
        """Get a subset of profile data for display."""
        if not obj.user or not hasattr(obj.user, "profile"):
            return None
        profile = obj.user.profile
        return {
            "display_name": getattr(profile, "display_name", None),
            "created_at": obj.user.date_joined.isoformat() if obj.user.date_joined else None,
            "coaster_count": getattr(profile, "coaster_credit_count", 0),
            "ride_count": getattr(profile, "ride_credit_count", 0),
            "park_count": getattr(profile, "park_credit_count", 0),
            "review_count": getattr(profile, "review_count", 0),
            "avatar_url": getattr(profile, "avatar_url", None),
        }

    def validate(self, data):
        # Ensure email is provided if user is anonymous
        request = self.context.get("request")
        if request and not request.user.is_authenticated and not data.get("email"):
            raise serializers.ValidationError({"email": "Email is required for guests."})
        return data


class EmailThreadSerializer(serializers.ModelSerializer):
    """Serializer for EmailThread model."""

    # NOTE: Frontend uses submission_id, we provide ticket as that field
    submission_id = serializers.UUIDField(source="ticket.id", read_only=True)
    sent_by_username = serializers.CharField(source="sent_by.username", read_only=True, allow_null=True)

    class Meta:
        model = EmailThread
        fields = [
            "id",
            "created_at",
            "submission_id",
            "message_id",
            "from_email",
            "to_email",
            "subject",
            "body_text",
            "direction",
            "sent_by",
            "sent_by_username",
        ]
        read_only_fields = ["id", "created_at", "submission_id"]


class ReportSerializer(serializers.ModelSerializer):
    """Serializer for Report model."""

    reporter_username = serializers.CharField(source="reporter.username", read_only=True, allow_null=True)
    resolved_by_username = serializers.CharField(source="resolved_by.username", read_only=True, allow_null=True)
    report_type_display = serializers.CharField(source="get_report_type_display", read_only=True)
    status_display = serializers.CharField(source="get_status_display", read_only=True)
    content_type_name = serializers.CharField(source="content_type.model", read_only=True)
    is_resolved = serializers.BooleanField(read_only=True)

    class Meta:
        from .models import Report

        model = Report
        fields = [
            "id",
            "reporter",
            "reporter_username",
            "content_type",
            "content_type_name",
            "object_id",
            "report_type",
            "report_type_display",
            "reason",
            "status",
            "status_display",
            "resolved_at",
            "resolved_by",
            "resolved_by_username",
            "resolution_notes",
            "is_resolved",
            "created_at",
            "updated_at",
        ]
        read_only_fields = [
            "id",
            "reporter",
            "resolved_at",
            "resolved_by",
            "created_at",
            "updated_at",
        ]


class ReportCreateSerializer(serializers.ModelSerializer):
    """Serializer for creating reports with entity type as string."""

    entity_type = serializers.CharField(write_only=True, help_text="Type of entity: park, ride, review, etc.")
    entity_id = serializers.CharField(write_only=True, help_text="ID of the entity being reported")

    class Meta:
        from .models import Report

        model = Report
        fields = [
            "entity_type",
            "entity_id",
            "report_type",
            "reason",
        ]

    def validate(self, data):
        from django.contrib.contenttypes.models import ContentType

        entity_type = data.pop("entity_type")
        entity_id = data.pop("entity_id")

        # Map common entity types to app.model
        type_mapping = {
            "park": ("parks", "park"),
            "ride": ("rides", "ride"),
            "review": ("reviews", "review"),
            "user": ("accounts", "user"),
        }

        if entity_type in type_mapping:
            app_label, model_name = type_mapping[entity_type]
        else:
            # Try to parse as app.model
            parts = entity_type.split(".")
            if len(parts) != 2:
                raise serializers.ValidationError(
                    {"entity_type": f"Unknown entity type: {entity_type}. Use 'park', 'ride', 'review', or 'app.model'."}
                )
            app_label, model_name = parts

        try:
            content_type = ContentType.objects.get(app_label=app_label, model=model_name)
        except ContentType.DoesNotExist:
            raise serializers.ValidationError({"entity_type": f"Unknown entity type: {entity_type}"})

        data["content_type"] = content_type
        data["object_id"] = entity_id
        return data


class ReportResolveSerializer(serializers.Serializer):
    """Serializer for resolving reports."""

    # Use RichChoiceSerializerField with only resolution statuses
    status = RichChoiceSerializerField(
        choice_group="report_statuses",
        domain="support",
        default="resolved",
    )
    notes = serializers.CharField(required=False, allow_blank=True)


# =============================================================================
# Support Ticket Action Serializers
# =============================================================================


class SendReplySerializer(serializers.Serializer):
    """
    Input serializer for send_reply action.
    
    Validates the request body for sending an email reply to a ticket.
    Supports both snake_case and camelCase field names for frontend compatibility.
    """

    # Primary fields (required=False because we validate manually to support camelCase)
    reply_body = serializers.CharField(
        required=False,
        min_length=1,
        max_length=50000,
        help_text="The body text of the email reply",
    )
    new_status = RichChoiceSerializerField(
        choice_group="ticket_statuses",
        domain="support",
        required=False,
        allow_null=True,
        help_text="Optionally update the ticket status after sending reply",
    )

    # camelCase aliases for frontend compatibility
    replyBody = serializers.CharField(required=False, write_only=True)
    newStatus = serializers.CharField(required=False, write_only=True, allow_null=True)

    def validate(self, data: dict) -> dict:
        """Normalize camelCase to snake_case and validate required fields."""
        # Normalize camelCase to snake_case
        if "replyBody" in data and data["replyBody"]:
            data["reply_body"] = data.pop("replyBody")
        elif "replyBody" in data:
            data.pop("replyBody")

        if "newStatus" in data and data["newStatus"]:
            data["new_status"] = data.pop("newStatus")
        elif "newStatus" in data:
            data.pop("newStatus")

        # Validate required fields
        if not data.get("reply_body"):
            raise serializers.ValidationError({"reply_body": "This field is required."})

        return data


class SendReplyResponseSerializer(serializers.Serializer):
    """Response serializer for send_reply action."""

    detail = serializers.CharField()
    thread_id = serializers.UUIDField()
    ticket_number = serializers.CharField()


class MergeTicketsSerializer(serializers.Serializer):
    """
    Input serializer for merge tickets action.
    
    Validates the request body for merging multiple tickets into one.
    Supports both snake_case and camelCase field names for frontend compatibility.
    """

    # Primary fields (required=False because we validate manually to support camelCase)
    primary_ticket_id = serializers.UUIDField(
        required=False,
        help_text="UUID of the primary ticket that will absorb others",
    )
    merge_ticket_ids = serializers.ListField(
        child=serializers.UUIDField(),
        required=False,
        min_length=1,
        help_text="List of ticket UUIDs to merge into the primary",
    )
    merge_reason = serializers.CharField(
        required=False,
        allow_blank=True,
        max_length=500,
        help_text="Optional reason for the merge",
    )

    # camelCase aliases for frontend compatibility
    primaryTicketId = serializers.UUIDField(required=False, write_only=True)
    mergeTicketIds = serializers.ListField(
        child=serializers.UUIDField(),
        required=False,
        write_only=True,
    )
    mergeReason = serializers.CharField(required=False, write_only=True, allow_blank=True)

    def validate(self, data: dict) -> dict:
        """Normalize camelCase to snake_case and validate required fields."""
        # Normalize camelCase to snake_case
        if "primaryTicketId" in data and data["primaryTicketId"]:
            data["primary_ticket_id"] = data.pop("primaryTicketId")
        elif "primaryTicketId" in data:
            data.pop("primaryTicketId")

        if "mergeTicketIds" in data and data["mergeTicketIds"]:
            data["merge_ticket_ids"] = data.pop("mergeTicketIds")
        elif "mergeTicketIds" in data:
            data.pop("mergeTicketIds")

        if "mergeReason" in data and data["mergeReason"]:
            data["merge_reason"] = data.pop("mergeReason")
        elif "mergeReason" in data:
            data.pop("mergeReason")

        # Validate required fields
        if not data.get("primary_ticket_id"):
            raise serializers.ValidationError({"primary_ticket_id": "This field is required."})
        if not data.get("merge_ticket_ids"):
            raise serializers.ValidationError({"merge_ticket_ids": "This field is required."})

        return data


class MergeTicketsResponseSerializer(serializers.Serializer):
    """Response serializer for merge tickets action."""

    detail = serializers.CharField()
    primaryTicketNumber = serializers.CharField()
    mergedCount = serializers.IntegerField()
    threadsConsolidated = serializers.IntegerField()
