"""Tests for serve() function."""

import pytest
from unittest.mock import Mock, patch
from typing import Dict, Any

from mcp_chain.serve import serve


class MockDictMCPServer:
    """Mock DictMCPServer for testing."""
    
    def __init__(self, metadata: Dict[str, Any] = None):
        if metadata is None:
            self._metadata = {"tools": [], "resources": []}
        else:
            self._metadata = metadata
    
    def get_metadata(self) -> Dict[str, Any]:
        return self._metadata
    
    def handle_request(self, request: Dict[str, Any]) -> Dict[str, Any]:
        return {"result": "success"}


def test_serve_function_exists():
    """Test that serve function exists and is callable."""
    assert callable(serve)


@patch('mcp_chain.serve.FastMCPServer')
def test_serve_creates_fastmcp_server(mock_fastmcp_server_class):
    """Test that serve() creates a FastMCPServer instance."""
    mock_chain = MockDictMCPServer()
    mock_server_instance = Mock()
    mock_fastmcp_server_class.return_value = mock_server_instance
    
    # Mock the run method to avoid actually starting a server
    mock_server_instance.run.return_value = None
    
    serve(mock_chain, name="test-server")
    
    # Should have created FastMCPServer with our chain and name
    mock_fastmcp_server_class.assert_called_once_with(mock_chain, name="test-server")
    # Should have called run on the server
    mock_server_instance.run.assert_called_once()


@patch('mcp_chain.serve.FastMCPServer')
def test_serve_passes_kwargs_to_run(mock_fastmcp_server_class):
    """Test that serve() passes kwargs to FastMCP run method."""
    mock_chain = MockDictMCPServer()
    mock_server_instance = Mock()
    mock_fastmcp_server_class.return_value = mock_server_instance
    mock_server_instance.run.return_value = None
    
    # Call serve with additional kwargs
    serve(mock_chain, name="test-server", port=8080, transport="http")
    
    # Should pass kwargs to run method
    mock_server_instance.run.assert_called_once_with(name="test-server", port=8080, transport="http")


@patch('mcp_chain.serve.FastMCPServer')  
def test_serve_with_minimal_args(mock_fastmcp_server_class):
    """Test serve() works with minimal arguments."""
    mock_chain = MockDictMCPServer()
    mock_server_instance = Mock()
    mock_fastmcp_server_class.return_value = mock_server_instance
    mock_server_instance.run.return_value = None
    
    # Should work with just a chain
    serve(mock_chain)
    
    mock_fastmcp_server_class.assert_called_once_with(mock_chain, name="mcp-chain")
    mock_server_instance.run.assert_called_once_with(name="mcp-chain")


def test_serve_validates_chain_is_dict_mcp_server():
    """Test that serve() validates the chain implements DictMCPServer protocol."""
    # This should fail if we pass something that's not a DictMCPServer
    invalid_chain = "not a server"
    
    with pytest.raises((TypeError, AttributeError)):
        serve(invalid_chain)