"""Tests for the tool registry."""

import pytest

from fliiq.runtime.agent.tools import ToolRegistry


def test_register_and_get_definitions():
    """Register a tool and verify its definition appears."""
    reg = ToolRegistry()
    reg.register("greet", "Say hello", {"type": "object", "properties": {}}, lambda p: "hi")

    defs = reg.get_tool_definitions()
    assert len(defs) == 1
    assert defs[0]["name"] == "greet"
    assert defs[0]["description"] == "Say hello"


async def test_execute_sync_handler():
    """Execute a tool with a sync handler."""
    reg = ToolRegistry()
    reg.register("add", "Add numbers", {"type": "object"}, lambda p: str(p["a"] + p["b"]))

    result = await reg.execute("add", {"a": 1, "b": 2})
    assert result == "3"


async def test_execute_async_handler():
    """Execute a tool with an async handler."""
    reg = ToolRegistry()

    async def _async_handler(params):
        return f"hello {params['name']}"

    reg.register("greet", "Greet", {"type": "object"}, _async_handler)

    result = await reg.execute("greet", {"name": "world"})
    assert result == "hello world"


async def test_execute_unknown_tool():
    """Executing an unknown tool returns error string."""
    reg = ToolRegistry()
    result = await reg.execute("nonexistent", {})
    assert "unknown tool" in result.lower()


async def test_execute_handler_error():
    """Handler errors are caught and returned as error strings."""
    reg = ToolRegistry()
    reg.register("boom", "Explodes", {"type": "object"}, lambda p: 1 / 0)

    result = await reg.execute("boom", {})
    assert "Error executing boom" in result


def test_register_builtins():
    """register_builtins() adds todo and ask_user tools."""
    reg = ToolRegistry()
    reg.register_builtins()

    defs = reg.get_tool_definitions()
    names = [d["name"] for d in defs]
    assert "todo" in names
    assert "ask_user" in names


async def test_builtin_todo_works():
    """Built-in todo tool can add and list tasks."""
    reg = ToolRegistry()
    reg.register_builtins()

    result = await reg.execute("todo", {"action": "add", "task": "Write tests"})
    assert "Write tests" in result

    result = await reg.execute("todo", {"action": "list"})
    assert "Write tests" in result


def test_register_skill():
    """register_skill() bridges a SkillBase to a tool definition."""
    from unittest.mock import MagicMock

    skill = MagicMock()
    skill.name = "web_fetch"
    skill.schema.return_value = {
        "name": "web_fetch",
        "description": "Fetch a URL",
        "parameters": {"type": "object", "properties": {"url": {"type": "string"}}},
        "output_schema": {},
    }

    reg = ToolRegistry()
    reg.register_skill(skill)

    defs = reg.get_tool_definitions()
    assert len(defs) == 1
    assert defs[0]["name"] == "web_fetch"
    assert defs[0]["description"] == "Fetch a URL"


async def test_ask_user_with_handler():
    """ask_user tool calls the provided handler callback in supervised mode."""
    reg = ToolRegistry()
    reg.register_builtins(ask_user_handler=lambda q: f"User says: {q}", mode="supervised")

    result = await reg.execute("ask_user", {"question": "Which database?"})
    assert "User says: Which database?" in result


async def test_ask_user_without_handler():
    """ask_user without handler returns unavailable message."""
    reg = ToolRegistry()
    reg.register_builtins(mode="supervised")

    result = await reg.execute("ask_user", {"question": "Which database?"})
    assert "not available" in result.lower()


async def test_ask_user_autonomous_non_critical():
    """ask_user in autonomous mode with critical=false returns best judgment message."""
    reg = ToolRegistry()
    reg._mode = "autonomous"
    reg.register_builtins(ask_user_handler=lambda q: f"User says: {q}")

    result = await reg.execute("ask_user", {"question": "Which database?", "critical": False})
    assert "best judgment" in result.lower()


async def test_ask_user_autonomous_critical():
    """ask_user in autonomous mode with critical=true still calls the handler."""
    reg = ToolRegistry()
    reg._mode = "autonomous"
    reg.register_builtins(ask_user_handler=lambda q: f"User says: {q}")

    result = await reg.execute("ask_user", {"question": "Which database?", "critical": True})
    assert "User says: Which database?" in result


def test_multiple_tools():
    """Multiple tools can be registered."""
    reg = ToolRegistry()
    reg.register("a", "Tool A", {"type": "object"}, lambda p: "a")
    reg.register("b", "Tool B", {"type": "object"}, lambda p: "b")
    reg.register_builtins()

    defs = reg.get_tool_definitions()
    assert len(defs) == 7  # 2 custom + todo + ask_user + ask_user_choice + plan_complete + install_skill
