"""Tests for MCPServerConfig and ServerConfig MCP section parsing"""

import pytest

from agentkit.server.config import MCPServerConfig, ServerConfig


class TestMCPServerConfig:
    """Tests for MCPServerConfig dataclass"""

    def test_from_dict_stdio(self):
        data = {
            "transport": "stdio",
            "command": "npx",
            "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
            "env": {"NODE_ENV": "production"},
            "timeout": 60.0,
        }
        config = MCPServerConfig.from_dict(data)
        assert config.transport == "stdio"
        assert config.command == "npx"
        assert config.args == ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
        assert config.env == {"NODE_ENV": "production"}
        assert config.timeout == 60.0
        assert config.url is None
        assert config.headers is None

    def test_from_dict_streamable_http(self):
        data = {
            "transport": "streamable_http",
            "url": "http://localhost:3001/mcp",
            "headers": {"Authorization": "Bearer test-token"},
            "timeout": 45.0,
        }
        config = MCPServerConfig.from_dict(data)
        assert config.transport == "streamable_http"
        assert config.url == "http://localhost:3001/mcp"
        assert config.headers == {"Authorization": "Bearer test-token"}
        assert config.timeout == 45.0
        assert config.command is None
        assert config.args is None

    def test_from_dict_sse(self):
        data = {
            "transport": "sse",
            "url": "http://localhost:3002/sse",
        }
        config = MCPServerConfig.from_dict(data)
        assert config.transport == "sse"
        assert config.url == "http://localhost:3002/sse"
        assert config.command is None

    def test_from_dict_defaults(self):
        data = {}
        config = MCPServerConfig.from_dict(data)
        assert config.transport == "stdio"
        assert config.command is None
        assert config.args is None
        assert config.env is None
        assert config.url is None
        assert config.headers is None
        assert config.timeout == 30.0

    def test_validate_stdio_valid(self):
        config = MCPServerConfig(transport="stdio", command="python")
        config.validate()  # Should not raise

    def test_validate_stdio_missing_command(self):
        config = MCPServerConfig(transport="stdio", command=None)
        with pytest.raises(ValueError, match="stdio transport requires 'command'"):
            config.validate()

    def test_validate_streamable_http_missing_url(self):
        config = MCPServerConfig(transport="streamable_http", url=None)
        with pytest.raises(ValueError, match="streamable_http transport requires 'url'"):
            config.validate()

    def test_validate_sse_missing_url(self):
        config = MCPServerConfig(transport="sse", url=None)
        with pytest.raises(ValueError, match="sse transport requires 'url'"):
            config.validate()

    def test_validate_invalid_transport(self):
        config = MCPServerConfig(transport="websocket")
        with pytest.raises(ValueError, match="Invalid transport: websocket"):
            config.validate()

    def test_validate_http_with_url(self):
        config = MCPServerConfig(transport="streamable_http", url="http://localhost:3001")
        config.validate()  # Should not raise

    def test_validate_sse_with_url(self):
        config = MCPServerConfig(transport="sse", url="http://localhost:3002")
        config.validate()  # Should not raise


class TestServerConfigMCPSection:
    """Tests for ServerConfig parsing with mcp section"""

    def test_from_dict_with_mcp_servers(self):
        data = {
            "mcp": {
                "servers": {
                    "filesystem": {
                        "transport": "stdio",
                        "command": "npx",
                        "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
                    },
                    "remote": {
                        "transport": "streamable_http",
                        "url": "http://localhost:3001/mcp",
                    },
                }
            }
        }
        config = ServerConfig.from_dict(data)
        assert len(config.mcp_servers) == 2
        assert "filesystem" in config.mcp_servers
        assert "remote" in config.mcp_servers
        assert config.mcp_servers["filesystem"].transport == "stdio"
        assert config.mcp_servers["filesystem"].command == "npx"
        assert config.mcp_servers["remote"].transport == "streamable_http"
        assert config.mcp_servers["remote"].url == "http://localhost:3001/mcp"

    def test_from_dict_without_mcp_section(self):
        data = {}
        config = ServerConfig.from_dict(data)
        assert config.mcp_servers == {}

    def test_from_dict_with_empty_mcp_servers(self):
        data = {"mcp": {"servers": {}}}
        config = ServerConfig.from_dict(data)
        assert config.mcp_servers == {}

    def test_from_dict_mcp_servers_with_sse(self):
        data = {
            "mcp": {
                "servers": {
                    "sse-server": {
                        "transport": "sse",
                        "url": "http://localhost:3002/sse",
                        "headers": {"X-API-Key": "secret"},
                        "timeout": 60.0,
                    }
                }
            }
        }
        config = ServerConfig.from_dict(data)
        assert len(config.mcp_servers) == 1
        sse_conf = config.mcp_servers["sse-server"]
        assert sse_conf.transport == "sse"
        assert sse_conf.url == "http://localhost:3002/sse"
        assert sse_conf.headers == {"X-API-Key": "secret"}
        assert sse_conf.timeout == 60.0

    def test_from_dict_mcp_ignores_non_dict_entries(self):
        data = {
            "mcp": {
                "servers": {
                    "valid": {
                        "transport": "stdio",
                        "command": "python",
                    },
                    "invalid": "not-a-dict",
                }
            }
        }
        config = ServerConfig.from_dict(data)
        assert len(config.mcp_servers) == 1
        assert "valid" in config.mcp_servers
        assert "invalid" not in config.mcp_servers
