"""
Unit tests for the tool registry.

Tests:
  - BUILTIN_TOOLS contains all 4 expected tools
  - get_tools_for_agent filters correctly based on agent.tool_assignments
  - to_litellm_format produces valid OpenAI function-calling schema
  - ToolDefinition model validation
"""

from __future__ import annotations

import uuid
from unittest.mock import MagicMock


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------


def make_agent(tool_list: list[str]) -> MagicMock:
    """Create a mock Agent with tool_assignments set."""
    agent = MagicMock()
    agent.id = uuid.uuid4()
    agent.tool_assignments = tool_list
    return agent


# ---------------------------------------------------------------------------
# Tests
# ---------------------------------------------------------------------------


class TestBuiltinTools:
    """BUILTIN_TOOLS registry contains the correct tool definitions."""

    def test_all_four_tools_present(self):
        from orchestrator.tools.registry import BUILTIN_TOOLS

        assert "web_search" in BUILTIN_TOOLS
        assert "kb_search" in BUILTIN_TOOLS
        assert "http_request" in BUILTIN_TOOLS
        assert "calendar_lookup" in BUILTIN_TOOLS

    def test_tool_definitions_have_required_fields(self):
        from orchestrator.tools.registry import BUILTIN_TOOLS

        for name, tool in BUILTIN_TOOLS.items():
            assert tool.name == name, f"Tool name mismatch for {name}"
            assert tool.description, f"Tool {name} missing description"
            assert isinstance(tool.parameters, dict), f"Tool {name} parameters must be dict"
            assert "type" in tool.parameters, f"Tool {name} parameters missing 'type' key"
            assert tool.handler is not None, f"Tool {name} has no handler"

    def test_http_request_requires_confirmation(self):
        from orchestrator.tools.registry import BUILTIN_TOOLS

        assert BUILTIN_TOOLS["http_request"].requires_confirmation is True

    def test_web_search_no_confirmation(self):
        from orchestrator.tools.registry import BUILTIN_TOOLS

        assert BUILTIN_TOOLS["web_search"].requires_confirmation is False

    def test_kb_search_no_confirmation(self):
        from orchestrator.tools.registry import BUILTIN_TOOLS

        assert BUILTIN_TOOLS["kb_search"].requires_confirmation is False

    def test_calendar_lookup_no_confirmation(self):
        from orchestrator.tools.registry import BUILTIN_TOOLS

        assert BUILTIN_TOOLS["calendar_lookup"].requires_confirmation is False


class TestGetToolsForAgent:
    """get_tools_for_agent filters BUILTIN_TOOLS by agent's tool_assignments list."""

    def test_filters_to_assigned_tools(self):
        from orchestrator.tools.registry import get_tools_for_agent

        agent = make_agent(["web_search", "kb_search"])
        result = get_tools_for_agent(agent)

        assert set(result.keys()) == {"web_search", "kb_search"}

    def test_empty_tool_list_returns_empty(self):
        from orchestrator.tools.registry import get_tools_for_agent

        agent = make_agent([])
        result = get_tools_for_agent(agent)

        assert result == {}

    def test_unknown_tools_ignored_silently(self):
        """Tools in agent.tool_assignments that don't exist in BUILTIN_TOOLS are skipped."""
        from orchestrator.tools.registry import get_tools_for_agent

        agent = make_agent(["web_search", "nonexistent_tool"])
        result = get_tools_for_agent(agent)

        assert "web_search" in result
        assert "nonexistent_tool" not in result

    def test_all_tools_accessible(self):
        from orchestrator.tools.registry import BUILTIN_TOOLS, get_tools_for_agent

        agent = make_agent(list(BUILTIN_TOOLS.keys()))
        result = get_tools_for_agent(agent)

        assert set(result.keys()) == set(BUILTIN_TOOLS.keys())


class TestToLitellmFormat:
    """to_litellm_format converts tool definitions to OpenAI function-calling schema."""

    def test_returns_list_of_dicts(self):
        from orchestrator.tools.registry import BUILTIN_TOOLS, to_litellm_format

        result = to_litellm_format({"web_search": BUILTIN_TOOLS["web_search"]})

        assert isinstance(result, list)
        assert len(result) == 1

    def test_openai_schema_structure(self):
        """Each entry must have type='function' and a nested function object."""
        from orchestrator.tools.registry import BUILTIN_TOOLS, to_litellm_format

        result = to_litellm_format({"web_search": BUILTIN_TOOLS["web_search"]})
        entry = result[0]

        assert entry["type"] == "function"
        assert "function" in entry
        func = entry["function"]
        assert func["name"] == "web_search"
        assert "description" in func
        assert "parameters" in func

    def test_empty_tools_returns_empty_list(self):
        from orchestrator.tools.registry import to_litellm_format

        assert to_litellm_format({}) == []

    def test_multiple_tools_converted(self):
        from orchestrator.tools.registry import BUILTIN_TOOLS, to_litellm_format

        result = to_litellm_format(BUILTIN_TOOLS)
        assert len(result) == 4
