"""Tests for TrajectoryCheck."""

import pytest

from ai_qa.checks.trajectory import TrajectoryCheck
from ai_qa.core.context import Context
from ai_qa.exceptions import ContextValidationError


def test_trajectory_check_name():
    """Test TrajectoryCheck has correct name."""
    check = TrajectoryCheck(expected_trajectory=[{"tool": "search"}])
    assert check.name == "trajectory"


def test_trajectory_check_requires_llm():
    """Test TrajectoryCheck requires_llm property."""
    check = TrajectoryCheck(expected_trajectory=[{"tool": "search"}])
    assert check.requires_llm is False


def test_trajectory_strict_match():
    """Test strict trajectory matching."""
    check = TrajectoryCheck(
        expected_trajectory=[
            {"tool": "search"},
            {"tool": "calculator"},
        ],
        match="strict",
    )
    ctx = Context(output="result",
        tool_calls=[
            {"name": "search", "params": {}},
            {"name": "calculator", "params": {}},
        ],
    )
    result = check.evaluate(ctx)
    assert result.score == 1.0
    assert result.passed


def test_trajectory_flexible_match():
    """Test flexible trajectory (subsequence)."""
    check = TrajectoryCheck(
        expected_trajectory=[
            {"tool": "search"},
            {"tool": "calculator"},
        ],
        match="flexible",
    )
    ctx = Context(output="result",
        tool_calls=[
            {"name": "validate"},
            {"name": "search", "params": {}},
            {"name": "analyze"},
            {"name": "calculator", "params": {}},
        ],
    )
    result = check.evaluate(ctx)
    assert result.score == 1.0
    assert result.passed


def test_trajectory_max_steps_exceeded():
    """Test max_steps constraint."""
    check = TrajectoryCheck(
        expected_trajectory=[{"tool": "search"}],
        max_steps=2,
    )
    ctx = Context(output="result",
        tool_calls=[
            {"name": "search", "params": {}},
            {"name": "search", "params": {}},
            {"name": "search", "params": {}},
        ],
    )
    result = check.evaluate(ctx)
    assert result.score == 0.0
    assert not result.passed


def test_trajectory_disallowed_tool():
    """Test disallowed_tools constraint."""
    check = TrajectoryCheck(
        expected_trajectory=[{"tool": "search"}],
        disallowed_tools=["delete"],
    )
    ctx = Context(output="result",
        tool_calls=[
            {"name": "search", "params": {}},
            {"name": "delete", "params": {}},
        ],
    )
    result = check.evaluate(ctx)
    assert result.score == 0.0
    assert not result.passed


def test_trajectory_no_tool_calls():
    """Test error when tool_calls missing."""
    check = TrajectoryCheck(expected_trajectory=[{"tool": "search"}])
    ctx = Context(output="result")
    with pytest.raises(ContextValidationError):
        check.evaluate(ctx)


def test_trajectory_mismatch():
    """Test trajectory mismatch."""
    check = TrajectoryCheck(
        expected_trajectory=[
            {"tool": "search"},
            {"tool": "calculator"},
        ],
        match="strict",
        threshold=0.6,
    )
    ctx = Context(output="result",
        tool_calls=[
            {"name": "calculator", "params": {}},
            {"name": "search", "params": {}},
        ],
    )
    result = check.evaluate(ctx)
    assert result.score == 0.5
    assert not result.passed


def test_trajectory_invalid_match_mode():
    """Test error on invalid match mode."""
    with pytest.raises(ValueError):
        TrajectoryCheck(
            expected_trajectory=[{"tool": "search"}],
            match="invalid",
        )
