"""Tests for check functions."""

from finagent_evals.checks import (
    check_tools,
    check_tools_any,
    check_tools_plus_any_of,
    check_must_contain,
    check_contains_any,
    check_must_not_contain,
    check_sources,
    check_authoritative_sources,
    check_ground_truth,
    check_structural,
    run_golden_checks,
)


class TestToolChecks:
    def test_tools_pass(self):
        ok, err = check_tools(["get_portfolio_snapshot"], ["get_portfolio_snapshot"])
        assert ok
        assert err == ""

    def test_tools_missing(self):
        ok, err = check_tools(["get_portfolio_snapshot"], [])
        assert not ok
        assert "Missing" in err

    def test_tools_exact_extra(self):
        ok, err = check_tools(["get_market_data"], ["get_market_data", "extra"], exact=True)
        assert not ok
        assert "Extra" in err

    def test_tools_no_tools_expected_but_called(self):
        ok, err = check_tools([], ["get_market_data"])
        assert not ok

    def test_tools_any_pass(self):
        ok, _ = check_tools_any(["a", "b"], ["b"])
        assert ok

    def test_tools_any_no_tools_ok(self):
        ok, _ = check_tools_any(["a"], [])
        assert ok

    def test_tools_any_fail(self):
        ok, _ = check_tools_any(["a", "b"], ["c"])
        assert not ok

    def test_tools_plus_any_of_pass(self):
        ok, _ = check_tools_plus_any_of(["a"], ["b", "c"], ["a", "b"])
        assert ok

    def test_tools_plus_any_of_fail_missing_required(self):
        ok, _ = check_tools_plus_any_of(["a"], ["b"], ["b"])
        assert not ok

    def test_tools_plus_any_of_fail_missing_optional(self):
        ok, _ = check_tools_plus_any_of(["a"], ["b", "c"], ["a"])
        assert not ok


class TestContentChecks:
    def test_must_contain_pass(self):
        ok, _ = check_must_contain(["portfolio", "AAPL"], "Your portfolio has AAPL")
        assert ok

    def test_must_contain_fail(self):
        ok, _ = check_must_contain(["TSLA"], "Your portfolio has AAPL")
        assert not ok

    def test_contains_any_pass(self):
        ok, _ = check_contains_any(["a", "b"], "text with b")
        assert ok

    def test_contains_any_fail(self):
        ok, _ = check_contains_any(["alpha", "beta"], "gamma delta")
        assert not ok

    def test_must_not_contain_pass(self):
        ok, _ = check_must_not_contain(["error"], "Everything is fine")
        assert ok

    def test_must_not_contain_fail(self):
        ok, _ = check_must_not_contain(["error"], "There was an error")
        assert not ok

    def test_must_not_contain_empty(self):
        ok, _ = check_must_not_contain([], "")
        assert not ok  # empty response

    def test_must_not_contain_give_up(self):
        ok, err = check_must_not_contain([], "I couldn't find that")
        assert not ok
        assert "Give-up" in err


class TestSourceChecks:
    def test_sources_pass(self):
        ok, _ = check_sources(["wash sale"], "There is a wash sale risk")
        assert ok

    def test_sources_fail(self):
        ok, _ = check_sources(["wash sale"], "Everything looks clean")
        assert not ok

    def test_authoritative_pass(self):
        sources = [{"label": "IRC \u00a71091 \u2014 Wash Sales"}]
        ok, _ = check_authoritative_sources(["irc_1091"], sources)
        assert ok

    def test_authoritative_fail(self):
        ok, _ = check_authoritative_sources(["irc_1091"], [])
        assert not ok

    def test_authoritative_empty_expected(self):
        ok, _ = check_authoritative_sources([], [])
        assert ok


class TestGroundTruth:
    def test_pass(self):
        ok, _ = check_ground_truth(["187", "AAPL"], "AAPL is at $187.50")
        assert ok

    def test_fail(self):
        ok, _ = check_ground_truth(["999"], "Price is 187")
        assert not ok

    def test_empty(self):
        ok, _ = check_ground_truth([], "anything")
        assert ok


class TestStructural:
    def test_pass(self):
        ok, _ = check_structural(2, 3, 5.0, 10.0)
        assert ok

    def test_steps_exceeded(self):
        ok, _ = check_structural(5, 3, 5.0, 10.0)
        assert not ok

    def test_latency_exceeded(self):
        ok, _ = check_structural(2, 3, 15.0, 10.0)
        assert not ok

    def test_none_values(self):
        ok, _ = check_structural(None, None, None, None)
        assert ok


class TestRunGoldenChecks:
    def test_passing_case(self):
        case = {
            "expected_tools": ["get_portfolio_snapshot"],
            "expected_output_contains": ["portfolio"],
            "should_not_contain": ["error"],
            "max_react_steps": 3,
            "max_latency_seconds": 10,
        }
        result = {
            "response": {"summary": "Your portfolio has AAPL and GOOG"},
            "tools_called": ["get_portfolio_snapshot"],
            "tool_errors": [],
            "react_step": 1,
            "latency_seconds": 2.0,
        }
        checks = run_golden_checks(case, result)
        assert checks["passed"]

    def test_failing_case(self):
        case = {
            "expected_tools": ["get_market_data"],
            "expected_output_contains": ["AAPL"],
            "should_not_contain": [],
        }
        result = {
            "response": {"summary": "Here is GOOG data"},
            "tools_called": [],
            "tool_errors": [],
        }
        checks = run_golden_checks(case, result)
        assert not checks["passed"]
