"""Tests for OpenTelemetry span instrumentation in BaseACPServer.

These tests verify that the OpenTelemetry span creation, attribute setting,
and error recording work correctly in the _process_notification and
_process_request methods of BaseACPServer.
"""

from __future__ import annotations

from typing import Any
from unittest.mock import MagicMock, patch

import pytest
from opentelemetry import trace
from opentelemetry.trace import Status, StatusCode

from terminaluse.lib.types.acp import CancelTaskParams, RPCMethod, SendEventParams
from terminaluse.types.agent import Agent
from terminaluse.types.event import Event
from terminaluse.types.task import Task
from terminaluse.types.task_message_content import TaskMessageContent_Text

# =============================================================================
# Fixtures
# =============================================================================


@pytest.fixture
def mock_tracer():
    """Create a mock tracer that returns controllable mock spans."""
    tracer = MagicMock()
    return tracer


@pytest.fixture
def mock_span():
    """Create a mock span with all expected methods."""
    span = MagicMock()
    span.set_attribute = MagicMock()
    span.set_status = MagicMock()
    span.record_exception = MagicMock()
    # Make it work as a context manager
    span.__enter__ = MagicMock(return_value=span)
    span.__exit__ = MagicMock(return_value=None)
    return span


@pytest.fixture
def sample_task() -> Task:
    """Fixture that provides a sample Task object."""
    return Task(
        id="test-task-123",
        namespace_id="ns-123",
        filesystem_id="fs-123",
        status="RUNNING",
    )


@pytest.fixture
def sample_agent() -> Agent:
    """Fixture that provides a sample Agent object."""
    return Agent(
        id="test-agent-456",
        name="test-agent",
        namespace_id="ns-123",
        description="Test agent",
        created_at="2023-01-01T00:00:00Z",
        updated_at="2023-01-01T00:00:00Z",
    )


@pytest.fixture
def sample_event(sample_task: Task, sample_agent: Agent) -> Event:
    """Fixture that provides a sample Event object."""
    return Event(
        id="event-789",
        agent_id=sample_agent.id,
        task_id=sample_task.id,
        sequence_id=1,
        created_at="2023-01-01T00:00:00Z",
        content=TaskMessageContent_Text(
            author="user",
            content="Hello, world!",
        ),
    )


@pytest.fixture
def sample_send_event_params(sample_task: Task, sample_agent: Agent, sample_event: Event) -> SendEventParams:
    """Fixture that provides sample SendEventParams."""
    return SendEventParams(
        agent=sample_agent,
        task=sample_task,
        event=sample_event,
    )


@pytest.fixture
def sample_cancel_params(sample_task: Task, sample_agent: Agent) -> CancelTaskParams:
    """Fixture that provides sample CancelTaskParams."""
    return CancelTaskParams(
        agent=sample_agent,
        task=sample_task,
    )


# =============================================================================
# Tests for _build_handler_span_attributes
# =============================================================================


