"""
links.py
This module defines the Link types for ActivityPub.
These links are based on the ActivityStreams vocabulary.

For more information, see:
https://www.w3.org/TR/activitystreams-vocabulary/#link
"""

from typing import Any
from pydantic import BaseModel, Field, field_validator

from phederation.utils.serialization import ActivityPubBase


class RelativeLink(BaseModel):
    """Relative link model to indicate where actor information can be found."""

    rel: str = Field(
        ..., description="Relation of this link template."
    )
    type: None | str = Field(
        default='application/json',
        description="The media type, i.e. 'application/activity+json' or 'text/html'.",
    )
    href: str


class RelativeLinkTemplate(BaseModel):
    rel: str = Field(
        ..., description="Relation of this link template."
    )
    template: None | str = Field(
        default='<instance_url>/authorize_interaction?uri={{uri}}',
        description="How to access the information in the link.",
    )

class APLink(ActivityPubBase):
    """
    Represents a Link in ActivityPub.
    
    A Link is an indirect, qualified reference to a resource identified by a URL.
    It can be used to represent a variety of connections between objects in the ActivityPub ecosystem.

    Specification: https://www.w3.org/TR/activitystreams-vocabulary/#link
    Usage: https://www.w3.org/TR/activitypub/#object-without-create
    """
    type: str = Field(default="Link", description="Indicates that this object represents a link")
    href: str = Field(..., description="The target resource pointed to by the link")
    rel: None | list[str] = Field(default=None, description="The relationship between the resource and the link")
    media_type: None | str = Field(default=None, description="The MIME media type of the referenced resource")
    name: None | str = Field(default=None, description="A human-readable name for the link")
    hreflang: None | str = Field(default=None, description="The language of the referenced resource")
    height: None | int = Field(default=None, description="The height of the referenced resource in pixels")
    width: None | int = Field(default=None, description="The width of the referenced resource in pixels")
    preview: None | str = Field(default=None, description="A link to a preview of the referenced resource")

    @field_validator('media_type')
    def validate_media_type(cls, value: Any | None):
        allowed_mimes = ["image/jpeg", "image/png", "application/json", "text/html", "video/mp4"]
        if value and not value in allowed_mimes:
            raise ValueError(f"Invalid MIME type: {value}")
        return value

class APMention(APLink):
    """
    Represents a Mention in ActivityPub.
    
    A Mention is a specialized Link that represents an @mention.
    It is typically used to reference another actor in the content of an object.

    Properties:
        type (Literal["Mention"]): The type of the object, always "Mention" for this class.
        href (ObjectId): The URL of the mentioned actor.
        name (None | str): The name or username of the mentioned actor.

    Inherits all other properties from APLink.

    Specification: https://www.w3.org/TR/activitystreams-vocabulary/#mention
    Usage: https://www.w3.org/TR/activitypub/#mention
    """
    type: str = Field(default="Mention", description="Indicates that this object represents a mention")
