"""Test smart field selection for search_records."""

from unittest.mock import Mock

import pytest

from mcp_server_odoo.tools import OdooToolHandler


class TestSearchSmartDefaults:
    """Test smart field selection for search_records when fields not specified."""

    @pytest.fixture
    def tool_handler(self):
        """Create a tool handler with mocked dependencies."""
        app = Mock()
        connection = Mock()
        access_controller = Mock()
        config = Mock()
        config.default_limit = 10
        config.max_limit = 100
        config.max_smart_fields = 15

        return OdooToolHandler(app, connection, access_controller, config)

    @pytest.mark.asyncio
    async def test_search_with_no_fields_uses_smart_defaults(self, tool_handler):
        """Test that search_records uses smart defaults when fields is None."""
        # Setup mocks
        tool_handler.connection.is_authenticated = True
        tool_handler.connection.search_count.return_value = 2
        tool_handler.connection.search.return_value = [1, 2]

        # Mock fields_get to return field metadata
        tool_handler.connection.fields_get.return_value = {
            "id": {"type": "integer", "required": True},
            "name": {"type": "char", "required": True, "searchable": True},
            "email": {"type": "char", "searchable": True},
            "phone": {"type": "char", "searchable": True},
            "create_date": {"type": "datetime"},
            "message_ids": {"type": "one2many"},  # Should be excluded
            "_barcode_scan": {"type": "char"},  # Should be excluded (technical)
            "image_1920": {"type": "binary"},  # Should be excluded (binary)
        }

        # Mock read to return records with only smart default fields
        tool_handler.connection.read.return_value = [
            {
                "id": 1,
                "name": "Test 1",
                "email": "test1@example.com",
                "create_date": "20250607T10:00:00",
            },
            {
                "id": 2,
                "name": "Test 2",
                "email": "test2@example.com",
                "create_date": "20250607T11:00:00",
            },
        ]

        # Call the handler with fields=None
        handler = tool_handler._handle_search_tool
        await handler("res.partner", [], None, 10, 0, None)

        # Verify smart defaults were used
        # The read call should have been made with specific fields, not None
        tool_handler.connection.read.assert_called_once()
        call_args = tool_handler.connection.read.call_args
        fields_arg = call_args[0][2]  # Third positional argument

        # Should have selected smart default fields
        assert fields_arg is not None
        assert isinstance(fields_arg, list)
        assert "id" in fields_arg
        assert "name" in fields_arg
        assert "email" in fields_arg

        # Should exclude technical/binary/relation fields
        assert "message_ids" not in fields_arg
        assert "_barcode_scan" not in fields_arg
        assert "image_1920" not in fields_arg

    @pytest.mark.asyncio
    async def test_search_with_specific_fields(self, tool_handler):
        """Test that search_records uses specified fields when provided."""
        # Setup mocks
        tool_handler.connection.is_authenticated = True
        tool_handler.connection.search_count.return_value = 1
        tool_handler.connection.search.return_value = [1]
        tool_handler.connection.read.return_value = [
            {"id": 1, "name": "Test", "phone": "+1234567890"}
        ]

        # Call with specific fields
        handler = tool_handler._handle_search_tool
        fields = ["name", "phone"]
        await handler("res.partner", [], fields, 10, 0, None)

        # Verify specified fields were used
        tool_handler.connection.read.assert_called_once_with("res.partner", [1], fields)

    @pytest.mark.asyncio
    async def test_search_with_all_fields(self, tool_handler):
        """Test that search_records can fetch all fields when explicitly requested."""
        # Setup mocks
        tool_handler.connection.is_authenticated = True
        tool_handler.connection.search_count.return_value = 1
        tool_handler.connection.search.return_value = [1]
        tool_handler.connection.read.return_value = [
            {
                "id": 1,
                "name": "Test",
                "email": "test@example.com",
                "phone": "+1234567890",
                "create_date": "20250607T10:00:00",
                "message_ids": [1, 2, 3],
                "_barcode_scan": "12345",
                "image_1920": "base64data...",
                # ... many more fields
            }
        ]

        # Call with __all__ to get all fields
        handler = tool_handler._handle_search_tool
        await handler("res.partner", [], ["__all__"], 10, 0, None)

        # Verify None was passed to read (which means all fields)
        tool_handler.connection.read.assert_called_once_with("res.partner", [1], None)

    @pytest.mark.asyncio
    async def test_search_smart_defaults_with_datetime_formatting(self, tool_handler):
        """Test that datetime fields are formatted even with smart defaults."""
        # Setup mocks
        tool_handler.connection.is_authenticated = True
        tool_handler.connection.search_count.return_value = 1
        tool_handler.connection.search.return_value = [1]

        # Mock fields_get
        tool_handler.connection.fields_get.return_value = {
            "id": {"type": "integer", "required": True},
            "name": {"type": "char", "required": True},
            "create_date": {"type": "datetime"},
        }

        # Mock read with datetime that needs formatting
        tool_handler.connection.read.return_value = [
            {"id": 1, "name": "Test", "create_date": "20250607T10:00:00"}
        ]

        # Call the handler
        handler = tool_handler._handle_search_tool
        result = await handler("res.partner", [], None, 10, 0, None)

        # Verify datetime was formatted
        assert result["records"][0]["create_date"] == "2025-06-07T10:00:00+00:00"