class TestBuildHandlerSpanAttributes:
    """Test the _build_handler_span_attributes method."""

    def test_returns_correct_handler_name(self, sample_send_event_params: SendEventParams):
        """Test that handler name is extracted correctly."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def my_test_handler(params: Any) -> None:
                pass

            server._handlers[RPCMethod.EVENT_SEND] = my_test_handler

            handler_name, attributes = server._build_handler_span_attributes(
                RPCMethod.EVENT_SEND,
                sample_send_event_params,
            )

            assert handler_name == "my_test_handler"

    def test_includes_rpc_method_attribute(self, sample_send_event_params: SendEventParams):
        """Test that rpc.method attribute is included."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def handler(params: Any) -> None:
                pass

            server._handlers[RPCMethod.EVENT_SEND] = handler

            _, attributes = server._build_handler_span_attributes(
                RPCMethod.EVENT_SEND,
                sample_send_event_params,
            )

            assert attributes["rpc.method"] == "event/send"

    def test_includes_handler_execution_mode(self, sample_send_event_params: SendEventParams):
        """Test that handler.execution_mode attribute is included."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def handler(params: Any) -> None:
                pass

            server._handlers[RPCMethod.EVENT_SEND] = handler

            _, attributes = server._build_handler_span_attributes(
                RPCMethod.EVENT_SEND,
                sample_send_event_params,
            )

            assert attributes["handler.execution_mode"] == "async"

    def test_includes_task_id_when_present(self, sample_send_event_params: SendEventParams):
        """Test that task.id attribute is included when task has ID."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def handler(params: Any) -> None:
                pass

            server._handlers[RPCMethod.EVENT_SEND] = handler

            _, attributes = server._build_handler_span_attributes(
                RPCMethod.EVENT_SEND,
                sample_send_event_params,
            )

            assert attributes["task.id"] == "test-task-123"

    def test_includes_agent_id_when_present(self, sample_send_event_params: SendEventParams):
        """Test that agent.id attribute is included when agent has ID."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def handler(params: Any) -> None:
                pass

            server._handlers[RPCMethod.EVENT_SEND] = handler

            _, attributes = server._build_handler_span_attributes(
                RPCMethod.EVENT_SEND,
                sample_send_event_params,
            )

            assert attributes["agent.id"] == "test-agent-456"

    def test_includes_request_id_when_provided(self, sample_send_event_params: SendEventParams):
        """Test that rpc.request_id attribute is included when request_id is provided."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def handler(params: Any) -> None:
                pass

            server._handlers[RPCMethod.EVENT_SEND] = handler

            _, attributes = server._build_handler_span_attributes(
                RPCMethod.EVENT_SEND,
                sample_send_event_params,
                request_id="req-12345",
            )

            assert attributes["rpc.request_id"] == "req-12345"

    def test_excludes_request_id_when_none(self, sample_send_event_params: SendEventParams):
        """Test that rpc.request_id attribute is excluded when request_id is None."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def handler(params: Any) -> None:
                pass

            server._handlers[RPCMethod.EVENT_SEND] = handler

            _, attributes = server._build_handler_span_attributes(
                RPCMethod.EVENT_SEND,
                sample_send_event_params,
                request_id=None,
            )

            assert "rpc.request_id" not in attributes

    def test_request_id_converted_to_string(self, sample_send_event_params: SendEventParams):
        """Test that integer request_id is converted to string."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def handler(params: Any) -> None:
                pass

            server._handlers[RPCMethod.EVENT_SEND] = handler

            _, attributes = server._build_handler_span_attributes(
                RPCMethod.EVENT_SEND,
                sample_send_event_params,
                request_id=12345,
            )

            assert attributes["rpc.request_id"] == "12345"


# =============================================================================
# Tests for _process_notification span instrumentation
# =============================================================================


