# #region Test.WsLogHandler [C:3] [TYPE Module] [SEMANTICS test,logging,handler,websocket]
# @BRIEF Tests for core/ws_log_handler.py — LogEntry, WebSocketLogHandler.
# @RELATION BINDS_TO -> [WsLogHandlerModule]

from pathlib import Path
import sys

sys.path.insert(0, str(Path(__file__).parent.parent.parent / "src"))

import logging
from unittest.mock import MagicMock, patch
import pytest


# #region test_log_entry [C:2] [TYPE Function]
# @BRIEF Test LogEntry Pydantic model.
class TestLogEntry:
    def test_creates_with_minimal_fields(self):
        from src.core.ws_log_handler import LogEntry
        entry = LogEntry(level="INFO", message="test")
        assert entry.level == "INFO"
        assert entry.message == "test"
        assert entry.context is None
        assert entry.timestamp is not None

    def test_creates_with_context(self):
        from src.core.ws_log_handler import LogEntry
        entry = LogEntry(level="ERROR", message="fail", context={"key": "val"})
        assert entry.context == {"key": "val"}
# #endregion test_log_entry


# #region test_websocket_log_handler [C:2] [TYPE Function]
# @BRIEF Test WebSocketLogHandler emit and get_recent_logs.
class TestWebSocketLogHandler:
    @pytest.fixture
    def handler(self):
        from src.core.ws_log_handler import WebSocketLogHandler
        return WebSocketLogHandler(capacity=100)

    def test_init(self, handler):
        assert handler.log_buffer.maxlen == 100
        assert len(handler.log_buffer) == 0

    def test_emit_stores_log_entry(self, handler):
        record = logging.LogRecord(
            name="test",
            level=logging.INFO,
            pathname="/test.py",
            lineno=10,
            msg="Test message",
            args=(),
            exc_info=None,
        )
        handler.emit(record)
        assert len(handler.log_buffer) == 1
        entry = handler.log_buffer[0]
        assert entry.level == "INFO"
        assert entry.message == "Test message"
        assert entry.context["name"] == "test"
        assert entry.context["lineno"] == 10

    def test_emit_error_level(self, handler):
        record = logging.LogRecord(
            name="test",
            level=logging.ERROR,
            pathname="/test.py",
            lineno=20,
            msg="Error occurred",
            args=(),
            exc_info=None,
        )
        handler.emit(record)
        assert handler.log_buffer[0].level == "ERROR"

    def test_get_recent_logs_returns_list(self, handler):
        record = logging.LogRecord("t", logging.INFO, "/t.py", 1, "msg", (), None)
        handler.emit(record)
        logs = handler.get_recent_logs()
        assert len(logs) == 1
        assert isinstance(logs, list)

    def test_get_recent_logs_returns_copy(self, handler):
        record = logging.LogRecord("t", logging.INFO, "/t.py", 1, "msg", (), None)
        handler.emit(record)
        logs = handler.get_recent_logs()
        assert len(logs) == 1
        # Verify it's a snapshot (list copy)
        handler.emit(record)
        assert len(logs) == 1  # Original list unchanged

    def test_capacity_limit(self):
        from src.core.ws_log_handler import WebSocketLogHandler
        small_handler = WebSocketLogHandler(capacity=3)
        for i in range(5):
            record = logging.LogRecord("t", logging.INFO, "/t.py", i, f"msg {i}", (), None)
            small_handler.emit(record)
        assert len(small_handler.log_buffer) == 3

    def test_emit_handles_exception_gracefully(self, handler):
        """If format raises, handleError is called. We mock format to raise."""
        bad_record = MagicMock()
        bad_record.levelname = "INFO"
        bad_record.name = "test"
        bad_record.pathname = "/test.py"
        bad_record.lineno = 1
        bad_record.funcName = "test"
        bad_record.process = 123
        bad_record.thread = 456

        # Make handler.format raise
        with patch.object(handler, "format", side_effect=Exception("Format failed")):
            with patch.object(handler, "handleError") as mock_handle:
                handler.emit(bad_record)
                mock_handle.assert_called_once_with(bad_record)

    def test_default_capacity(self):
        from src.core.ws_log_handler import WebSocketLogHandler
        h = WebSocketLogHandler()
        assert h.log_buffer.maxlen == 1000
# #endregion test_websocket_log_handler
# #endregion Test.WsLogHandler
