"""Content-related type definitions for the SDK.

This module defines the types used to represent messages, content blocks, and other content-related structures in the
SDK. These types are modeled after the Bedrock API.

- Bedrock docs: https://docs.aws.amazon.com/bedrock/latest/APIReference/API_Types_Amazon_Bedrock_Runtime.html
"""

from typing import Any, Literal

from typing_extensions import NotRequired, TypedDict

from .citations import CitationsContentBlock
from .event_loop import Metrics, Usage
from .media import DocumentContent, ImageContent, VideoContent
from .tools import ToolResult, ToolUse


class GuardContentText(TypedDict):
    """Text content to be evaluated by guardrails.

    Attributes:
        qualifiers: The qualifiers describing the text block.
        text: The input text details to be evaluated by the guardrail.
    """

    qualifiers: list[Literal["grounding_source", "query", "guard_content"]]
    text: str


class GuardContent(TypedDict):
    """Content block to be evaluated by guardrails.

    Attributes:
        text: Text within content block to be evaluated by the guardrail.
    """

    text: GuardContentText


class ReasoningTextBlock(TypedDict, total=False):
    """Contains the reasoning that the model used to return the output.

    Attributes:
        signature: A token that verifies that the reasoning text was generated by the model.
        text: The reasoning that the model used to return the output.
    """

    signature: str | None
    text: str


class ReasoningContentBlock(TypedDict, total=False):
    """Contains content regarding the reasoning that is carried out by the model.

    Attributes:
        reasoningText: The reasoning that the model used to return the output.
        redactedContent: The content in the reasoning that was encrypted by the model provider for safety reasons.
    """

    reasoningText: ReasoningTextBlock
    redactedContent: bytes


class CachePoint(TypedDict):
    """A cache point configuration for optimizing conversation history.

    Attributes:
        type: The type of cache point, typically "default".
        ttl: Optional cache TTL duration (e.g. "5m", "1h"). Supported by providers
            that accept Anthropic-compatible cache_control fields.
    """

    type: str
    ttl: NotRequired[str]


class ContentBlock(TypedDict, total=False):
    """A block of content for a message that you pass to, or receive from, a model.

    Attributes:
        cachePoint: A cache point configuration to optimize conversation history.
        document: A document to include in the message.
        guardContent: Contains the content to assess with the guardrail.
        image: Image to include in the message.
        reasoningContent: Contains content regarding the reasoning that is carried out by the model.
        text: Text to include in the message.
        toolResult: The result for a tool request that a model makes.
        toolUse: Information about a tool use request from a model.
        video: Video to include in the message.
        citationsContent: Contains the citations for a document.
    """

    cachePoint: CachePoint
    document: DocumentContent
    guardContent: GuardContent
    image: ImageContent
    reasoningContent: ReasoningContentBlock
    text: str
    toolResult: ToolResult
    toolUse: ToolUse
    video: VideoContent
    citationsContent: CitationsContentBlock


class SystemContentBlock(TypedDict, total=False):
    """Contains configurations for instructions to provide the model for how to handle input.

    Attributes:
        cachePoint: A cache point configuration to optimize conversation history.
        text: A system prompt for the model.
    """

    cachePoint: CachePoint
    text: str


class DeltaContent(TypedDict, total=False):
    """A block of content in a streaming response.

    Attributes:
        text: The content text.
        toolUse: Information about a tool that the model is requesting to use.
    """

    text: str
    toolUse: dict[Literal["input"], str]


class ContentBlockStartToolUse(TypedDict):
    """The start of a tool use block.

    Attributes:
        name: The name of the tool that the model is requesting to use.
        toolUseId: The ID for the tool request.
        reasoningSignature: Token that ties the model's reasoning to this tool call.
    """

    name: str
    toolUseId: str
    reasoningSignature: NotRequired[str]


class ContentBlockStart(TypedDict, total=False):
    """Content block start information.

    Attributes:
        toolUse: Information about a tool that the model is requesting to use.
    """

    toolUse: ContentBlockStartToolUse | None


class ContentBlockDelta(TypedDict):
    """The content block delta event.

    Attributes:
        contentBlockIndex: The block index for a content block delta event.
        delta: The delta for a content block delta event.
    """

    contentBlockIndex: int
    delta: DeltaContent


class ContentBlockStop(TypedDict):
    """A content block stop event.

    Attributes:
        contentBlockIndex: The index for a content block.
    """

    contentBlockIndex: int


Role = Literal["user", "assistant"]
"""Role of a message sender.

- "user": Messages from the user to the assistant
- "assistant": Messages from the assistant to the user
"""


class MessageMetadata(TypedDict, total=False):
    """Optional metadata attached to a message.

    Not sent to model providers — explicitly stripped before model calls.
    Persisted alongside the message in session storage.

    Attributes:
        usage: Token usage information from the model response.
        metrics: Performance metrics from the model response.
        custom: Arbitrary user/framework metadata (e.g. compression provenance).
    """

    usage: Usage
    metrics: Metrics
    custom: dict[str, Any]


class Message(TypedDict):
    """A message in a conversation with the agent.

    Attributes:
        content: The message content.
        role: The role of the message sender.
        metadata: Optional metadata, stripped before model calls.
    """

    content: list[ContentBlock]
    role: Role
    metadata: NotRequired[MessageMetadata]


Messages = list[Message]
"""A list of messages representing a conversation."""


def get_message_metadata(message: Message) -> MessageMetadata:
    """Get metadata for a message, returning empty dict if not present.

    Individual fields (usage, metrics, custom) may not be present. Use .get() to safely access them.
    """
    return message.get("metadata", {})
