"""Auto-detection for MCP transport type."""

from __future__ import annotations

from typing import Any

from mcpbridge.config import MCPConfig, MCPServerConfig
from mcpbridge.transport.base import BaseTransport
from mcpbridge.transport.http_sse import HttpSseTransport
from mcpbridge.transport.stdio import StdioTransport
from mcpbridge.transport.streamable_http import StreamableHttpTransport
from mcpbridge.transport.websocket import WebSocketTransport


def _get(d: Any, key: str, default: Any = None) -> Any:
    if isinstance(d, dict):
        return d.get(key, default)
    return getattr(d, key, default)


def detect_transport(mcp_config: dict[str, Any] | MCPConfig | MCPServerConfig) -> BaseTransport:
    """Detect and construct the correct MCP transport for the given config.

    Detection rules:
    - If `command` is present -> stdio transport
    - If `transport` is explicitly set (not "auto") -> use it
    - If URL starts with ws:// or wss:// -> websocket
    - If URL ends with /sse -> HTTP SSE transport
    - Otherwise -> streamable HTTP transport (preferred default)
    """

    command = _get(mcp_config, "command", None)
    url = _get(mcp_config, "url", None)
    transport = _get(mcp_config, "transport", "auto")

    timeout = int(_get(mcp_config, "timeout", 30))
    headers = dict(_get(mcp_config, "headers", {}) or {})
    args = list(_get(mcp_config, "args", []) or [])
    env = dict(_get(mcp_config, "env", {}) or {})

    if command:
        return StdioTransport(command=str(command), args=[str(a) for a in args], env={str(k): str(v) for k, v in env.items()}, headers=headers, timeout=timeout)

    if transport and transport != "auto":
        transport_str = str(transport)
        if transport_str in {"stdio"}:
            return StdioTransport(command=str(command), args=[str(a) for a in args], env={str(k): str(v) for k, v in env.items()}, headers=headers, timeout=timeout)
        if transport_str in {"http", "sse", "http_sse"}:
            return HttpSseTransport(url=str(url), headers=headers, timeout=timeout)
        if transport_str in {"streamable_http"}:
            return StreamableHttpTransport(url=str(url), headers=headers, timeout=timeout)
        if transport_str in {"ws", "websocket"}:
            return WebSocketTransport(url=str(url), headers=headers, timeout=timeout)
        # Fall back to default below if an unknown string is supplied.

    if not url:
        # No URL and no command: can't detect.
        raise ValueError("MCP transport detection failed: missing both `url` and `command`")

    url_str = str(url)
    if url_str.startswith("ws://") or url_str.startswith("wss://"):
        return WebSocketTransport(url=url_str, headers=headers, timeout=timeout)
    if url_str.endswith("/sse"):
        return HttpSseTransport(url=url_str, headers=headers, timeout=timeout)
    return StreamableHttpTransport(url=url_str, headers=headers, timeout=timeout)

