"""Tests for ToolUseCheck."""

from unittest.mock import MagicMock, patch

import pytest

from ai_qa.checks.tool_use import ToolUseCheck
from ai_qa.core.context import Context
from ai_qa.exceptions import ContextValidationError


def test_tool_use_check_name():
    """Test ToolUseCheck has correct name."""
    check = ToolUseCheck(expected_tool="search")
    assert check.name == "tool_use"


def test_tool_use_check_requires_llm():
    """Test ToolUseCheck requires_llm property."""
    check = ToolUseCheck(expected_tool="search")
    assert check.requires_llm is False


def test_tool_use_check_correct_tool_and_params():
    """Test correct tool with exact params."""
    check = ToolUseCheck(
        expected_tool="search",
        expected_params={"query": "python"},
        param_match="exact",
    )
    ctx = Context(
        output="result",
        tool_calls=[
            {"name": "search", "params": {"query": "python"}},
        ],
    )
    result = check.evaluate(ctx)
    assert result.score == 1.0
    assert result.passed


def test_tool_use_check_correct_tool_wrong_params():
    """Test correct tool with wrong params."""
    check = ToolUseCheck(
        expected_tool="search",
        expected_params={"query": "python"},
        param_match="exact",
        threshold=0.6,
    )
    ctx = Context(
        output="result",
        tool_calls=[
            {"name": "search", "params": {"query": "javascript"}},
        ],
    )
    result = check.evaluate(ctx)
    assert result.score == 0.5
    assert not result.passed


def test_tool_use_check_wrong_tool():
    """Test wrong tool called."""
    check = ToolUseCheck(expected_tool="search")
    ctx = Context(
        output="result",
        tool_calls=[
            {"name": "calculator", "params": {}},
        ],
    )
    result = check.evaluate(ctx)
    assert result.score == 0.0
    assert not result.passed


def test_tool_use_check_subset_match():
    """Test subset param matching."""
    check = ToolUseCheck(
        expected_tool="search",
        expected_params={"query": "python"},
        param_match="subset",
    )
    ctx = Context(
        output="result",
        tool_calls=[
            {
                "name": "search",
                "params": {"query": "python", "limit": 10},
            },
        ],
    )
    result = check.evaluate(ctx)
    assert result.score == 1.0
    assert result.passed


def test_tool_use_check_no_tool_calls():
    """Test error when tool_calls missing."""
    check = ToolUseCheck(expected_tool="search")
    ctx = Context(output="result")
    with pytest.raises(ContextValidationError):
        check.evaluate(ctx)


def test_tool_use_check_semantic_match():
    """Test semantic param matching with LLM."""
    check = ToolUseCheck(
        expected_tool="search",
        expected_params={"query": "python"},
        param_match="semantic",
    )
    ctx = Context(
        output="result",
        tool_calls=[
            {
                "name": "search",
                "params": {"search_term": "python programming"},
            },
        ],
    )

    with patch("ai_qa.checks.tool_use.get_provider") as mock_get_provider:
        mock_provider = MagicMock()
        mock_provider.judge.return_value = {
            "score": 0.8,
            "evidence": "Similar intent",
        }
        mock_get_provider.return_value = mock_provider

        result = check.evaluate(ctx)
        assert result.score == 0.8
        assert result.passed


def test_tool_use_check_invalid_param_match():
    """Test error on invalid param_match."""
    with pytest.raises(ValueError):
        ToolUseCheck(
            expected_tool="search",
            param_match="invalid",
        )


def test_tool_use_check_no_params_expected():
    """Test tool check without param expectations."""
    check = ToolUseCheck(expected_tool="search")
    ctx = Context(
        output="result",
        tool_calls=[
            {"name": "search", "params": {"anything": "here"}},
        ],
    )
    result = check.evaluate(ctx)
    assert result.score == 1.0
    assert result.passed
