"""Tests for the validate() entrypoint."""

from unittest.mock import patch

import pytest

from ai_qa import validate
from ai_qa.core.check import BaseCheck
from ai_qa.core.context import Context
from ai_qa.core.result import CheckResult, ValidationResult


class MockCheck(BaseCheck):
    """Mock check for testing."""

    requires_llm = False
    version = "1.0.0"

    def __init__(self, name: str = "mock", **kwargs):
        """Init mock check."""
        super().__init__(**kwargs)
        self.name = name

    def validate_context(self, ctx: Context) -> None:
        """No validation needed."""
        pass

    def evaluate(self, ctx: Context) -> CheckResult:
        """Return success."""
        return CheckResult(
            name=self.name,
            score=1.0,
            passed=True,
            threshold=self.threshold,
            evidence="Mock check passed",
            cost_usd=0.0,
            tokens_used={},
            check_version=self.version,
        )


def test_validate_basic():
    """Test basic validate() call with single check."""
    with patch("ai_qa.get_check") as mock_get_check:
        mock_get_check.return_value = MockCheck("length")
        result = validate(
            output="This is a test",
            checks=["length"],
        )

        assert isinstance(result, ValidationResult)
        assert len(result.checks) == 1
        assert result.checks[0].name == "length"


def test_validate_with_input():
    """Test validate() with input parameter."""
    with patch("ai_qa.get_check") as mock_get_check:
        mock_get_check.return_value = MockCheck("relevance")
        result = validate(
            output="Paris is the capital of France",
            input="What is the capital of France?",
            checks=["relevance"],
        )

        assert isinstance(result, ValidationResult)
        assert len(result.checks) == 1


def test_validate_multiple_checks():
    """Test validate() with multiple checks."""
    with patch("ai_qa.get_check") as mock_get_check:
        mock_get_check.side_effect = [
            MockCheck("json_format"),
            MockCheck("schema"),
        ]
        result = validate(
            output={"status": "ok"},
            checks=["json_format", "schema"],
        )

        assert isinstance(result, ValidationResult)
        assert len(result.checks) == 2


def test_validate_with_threshold():
    """Test validate() with threshold override."""
    with patch("ai_qa.get_check") as mock_get_check:
        mock_get_check.return_value = MockCheck("length")
        result = validate(
            output="test",
            checks=["length"],
            threshold=0.9,
        )

        assert isinstance(result, ValidationResult)
        # All checks should have the overridden threshold
        assert all(r.threshold == 0.9 for r in result.checks)


def test_validate_invalid_check():
    """Test validate() with invalid check name."""
    with patch("ai_qa.get_check") as mock_get_check:
        mock_get_check.side_effect = Exception("Check not found")
        with pytest.raises(Exception):
            validate(
                output="test",
                checks=["nonexistent_check"],
            )


def test_validate_with_context():
    """Test validate() with RAG context."""
    with patch("ai_qa.get_check") as mock_get_check:
        mock_get_check.return_value = MockCheck("groundedness")
        result = validate(
            output="Python is a programming language",
            context=["Python is a high-level programming language"],
            checks=["groundedness"],
        )

        assert isinstance(result, ValidationResult)
        assert len(result.checks) == 1


def test_validate_with_conversation():
    """Test validate() with conversation history."""
    with patch("ai_qa.get_check") as mock_get_check:
        mock_get_check.return_value = MockCheck("context_retention")
        result = validate(
            output="Yes, Paris is the capital",
            conversation=[
                {"role": "user", "content": "What is the capital of France?"},
                {"role": "assistant", "content": "Paris"},
            ],
            checks=["context_retention"],
        )

        assert isinstance(result, ValidationResult)
        assert len(result.checks) == 1


def test_validate_summary():
    """Test ValidationResult summary."""
    with patch("ai_qa.get_check") as mock_get_check:
        mock_get_check.return_value = MockCheck("length")
        result = validate(
            output="test output",
            checks=["length"],
        )

        summary = result.summary
        assert "total" in summary or "passed" in summary


def test_validate_with_metadata():
    """Test validate() with metadata."""
    with patch("ai_qa.get_check") as mock_get_check:
        mock_get_check.return_value = MockCheck("length")
        result = validate(
            output="test",
            checks=["length"],
            metadata={"model": "gpt-4", "temperature": 0.7},
        )

        assert isinstance(result, ValidationResult)


def test_validate_with_dict_output():
    """Test validate() with dict output."""
    with patch("ai_qa.get_check") as mock_get_check:
        mock_get_check.return_value = MockCheck("json_format")
        result = validate(
            output={"name": "John", "age": 30},
            checks=["json_format"],
        )

        assert isinstance(result, ValidationResult)


def test_validate_with_list_output():
    """Test validate() with list output."""
    with patch("ai_qa.get_check") as mock_get_check:
        mock_get_check.return_value = MockCheck("json_format")
        result = validate(
            output=[1, 2, 3, 4, 5],
            checks=["json_format"],
        )

        assert isinstance(result, ValidationResult)


def test_validate_docstring_exists():
    """Test that validate() has a docstring."""
    assert validate.__doc__ is not None
    assert len(validate.__doc__) > 0
    assert "validate" in validate.__doc__.lower()