class TestProcessNotificationSpanInstrumentation:
    """Test span instrumentation in _process_notification method."""

    @pytest.mark.asyncio
    async def test_creates_span_with_correct_name(
        self,
        mock_span: MagicMock,
        sample_send_event_params: SendEventParams,
    ):
        """Test that _process_notification creates a span named 'task.handler.execute'."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def handler(params: Any) -> None:
                pass

            server._handlers[RPCMethod.EVENT_SEND] = handler

            mock_tracer = MagicMock()
            mock_tracer.start_as_current_span.return_value = mock_span

            with patch(
                "terminaluse.lib.sdk.fastacp.base.base_acp_server._tracer",
                mock_tracer,
            ):
                await server._process_notification(RPCMethod.EVENT_SEND, sample_send_event_params)

            # Verify span was started with correct name
            mock_tracer.start_as_current_span.assert_called_once()
            call_args = mock_tracer.start_as_current_span.call_args
            assert call_args[0][0] == "task.handler.execute"

    @pytest.mark.asyncio
    async def test_span_includes_correct_attributes(
        self,
        mock_span: MagicMock,
        sample_send_event_params: SendEventParams,
    ):
        """Test that _process_notification span includes correct attributes."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def my_handler(params: Any) -> None:
                pass

            server._handlers[RPCMethod.EVENT_SEND] = my_handler

            mock_tracer = MagicMock()
            mock_tracer.start_as_current_span.return_value = mock_span

            with patch(
                "terminaluse.lib.sdk.fastacp.base.base_acp_server._tracer",
                mock_tracer,
            ):
                await server._process_notification(RPCMethod.EVENT_SEND, sample_send_event_params)

            # Verify attributes passed to span
            call_args = mock_tracer.start_as_current_span.call_args
            attributes = call_args[1]["attributes"]
            assert attributes["rpc.method"] == "event/send"
            assert attributes["handler.name"] == "my_handler"
            assert attributes["handler.execution_mode"] == "async"
            assert attributes["task.id"] == "test-task-123"
            assert attributes["agent.id"] == "test-agent-456"

    @pytest.mark.asyncio
    async def test_records_handler_duration_on_success(
        self,
        mock_span: MagicMock,
        sample_send_event_params: SendEventParams,
    ):
        """Test that handler duration is recorded as span attribute on success."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def handler(params: Any) -> None:
                await asyncio.sleep(0.01)  # Small delay to ensure measurable duration

            import asyncio

            server._handlers[RPCMethod.EVENT_SEND] = handler

            mock_tracer = MagicMock()
            mock_tracer.start_as_current_span.return_value = mock_span

            with patch(
                "terminaluse.lib.sdk.fastacp.base.base_acp_server._tracer",
                mock_tracer,
            ):
                await server._process_notification(RPCMethod.EVENT_SEND, sample_send_event_params)

            # Verify duration attribute was set
            mock_span.set_attribute.assert_called()
            duration_calls = [
                c for c in mock_span.set_attribute.call_args_list if c[0][0] == "handler.duration_seconds"
            ]
            assert len(duration_calls) == 1
            duration = duration_calls[0][0][1]
            assert duration >= 0.01  # Should be at least 10ms

    @pytest.mark.asyncio
    async def test_records_error_status_on_exception(
        self,
        mock_span: MagicMock,
        sample_send_event_params: SendEventParams,
    ):
        """Test that span status is set to ERROR when handler raises exception."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def failing_handler(params: Any) -> None:
                raise ValueError("Test error")

            server._handlers[RPCMethod.EVENT_SEND] = failing_handler

            mock_tracer = MagicMock()
            mock_tracer.start_as_current_span.return_value = mock_span

            with patch(
                "terminaluse.lib.sdk.fastacp.base.base_acp_server._tracer",
                mock_tracer,
            ):
                # Should not raise - error is handled
                await server._process_notification(RPCMethod.EVENT_SEND, sample_send_event_params)

            # Verify set_status was called with ERROR status
            mock_span.set_status.assert_called_once()
            status_call = mock_span.set_status.call_args[0][0]
            assert isinstance(status_call, Status)
            assert status_call.status_code == StatusCode.ERROR
            assert "Test error" in status_call.description

    @pytest.mark.asyncio
    async def test_records_exception_on_span(
        self,
        mock_span: MagicMock,
        sample_send_event_params: SendEventParams,
    ):
        """Test that exception is recorded on span when handler raises."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            test_error = ValueError("Test error for recording")

            async def failing_handler(params: Any) -> None:
                raise test_error

            server._handlers[RPCMethod.EVENT_SEND] = failing_handler

            mock_tracer = MagicMock()
            mock_tracer.start_as_current_span.return_value = mock_span

            with patch(
                "terminaluse.lib.sdk.fastacp.base.base_acp_server._tracer",
                mock_tracer,
            ):
                await server._process_notification(RPCMethod.EVENT_SEND, sample_send_event_params)

            # Verify record_exception was called with the exception
            mock_span.record_exception.assert_called_once()
            recorded_exception = mock_span.record_exception.call_args[0][0]
            assert isinstance(recorded_exception, ValueError)
            assert str(recorded_exception) == "Test error for recording"

    @pytest.mark.asyncio
    async def test_records_duration_even_on_exception(
        self,
        mock_span: MagicMock,
        sample_send_event_params: SendEventParams,
    ):
        """Test that handler duration is recorded even when handler raises."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def failing_handler(params: Any) -> None:
                raise RuntimeError("Handler failure")

            server._handlers[RPCMethod.EVENT_SEND] = failing_handler

            mock_tracer = MagicMock()
            mock_tracer.start_as_current_span.return_value = mock_span

            with patch(
                "terminaluse.lib.sdk.fastacp.base.base_acp_server._tracer",
                mock_tracer,
            ):
                await server._process_notification(RPCMethod.EVENT_SEND, sample_send_event_params)

            # Verify duration attribute was set
            duration_calls = [
                c for c in mock_span.set_attribute.call_args_list if c[0][0] == "handler.duration_seconds"
            ]
            assert len(duration_calls) == 1


# =============================================================================
# Tests for _process_request span instrumentation
# =============================================================================


