from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, TypedDict

from .constants import Provider, SDK_PROVIDER_HEADER_NAME


@dataclass
class AgentSDKConfig:
    """Configuration for the Scalar Agent SDK."""

    token: str
    base_url: str = field(default="https://services.scalar.com")


class AnthropicMCPConfig(TypedDict):
    type: str
    url: str
    headers: dict[str, str]


class OpenAIMCPParams(TypedDict):
    url: str
    headers: dict[str, str]


class OpenAIMCPConfig(TypedDict):
    name: str
    params: OpenAIMCPParams


def _build_headers(token: str, provider: Provider) -> dict[str, str]:
    return {
        "content-type": "application/json",
        "accept": "application/json, text/event-stream",
        SDK_PROVIDER_HEADER_NAME: provider.value,
        "Authorization": token,
    }


class Installation:
    """Client for a specific Scalar MCP installation."""

    def __init__(self, url: str, installation_id: str, token: str) -> None:
        self._url = url
        self._installation_id = installation_id
        self._token = token

    def create_openai_mcp(self) -> OpenAIMCPConfig:
        """Returns params for constructing MCPServerStreamableHttp from openai-agents.

        Example:
            import asyncio

            from scalar_agent import agent_scalar
            from agents import Agent, Runner
            from agents.mcp import MCPServerStreamableHttp

            async def main() -> None:
                scalar = agent_scalar(token="your-personal-token")
                installation = scalar.installation("your-installation-id")

                server = MCPServerStreamableHttp(**installation.create_openai_mcp())
                await server.connect()

                agent = Agent(name="api-agent", mcp_servers=[server])
                result = await Runner.run(agent, "Which APIs are available that let me create a planet?")
                print(result.final_output)

                await server.cleanup()

            asyncio.run(main())
        """
        return OpenAIMCPConfig(
            name=self._installation_id,
            params=OpenAIMCPParams(
                url=self._url,
                headers=_build_headers(self._token, Provider.OPENAI),
            ),
        )

    def create_anthropic_mcp(self) -> AnthropicMCPConfig:
        """Returns an MCP server configuration for claude_agent_sdk.

        Example:
            import asyncio

            from scalar_agent import agent_scalar
            from claude_agent_sdk import query
            from claude_agent_sdk.types import ClaudeAgentOptions, ResultMessage

            scalar = agent_scalar(token="your-personal-token")
            installation = scalar.installation("your-installation-id")

            async def main() -> None:
                async for message in query(
                    prompt="Which APIs are available that let me create a planet?",
                    options=ClaudeAgentOptions(
                        mcp_servers={"scalar": installation.create_anthropic_mcp()},
                        allowed_tools=["mcp__scalar__*"],
                    ),
                ):
                    if isinstance(message, ResultMessage):
                        print(message.result)

            asyncio.run(main())
        """
        return AnthropicMCPConfig(
            type="http",
            url=self._url,
            headers={
                "Authorization": self._token,
                SDK_PROVIDER_HEADER_NAME: Provider.ANTHROPIC.value,
            },
        )


class ScalarAgent:
    """Scalar agent client for connecting to Scalar MCP servers."""

    def __init__(self, config: AgentSDKConfig) -> None:
        self._config = config

    def installation(self, installation_id: str) -> Installation:
        """Creates an installation client for the given installation ID.

        Example:
            scalar = agent_scalar(token="your-personal-token")
            installation = scalar.installation("your-installation-id")
        """
        base_url = self._config.base_url.rstrip("/")
        url = f"{base_url}/vector/mcp/{installation_id}"
        return Installation(url, installation_id, self._config.token)


def agent_scalar(
    token: str,
    base_url: str = "https://services.scalar.com",
) -> ScalarAgent:
    """Creates a Scalar agent client configured to connect to Scalar's MCP servers.

    Args:
        token: Your Scalar Personal Token used to authenticate requests to your MCP.
        base_url: Base URL of the Scalar MCP server. Defaults to the Scalar environment.

    Example:
        scalar = agent_scalar(token="your-personal-token")
        installation = scalar.installation("your-installation-id")
    """
    return ScalarAgent(AgentSDKConfig(token=token, base_url=base_url))
