from rest_framework import serializers

from apps.core.tenancy import get_active_organization, validate_same_organization_field

from .models import Task, Message, Approval


def _validate_user_in_organization(serializer, value):
    """Field validator for a writable User FK: the user must be a member of the
    caller's active organization.

    Users have no `organization` FK (membership is M2M), so
    `validate_same_organization_field` cannot be reused here. Raises the same
    "does not exist" shape so a caller cannot probe for foreign user ids.
    """
    if value is None:
        return value
    request = serializer.context.get("request")
    assert request is not None, (
        f"{serializer.__class__.__name__} must receive request in its context "
        "for cross-organization user validation to run."
    )
    organization = get_active_organization(request)
    if not value.organizations.filter(pk=organization.pk).exists():
        raise serializers.ValidationError(
            f'Invalid pk "{value.pk}" - object does not exist.',
            code="does_not_exist",
        )
    return value


class TaskSerializer(serializers.ModelSerializer):
    """Serializer for Task model."""
    assignee_name = serializers.SerializerMethodField()
    project_name = serializers.SerializerMethodField()
    event_name = serializers.SerializerMethodField()
    created_by_name = serializers.SerializerMethodField()
    message_count = serializers.SerializerMethodField()
    attachment_count = serializers.SerializerMethodField()

    class Meta:
        model = Task
        fields = [
            "id", "title", "description", "status", "priority", "assignee", "assignee_name",
            "project", "project_name", "event", "event_name", "due_date", "tags", "subtasks", "attachments",
            "message_count", "attachment_count", "approved_at", "archived_at", "completed_at", "source",
            "created_by", "created_by_name", "created_at", "updated_at"
        ]
        read_only_fields = ["id", "created_at", "updated_at", "message_count", "attachment_count", "created_by", "approved_at", "archived_at", "completed_at"]

    # The view stamps `organization` on the task, but DRF only checks that
    # these related rows exist — not that they belong to that organization.
    # Without these, a task could link a foreign project/event and notify a
    # user in another tenant with its title and link (SEC-05).
    def validate_assignee(self, value):
        return _validate_user_in_organization(self, value)

    def validate_project(self, value):
        return validate_same_organization_field(self, value)

    def validate_event(self, value):
        return validate_same_organization_field(self, value)

    def get_assignee_name(self, obj):
        if obj.assignee:
            return obj.assignee.get_full_name() or obj.assignee.username
        return None

    def get_project_name(self, obj):
        if obj.project:
            return obj.project.name
        return None

    def get_event_name(self, obj):
        if obj.event:
            return obj.event.name
        return None

    def get_created_by_name(self, obj):
        return obj.created_by.get_full_name() or obj.created_by.username

    def get_message_count(self, obj):
        anno = getattr(obj, "msg_count", None)
        if anno is not None:
            return anno
        return Message.objects.filter(related_task_id=obj.id).count()

    def get_attachment_count(self, obj):
        atts = obj.attachments or []
        return len(atts) if isinstance(atts, list) else 0


class MessageSerializer(serializers.ModelSerializer):
    """Serializer for Message model."""
    sender_name = serializers.SerializerMethodField()

    class Meta:
        model = Message
        fields = ["id", "sender", "sender_name", "content", "attachments", "is_read", "related_task", "related_approval", "created_at"]
        read_only_fields = ["id", "created_at"]

    def get_sender_name(self, obj):
        return obj.sender.get_full_name() or obj.sender.username


class ApprovalSerializer(serializers.ModelSerializer):
    """Serializer for Approval model."""
    requester_name = serializers.SerializerMethodField()
    approver_name = serializers.SerializerMethodField()

    class Meta:
        model = Approval
        fields = [
            "id", "title", "description", "requester", "requester_name",
            "approver", "approver_name", "status", "data", "comment",
            "resolved_at", "created_at"
        ]
        # status / resolved_at / requester are server-controlled. approver assigned at create only.
        read_only_fields = ["id", "created_at", "requester", "status", "resolved_at"]

    def get_requester_name(self, obj):
        return obj.requester.get_full_name() or obj.requester.username

    def get_approver_name(self, obj):
        return obj.approver.get_full_name() or obj.approver.username