class TestProcessRequestSpanInstrumentation:
    """Test span instrumentation in _process_request method."""

    @pytest.mark.asyncio
    async def test_creates_span_with_correct_name(
        self,
        mock_span: MagicMock,
        sample_cancel_params: CancelTaskParams,
    ):
        """Test that _process_request creates a span named 'task.handler.execute'."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def handler(params: Any) -> None:
                pass

            server._handlers[RPCMethod.TASK_CANCEL] = handler

            mock_tracer = MagicMock()
            mock_tracer.start_as_current_span.return_value = mock_span

            with patch(
                "terminaluse.lib.sdk.fastacp.base.base_acp_server._tracer",
                mock_tracer,
            ):
                await server._process_request("req-123", RPCMethod.TASK_CANCEL, sample_cancel_params)

            # Verify span was started with correct name
            mock_tracer.start_as_current_span.assert_called_once()
            call_args = mock_tracer.start_as_current_span.call_args
            assert call_args[0][0] == "task.handler.execute"

    @pytest.mark.asyncio
    async def test_span_includes_request_id_attribute(
        self,
        mock_span: MagicMock,
        sample_cancel_params: CancelTaskParams,
    ):
        """Test that _process_request span includes request_id attribute."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def handler(params: Any) -> None:
                pass

            server._handlers[RPCMethod.TASK_CANCEL] = handler

            mock_tracer = MagicMock()
            mock_tracer.start_as_current_span.return_value = mock_span

            with patch(
                "terminaluse.lib.sdk.fastacp.base.base_acp_server._tracer",
                mock_tracer,
            ):
                await server._process_request("my-request-id", RPCMethod.TASK_CANCEL, sample_cancel_params)

            # Verify attributes include request_id
            call_args = mock_tracer.start_as_current_span.call_args
            attributes = call_args[1]["attributes"]
            assert attributes["rpc.request_id"] == "my-request-id"

    @pytest.mark.asyncio
    async def test_records_handler_duration_on_success(
        self,
        mock_span: MagicMock,
        sample_cancel_params: CancelTaskParams,
    ):
        """Test that handler duration is recorded as span attribute on success."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def handler(params: Any) -> None:
                import asyncio

                await asyncio.sleep(0.01)

            server._handlers[RPCMethod.TASK_CANCEL] = handler

            mock_tracer = MagicMock()
            mock_tracer.start_as_current_span.return_value = mock_span

            with patch(
                "terminaluse.lib.sdk.fastacp.base.base_acp_server._tracer",
                mock_tracer,
            ):
                await server._process_request("req-1", RPCMethod.TASK_CANCEL, sample_cancel_params)

            # Verify duration attribute was set
            duration_calls = [
                c for c in mock_span.set_attribute.call_args_list if c[0][0] == "handler.duration_seconds"
            ]
            assert len(duration_calls) == 1
            duration = duration_calls[0][0][1]
            assert duration >= 0.01

    @pytest.mark.asyncio
    async def test_records_error_status_on_exception(
        self,
        mock_span: MagicMock,
        sample_cancel_params: CancelTaskParams,
    ):
        """Test that span status is set to ERROR when handler raises exception."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def failing_handler(params: Any) -> None:
                raise RuntimeError("Request handler error")

            server._handlers[RPCMethod.TASK_CANCEL] = failing_handler

            mock_tracer = MagicMock()
            mock_tracer.start_as_current_span.return_value = mock_span

            with patch(
                "terminaluse.lib.sdk.fastacp.base.base_acp_server._tracer",
                mock_tracer,
            ):
                await server._process_request("req-1", RPCMethod.TASK_CANCEL, sample_cancel_params)

            # Verify set_status was called with ERROR status using trace.Status
            mock_span.set_status.assert_called_once()
            status_call = mock_span.set_status.call_args[0][0]
            assert isinstance(status_call, Status)
            assert status_call.status_code == StatusCode.ERROR
            assert "Request handler error" in status_call.description

    @pytest.mark.asyncio
    async def test_records_exception_on_span(
        self,
        mock_span: MagicMock,
        sample_cancel_params: CancelTaskParams,
    ):
        """Test that exception is recorded on span when handler raises."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def failing_handler(params: Any) -> None:
                raise KeyError("missing_key")

            server._handlers[RPCMethod.TASK_CANCEL] = failing_handler

            mock_tracer = MagicMock()
            mock_tracer.start_as_current_span.return_value = mock_span

            with patch(
                "terminaluse.lib.sdk.fastacp.base.base_acp_server._tracer",
                mock_tracer,
            ):
                await server._process_request("req-1", RPCMethod.TASK_CANCEL, sample_cancel_params)

            # Verify record_exception was called
            mock_span.record_exception.assert_called_once()
            recorded_exception = mock_span.record_exception.call_args[0][0]
            assert isinstance(recorded_exception, KeyError)

    @pytest.mark.asyncio
    async def test_integer_request_id_converted_to_string(
        self,
        mock_span: MagicMock,
        sample_cancel_params: CancelTaskParams,
    ):
        """Test that integer request_id is converted to string in span attribute."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def handler(params: Any) -> None:
                pass

            server._handlers[RPCMethod.TASK_CANCEL] = handler

            mock_tracer = MagicMock()
            mock_tracer.start_as_current_span.return_value = mock_span

            with patch(
                "terminaluse.lib.sdk.fastacp.base.base_acp_server._tracer",
                mock_tracer,
            ):
                await server._process_request(12345, RPCMethod.TASK_CANCEL, sample_cancel_params)

            # Verify request_id is stringified
            call_args = mock_tracer.start_as_current_span.call_args
            attributes = call_args[1]["attributes"]
            assert attributes["rpc.request_id"] == "12345"


