from __future__ import annotations

from typing import TYPE_CHECKING, Any

from pydantic import BaseModel, ConfigDict, Field

from . import __version__ as A2A_PACK_VERSION
from .runtime import AgentRuntime, SkillPolicy
from .workspace import WorkspaceAccess

if TYPE_CHECKING:
    from .agent import A2AAgent


class SkillCard(BaseModel):
    """Public description of a single skill, shaped for the A2A spec."""

    model_config = ConfigDict(extra="forbid")

    id: str
    name: str
    description: str
    tags: list[str] = Field(default_factory=list)
    scopes: list[str] = Field(default_factory=list)
    stream: bool = False
    policy: SkillPolicy = Field(default_factory=SkillPolicy)
    input_schema: dict[str, Any]
    output_schema: dict[str, Any]


class AgentCard(BaseModel):
    """Public description of an agent.

    Mirrors the A2A Agent Card spec: identity, capabilities, IO modes, and
    the catalog of skills the agent advertises.
    """

    model_config = ConfigDict(extra="forbid")

    name: str
    description: str
    version: str
    skills: list[SkillCard]
    capabilities: dict[str, Any] = Field(default_factory=dict)
    input_modes: list[str] = Field(default_factory=lambda: ["application/json"])
    output_modes: list[str] = Field(default_factory=lambda: ["application/json"])
    required_secrets: list[str] = Field(default_factory=list)
    required_env: list[str] = Field(default_factory=list)
    runtime: AgentRuntime = Field(default_factory=AgentRuntime)
    state_schema: dict[str, Any] | None = None
    workspace_access: WorkspaceAccess = Field(default_factory=WorkspaceAccess.none)
    mcp_endpoint: str = "/mcp"

    @classmethod
    def from_agent(cls, agent: "A2AAgent") -> "AgentCard":
        agent_cls = type(agent)
        skills = [
            SkillCard(
                id=spec.name,
                name=spec.name,
                description=spec.description,
                tags=list(spec.tags),
                scopes=list(spec.scopes),
                stream=spec.stream,
                policy=spec.policy,
                input_schema=spec.input_schema,
                output_schema=spec.output_schema,
            )
            for spec in agent.skills.values()
        ]
        state_schema = (
            agent_cls.state_model.model_json_schema()
            if agent_cls.state_model is not None
            else None
        )
        capabilities = dict(agent_cls.capabilities)
        capabilities["a2a_pack"] = {
            "package": "a2a-pack",
            "version": A2A_PACK_VERSION,
        }
        return cls(
            name=agent_cls.name,
            description=agent_cls.description,
            version=agent_cls.version,
            skills=skills,
            capabilities=capabilities,
            input_modes=list(agent_cls.input_modes),
            output_modes=list(agent_cls.output_modes),
            required_secrets=list(agent_cls.required_secrets),
            required_env=list(agent_cls.required_env),
            runtime=agent_cls.runtime(),
            state_schema=state_schema,
            workspace_access=agent_cls.workspace_access,
        )
