"""tests/test_scoring_function_call_guard.py — Unit tests for llm_guard.scoring.function_call_guard."""
import pytest
from unittest.mock import MagicMock, patch

pytestmark = pytest.mark.unit

OPENAI_MESSAGES = [
    {"role": "user", "content": "What is the capital of France?"},
    {"role": "assistant", "content": "I'll search for that.",
     "tool_calls": [{"function": {"name": "search", "arguments": '{"query": "capital France"}'}}]},
    {"role": "tool", "content": "Paris is the capital of France."},
    {"role": "assistant", "content": "Paris is the capital of France."},
]

CLAUDE_MESSAGES = [
    {"role": "user", "content": "What is capital of France?"},
    {"role": "assistant", "content": [
        {"type": "text", "text": "Let me search."},
        {"type": "tool_use", "name": "search", "input": {"query": "capital France"}},
    ]},
    {"role": "user", "content": [
        {"type": "tool_result", "content": "Paris is the capital."},
    ]},
    {"role": "assistant", "content": "Paris."},
]


class TestImport:
    def test_import(self):
        from llm_guard.scoring.function_call_guard import FunctionCallGuard
        assert FunctionCallGuard is not None


class TestInstantiation:
    def test_default_construction(self):
        from llm_guard.scoring.function_call_guard import FunctionCallGuard
        guard = FunctionCallGuard()
        assert guard is not None
        assert guard._use_judge is False

    def test_custom_params(self):
        from llm_guard.scoring.function_call_guard import FunctionCallGuard
        guard = FunctionCallGuard(use_judge=False)
        assert not guard._use_judge


class TestParseToolCalls:
    def test_parse_openai_messages(self):
        from llm_guard.scoring.function_call_guard import FunctionCallGuard
        steps = FunctionCallGuard._parse_tool_calls(OPENAI_MESSAGES)
        assert len(steps) >= 1
        assert "action_type" in steps[0]
        assert "observation" in steps[0]

    def test_parse_claude_messages(self):
        from llm_guard.scoring.function_call_guard import FunctionCallGuard
        steps = FunctionCallGuard._parse_tool_calls(CLAUDE_MESSAGES)
        assert len(steps) >= 1

    def test_parse_empty_messages(self):
        from llm_guard.scoring.function_call_guard import FunctionCallGuard
        steps = FunctionCallGuard._parse_tool_calls([])
        assert steps == []

    def test_parse_no_tool_calls(self):
        from llm_guard.scoring.function_call_guard import FunctionCallGuard
        msgs = [
            {"role": "user", "content": "Hello"},
            {"role": "assistant", "content": "Hi there!"},
        ]
        steps = FunctionCallGuard._parse_tool_calls(msgs)
        assert steps == []


class TestScore:
    def test_score_openai_messages_returns_result(self):
        from llm_guard.scoring.function_call_guard import FunctionCallGuard
        guard = FunctionCallGuard()
        result = guard.score(OPENAI_MESSAGES, question="What is the capital of France?")
        assert hasattr(result, "risk_score")
        assert 0.0 <= result.risk_score <= 1.0

    def test_score_claude_messages_returns_result(self):
        from llm_guard.scoring.function_call_guard import FunctionCallGuard
        guard = FunctionCallGuard()
        result = guard.score(CLAUDE_MESSAGES, question="Capital of France?")
        assert hasattr(result, "risk_score")

    def test_score_empty_messages_returns_neutral(self):
        from llm_guard.scoring.function_call_guard import FunctionCallGuard
        guard = FunctionCallGuard()
        result = guard.score([], question="Q?")
        assert result.risk_score == 0.5
        assert result.step_count == 0

    def test_score_confidence_tier_valid(self):
        from llm_guard.scoring.function_call_guard import FunctionCallGuard
        guard = FunctionCallGuard()
        result = guard.score(OPENAI_MESSAGES, question="Capital of France?")
        assert result.confidence_tier in ("HIGH", "MEDIUM", "LOW")


class TestFit:
    def test_fit_too_few_raises(self):
        from llm_guard.scoring.function_call_guard import FunctionCallGuard
        guard = FunctionCallGuard()
        with pytest.raises(ValueError, match="20"):
            guard.fit([{"messages": OPENAI_MESSAGES, "label": 0}] * 5)