# =============================================================================
# Tests for error handling using trace.Status (verifies fix at lines 546, 570)
# =============================================================================


class TestTraceStatusUsage:
    """Test that trace.Status is used correctly (not _trace.Status).

    These tests verify the fix at lines 546 and 570 where trace.Status
    is used instead of the incorrect _trace.Status reference.
    """

    @pytest.mark.asyncio
    async def test_notification_uses_trace_status_for_error(
        self,
        sample_send_event_params: SendEventParams,
    ):
        """Verify _process_notification uses trace.Status for error recording."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def failing_handler(params: Any) -> None:
                raise Exception("Test")

            server._handlers[RPCMethod.EVENT_SEND] = failing_handler

            # Create a real mock that captures the actual Status object passed
            captured_status = []

            def capture_set_status(status):
                captured_status.append(status)

            mock_span = MagicMock()
            mock_span.set_status = capture_set_status
            mock_span.set_attribute = MagicMock()
            mock_span.record_exception = MagicMock()
            mock_span.__enter__ = MagicMock(return_value=mock_span)
            mock_span.__exit__ = MagicMock(return_value=None)

            mock_tracer = MagicMock()
            mock_tracer.start_as_current_span.return_value = mock_span

            with patch(
                "terminaluse.lib.sdk.fastacp.base.base_acp_server._tracer",
                mock_tracer,
            ):
                await server._process_notification(RPCMethod.EVENT_SEND, sample_send_event_params)

            # Verify it's using the correct trace.Status class
            assert len(captured_status) == 1
            assert type(captured_status[0]).__module__ == "opentelemetry.trace.status"
            assert isinstance(captured_status[0], trace.Status)

    @pytest.mark.asyncio
    async def test_request_uses_trace_status_for_error(
        self,
        sample_cancel_params: CancelTaskParams,
    ):
        """Verify _process_request uses trace.Status for error recording."""
        with patch.dict("os.environ", {"TERMINALUSE_BASE_URL": ""}):
            from terminaluse.lib.sdk.fastacp.base.base_acp_server import BaseACPServer

            server = BaseACPServer()

            async def failing_handler(params: Any) -> None:
                raise Exception("Test")

            server._handlers[RPCMethod.TASK_CANCEL] = failing_handler

            # Create a real mock that captures the actual Status object passed
            captured_status = []

            def capture_set_status(status):
                captured_status.append(status)

            mock_span = MagicMock()
            mock_span.set_status = capture_set_status
            mock_span.set_attribute = MagicMock()
            mock_span.record_exception = MagicMock()
            mock_span.__enter__ = MagicMock(return_value=mock_span)
            mock_span.__exit__ = MagicMock(return_value=None)

            mock_tracer = MagicMock()
            mock_tracer.start_as_current_span.return_value = mock_span

            with patch(
                "terminaluse.lib.sdk.fastacp.base.base_acp_server._tracer",
                mock_tracer,
            ):
                await server._process_request("req-1", RPCMethod.TASK_CANCEL, sample_cancel_params)

            # Verify it's using the correct trace.Status class
            assert len(captured_status) == 1
            assert type(captured_status[0]).__module__ == "opentelemetry.trace.status"
            assert isinstance(captured_status[0], trace.Status)


# =============================================================================
# Tests for tracer initialization
# =============================================================================


class TestTracerInitialization:
    """Test that the module-level tracer is properly initialized."""

    def test_tracer_is_initialized_at_module_level(self):
        """Verify that _tracer is initialized with the correct module name."""
        # Import the module to check the tracer
        from terminaluse.lib.sdk.fastacp.base import base_acp_server

        # The tracer should be initialized
        assert hasattr(base_acp_server, "_tracer")
        assert base_acp_server._tracer is not None

    def test_tracer_uses_module_name(self):
        """Verify that trace.get_tracer is called with the module name."""
        with patch("opentelemetry.trace.get_tracer") as mock_get_tracer:
            # Re-import to trigger the trace.get_tracer call
            import importlib

            from terminaluse.lib.sdk.fastacp.base import base_acp_server

            # Force reimport
            importlib.reload(base_acp_server)

            # Verify get_tracer was called with module name
            mock_get_tracer.assert_called_with("terminaluse.lib.sdk.fastacp.base.base_acp_server")
