from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any

from pydantic import BaseModel, Field

from backend.schemas.generated_document import ArtifactReferenceMetadata


@dataclass(frozen=True)
class ArtifactReference:
    """Stable reference to one persisted artifact inside one assistant message artifact group."""

    message_id: str
    artifacts_id: str
    artifact_index: int

    def as_metadata(self) -> ArtifactReferenceMetadata:
        """Serialize this in-memory reference into generated-document metadata shape."""

        return {
            "messageId": self.message_id,
            "artifactsId": self.artifacts_id,
            "artifactIndex": self.artifact_index,
        }


class ArtifactReferenceSpec(BaseModel):
    """Validated artifact reference payload shared by tools that target persisted artifacts."""

    message_id: str = Field(..., description="Assistant message id that originally produced the artifact.")
    artifacts_id: str = Field(
        ...,
        description="Artifacts group id from a prior assistant artifact reference in the conversation context.",
    )
    artifact_index: int = Field(
        ...,
        ge=0,
        description="Zero-based index of the artifact inside that artifacts group. This is not a parts index.",
    )


@dataclass(frozen=True)
class ReadArtifactResult:
    """LLM-ready result for one artifact read operation.

    `result` and `parts` are the public payload returned by the `read_artifact` tool.
    `status`, `read_mode`, `artifact_name`, and `content_text` are also used internally when another backend
    tool reuses the artifact-read path as a normalization step before preparing its own prompt input.
    """

    result: str
    parts: list[dict[str, Any]] = field(default_factory=list)
    status: str = ""
    read_mode: str = ""
    artifact_name: str = ""
    content_text: str = ""


@dataclass(frozen=True)
class ResolvedArtifactRead:
    """Canonical service return type for one artifact reference resolution."""

    reference: ArtifactReference
    read_result: ReadArtifactResult


@dataclass(frozen=True)
class PreparedToolSourceArtifact:
    """Backend-owned source artifact payload ready to be consumed by another tool.

    This typed structure is the output of source-artifact preparation: the orchestrator selected a persisted
    artifact reference, the backend resolved it and normalized it through the artifact-read stack, and the caller
    tool now receives a compact representation with the original reference plus the normalized content it can use.
    """

    reference: ArtifactReference
    artifact_name: str
    read_mode: str
    content: str
    parts: list[dict[str, Any]] = field(default_factory=list)
