"""
Tests for advanced_search_system/tools/base_tool.py

Tests cover:
- TYPE_MAP constant
- BaseTool class initialization and methods
- Parameter validation
"""

from unittest.mock import patch


class TestTypeMap:
    """Tests for TYPE_MAP constant."""

    def test_type_map_exists(self):
        """Test that TYPE_MAP is defined."""
        from local_deep_research.advanced_search_system.tools.base_tool import (
            TYPE_MAP,
        )

        assert TYPE_MAP is not None
        assert isinstance(TYPE_MAP, dict)

    def test_contains_common_types(self):
        """Test that common types are mapped."""
        from local_deep_research.advanced_search_system.tools.base_tool import (
            TYPE_MAP,
        )

        assert TYPE_MAP["str"] is str
        assert TYPE_MAP["int"] is int
        assert TYPE_MAP["float"] is float
        assert TYPE_MAP["bool"] is bool
        assert TYPE_MAP["list"] is list
        assert TYPE_MAP["dict"] is dict

    def test_contains_collection_types(self):
        """Test that collection types are mapped."""
        from local_deep_research.advanced_search_system.tools.base_tool import (
            TYPE_MAP,
        )

        assert TYPE_MAP["tuple"] is tuple
        assert TYPE_MAP["set"] is set


class ConcreteTool:
    """Concrete implementation of BaseTool for testing."""

    def __init__(self, name="test_tool", description="A test tool"):
        # We can't subclass ABC directly in tests, so we'll access methods
        self.name = name
        self.description = description
        self.parameters = {}

    def execute(self, **kwargs):
        return f"Executed with {kwargs}"


class TestBaseTool:
    """Tests for BaseTool class."""

    def test_init_sets_name_and_description(self):
        """Test that __init__ sets name and description."""
        from local_deep_research.advanced_search_system.tools.base_tool import (
            BaseTool,
        )

        # Create a minimal concrete subclass
        class TestTool(BaseTool):
            def execute(self, **kwargs):
                return "result"

        tool = TestTool(name="my_tool", description="Does something")

        assert tool.name == "my_tool"
        assert tool.description == "Does something"
        assert tool.parameters == {}

    def test_get_schema_returns_correct_format(self):
        """Test that get_schema returns proper format."""
        from local_deep_research.advanced_search_system.tools.base_tool import (
            BaseTool,
        )

        class TestTool(BaseTool):
            def execute(self, **kwargs):
                return "result"

        tool = TestTool(name="my_tool", description="Does something")
        tool.parameters = {
            "query": {"type": "str", "required": True},
        }

        schema = tool.get_schema()

        assert schema["name"] == "my_tool"
        assert schema["description"] == "Does something"
        assert "query" in schema["parameters"]

    def test_validate_parameters_returns_true_for_valid(self):
        """Test validation returns True for valid parameters."""
        from local_deep_research.advanced_search_system.tools.base_tool import (
            BaseTool,
        )

        class TestTool(BaseTool):
            def execute(self, **kwargs):
                return "result"

        tool = TestTool(name="test", description="test")
        tool.parameters = {
            "query": {"type": "str", "required": True},
        }

        result = tool.validate_parameters(query="hello")

        assert result is True

    def test_validate_parameters_returns_false_for_missing_required(self):
        """Test validation returns False for missing required parameter."""
        from local_deep_research.advanced_search_system.tools.base_tool import (
            BaseTool,
        )

        class TestTool(BaseTool):
            def execute(self, **kwargs):
                return "result"

        tool = TestTool(name="test", description="test")
        tool.parameters = {
            "query": {"type": "str", "required": True},
        }

        result = tool.validate_parameters()  # Missing 'query'

        assert result is False

    def test_validate_parameters_allows_optional_missing(self):
        """Test validation allows missing optional parameters."""
        from local_deep_research.advanced_search_system.tools.base_tool import (
            BaseTool,
        )

        class TestTool(BaseTool):
            def execute(self, **kwargs):
                return "result"

        tool = TestTool(name="test", description="test")
        tool.parameters = {
            "query": {"type": "str", "required": False},
        }

        result = tool.validate_parameters()  # Missing optional param

        assert result is True

    def test_validate_parameters_returns_false_for_wrong_type(self):
        """Test validation returns False for wrong parameter type."""
        from local_deep_research.advanced_search_system.tools.base_tool import (
            BaseTool,
        )

        class TestTool(BaseTool):
            def execute(self, **kwargs):
                return "result"

        tool = TestTool(name="test", description="test")
        tool.parameters = {
            "count": {"type": "int", "required": True},
        }

        result = tool.validate_parameters(count="not an int")

        assert result is False

    def test_validate_parameters_checks_enum_values(self):
        """Test validation checks enum values."""
        from local_deep_research.advanced_search_system.tools.base_tool import (
            BaseTool,
        )

        class TestTool(BaseTool):
            def execute(self, **kwargs):
                return "result"

        tool = TestTool(name="test", description="test")
        tool.parameters = {
            "mode": {"type": "str", "enum": ["fast", "slow"]},
        }

        # Valid enum value
        assert tool.validate_parameters(mode="fast") is True

        # Invalid enum value
        assert tool.validate_parameters(mode="medium") is False

    def test_validate_parameters_ignores_unknown_types(self):
        """Test validation ignores unknown type strings."""
        from local_deep_research.advanced_search_system.tools.base_tool import (
            BaseTool,
        )

        class TestTool(BaseTool):
            def execute(self, **kwargs):
                return "result"

        tool = TestTool(name="test", description="test")
        tool.parameters = {
            "custom": {"type": "unknown_type"},  # Unknown type
        }

        # Should not fail validation for unknown types
        result = tool.validate_parameters(custom="anything")

        assert result is True

    def test_log_execution_logs_info(self):
        """Test that _log_execution logs properly."""
        from local_deep_research.advanced_search_system.tools.base_tool import (
            BaseTool,
        )

        class TestTool(BaseTool):
            def execute(self, **kwargs):
                return "result"

        tool = TestTool(name="test_tool", description="test")

        with patch(
            "local_deep_research.advanced_search_system.tools.base_tool.logger"
        ) as mock_logger:
            tool._log_execution(param1="value1", param2="value2")

            mock_logger.info.assert_called()
            # Should mention tool name and parameter count
            call_args = mock_logger.info.call_args[0][0]
            assert "test_tool" in call_args
            assert "2" in call_args

    def test_log_result_logs_info(self):
        """Test that _log_result logs properly."""
        from local_deep_research.advanced_search_system.tools.base_tool import (
            BaseTool,
        )

        class TestTool(BaseTool):
            def execute(self, **kwargs):
                return "result"

        tool = TestTool(name="test_tool", description="test")

        with patch(
            "local_deep_research.advanced_search_system.tools.base_tool.logger"
        ) as mock_logger:
            tool._log_result("my_result")

            mock_logger.info.assert_called()
            call_args = mock_logger.info.call_args[0][0]
            assert "test_tool" in call_args
            assert "my_result" in call_args
