"""Tests for multi-valued field evaluation."""

from therismos.expr import F, unwind_data


class TestEqMultiValuedEval:
    """Test Eq evaluation with list-valued fields."""

    def test_eq_list_any_match(self) -> None:
        """Test that Eq returns True if ANY value matches."""
        expr = F("tags") == "python"
        assert expr.evaluate(unwind_data({"tags": ["python", "java", "rust"]})) is True

    def test_eq_list_no_match(self) -> None:
        """Test that Eq returns False if no values match."""
        expr = F("tags") == "python"
        assert expr.evaluate(unwind_data({"tags": ["java", "rust", "go"]})) is False

    def test_eq_single_value_backward_compat(self) -> None:
        """Test that Eq works with single values (backward compatibility)."""
        expr = F("name") == "alice"
        assert expr.evaluate(unwind_data({"name": "alice"})) is True
        assert expr.evaluate(unwind_data({"name": "bob"})) is False


class TestNeMultiValuedEval:
    """Test Ne evaluation with list-valued fields."""

    def test_ne_list_none_match(self) -> None:
        """Test that Ne returns True if NONE of the values match."""
        expr = F("tags") != "python"
        assert expr.evaluate(unwind_data({"tags": ["java", "rust", "go"]})) is True

    def test_ne_list_some_match(self) -> None:
        """Test that Ne returns False if any value matches."""
        expr = F("tags") != "python"
        assert expr.evaluate(unwind_data({"tags": ["python", "java", "rust"]})) is False


class TestComparisonMultiValuedEval:
    """Test comparison expressions with list-valued fields."""

    def test_lt_list_any_less(self) -> None:
        """Test that Lt returns True if ANY value is less than target."""
        expr = F("scores") < 50
        assert expr.evaluate(unwind_data({"scores": [30, 60, 80]})) is True

    def test_gt_list_any_greater(self) -> None:
        """Test that Gt returns True if ANY value is greater than target."""
        expr = F("scores") > 50
        assert expr.evaluate(unwind_data({"scores": [30, 40, 60]})) is True


class TestRegexMultiValuedEval:
    """Test Regex evaluation with list-valued fields."""

    def test_regex_list_any_match(self) -> None:
        """Test that Regex returns True if ANY value matches."""
        expr = F("tags").matches(r"py.*")
        assert expr.evaluate(unwind_data({"tags": ["python", "java", "rust"]})) is True

    def test_regex_list_no_match(self) -> None:
        """Test that Regex returns False if no values match."""
        expr = F("tags").matches(r"py.*")
        assert expr.evaluate(unwind_data({"tags": ["java", "rust", "go"]})) is False


class TestIsNullMultiValuedEval:
    """Test IsNull evaluation with list-valued fields."""

    def test_is_null_empty_list(self) -> None:
        """Test that empty list is treated as null."""
        expr = F("tags").is_null()
        assert expr.evaluate(unwind_data({"tags": []})) is True

    def test_is_null_list_with_none_values(self) -> None:
        """Test that list with all None values satisfies is_null."""
        expr = F("tags").is_null()
        assert expr.evaluate(unwind_data({"tags": [None, None]})) is True

    def test_is_null_list_with_some_none(self) -> None:
        """Test that list with some None values does not satisfy is_null."""
        expr = F("tags").is_null()
        assert expr.evaluate(unwind_data({"tags": [None, "python"]})) is False

    def test_is_not_null_list_with_all_non_none(self) -> None:
        """Test that list with all non-None values satisfies is_not_null."""
        expr = F("tags").is_not_null()
        assert expr.evaluate(unwind_data({"tags": ["python", "java"]})) is True
