"""Request, response, and patch schemas for the Follow domain.

Uses the framework's base schema classes:
    - ``BaseRequestSchema`` — inbound (``extra="forbid"``)
    - ``BaseResponseSchema`` — outbound (``from_attributes=True``)
    - ``BasePatchSchema`` — partial updates (``extra="forbid"``)
"""
from __future__ import annotations

from datetime import datetime

from pydantic import Field

from repo_core.base.schemas import BaseRequestSchema, BaseResponseSchema, BasePatchSchema
from repo_core.domains.follow.model import FollowTargetType


class CreateFollowRequest(BaseRequestSchema):
    """Payload for creating a new follow.

    Usage::

        payload = CreateFollowRequest(
            user_id=42,
            target_type="story",
            target_id="story-abc-123",
        )
    """

    user_id: int = Field(..., gt=0,
                         description="ID of the user who is following")
    target_type: FollowTargetType = Field(...,
                                          description="Kind of object being followed")
    target_id: str = Field(
        ...,
        min_length=1,
        max_length=128,
        description="ID of the followed object within its domain",
    )


class PatchFollowRequest(BasePatchSchema):
    """Partial-update payload for a follow.

    In practice follows are rarely patched (they are created and deleted),
    but the schema exists for framework symmetry and edge cases like
    re-pointing a follow to a merged or renamed target.
    """

    target_type: FollowTargetType | None = Field(
        default=None,
        description="New target type (only if the target's kind changed)",
    )
    target_id: str | None = Field(
        default=None,
        min_length=1,
        max_length=128,
        description="New target ID (e.g. after a merge or rename)",
    )


class FollowResponse(BaseResponseSchema):
    """Serialised follow returned to API callers.

    Accepts ORM objects or dicts directly::

        response = FollowResponse.model_validate(orm_follow)
        data = response.to_dict()
    """

    id: int
    user_id: int
    target_type: FollowTargetType
    target_id: str
    created_at: datetime | None = None
    updated_at: datetime | None = None
