"""
Tests for the intelligent constraint relaxer.

Tests cover:
- Constraint priority handling
- Progressive relaxation strategies
- Constraint type inference
"""

from unittest.mock import Mock


class TestIntelligentConstraintRelaxer:
    """Tests for the IntelligentConstraintRelaxer class."""

    def test_relaxer_constraint_priorities(self):
        """Verify constraint type priorities are correctly defined."""
        from local_deep_research.advanced_search_system.constraint_checking.intelligent_constraint_relaxer import (
            IntelligentConstraintRelaxer,
        )

        relaxer = IntelligentConstraintRelaxer()

        # High priority constraints should never be relaxed first
        assert (
            relaxer.constraint_priorities["NAME_PATTERN"]
            > relaxer.constraint_priorities["STATISTIC"]
        )
        assert (
            relaxer.constraint_priorities["EXISTENCE"]
            > relaxer.constraint_priorities["COMPARISON"]
        )
        assert (
            relaxer.constraint_priorities["LOCATION"]
            > relaxer.constraint_priorities["RELATIONSHIP"]
        )

        # Verify COMPARISON and STATISTIC are lowest priority
        assert relaxer.constraint_priorities["COMPARISON"] <= 3
        assert relaxer.constraint_priorities["STATISTIC"] <= 3

    def test_relax_constraints_sufficient_candidates(self):
        """No relaxation when enough candidates are already found."""
        from local_deep_research.advanced_search_system.constraint_checking.intelligent_constraint_relaxer import (
            IntelligentConstraintRelaxer,
        )

        relaxer = IntelligentConstraintRelaxer()

        mock_constraints = [Mock() for _ in range(5)]
        mock_candidates = [Mock() for _ in range(10)]

        result = relaxer.relax_constraints_progressively(
            constraints=mock_constraints,
            candidates_found=mock_candidates,
            target_candidates=5,
        )

        # Should return original constraints unchanged
        assert len(result) == 1
        assert result[0] == mock_constraints

    def test_relax_constraints_progressively(self):
        """Test progressive constraint removal when candidates are insufficient."""
        from local_deep_research.advanced_search_system.constraint_checking.intelligent_constraint_relaxer import (
            IntelligentConstraintRelaxer,
        )

        relaxer = IntelligentConstraintRelaxer()

        # Create mock constraints with different types
        constraints = []
        for type_name in [
            "NAME_PATTERN",
            "LOCATION",
            "TEMPORAL",
            "STATISTIC",
            "COMPARISON",
        ]:
            mock = Mock()
            mock.type = Mock()
            mock.type.value = type_name
            constraints.append(mock)

        # Only 1 candidate found, need relaxation
        mock_candidates = [Mock()]

        result = relaxer.relax_constraints_progressively(
            constraints=constraints,
            candidates_found=mock_candidates,
            target_candidates=5,
        )

        # Should have multiple relaxation strategies
        assert len(result) >= 1

    def test_relax_statistical_constraint(self):
        """Test number range expansion (10%, 20%, 50%)."""
        from local_deep_research.advanced_search_system.constraint_checking.intelligent_constraint_relaxer import (
            IntelligentConstraintRelaxer,
        )

        relaxer = IntelligentConstraintRelaxer()

        mock_constraint = Mock()
        mock_constraint.value = "population of 1000000"
        mock_constraint.__str__ = lambda self: "population of 1000000"

        variations = relaxer._relax_statistical_constraint(mock_constraint)

        # Should create range variations
        assert len(variations) > 0

        # Check that at least one variation contains "between" or "approximately"
        variation_texts = [str(v) for v in variations]
        has_range = any(
            "between" in v.lower() or "approximately" in v.lower()
            for v in variation_texts
        )
        assert (
            has_range or len(variations) > 0
        )  # Either range patterns or other relaxations

    def test_relax_temporal_constraint(self):
        """Test year to decade conversion."""
        from local_deep_research.advanced_search_system.constraint_checking.intelligent_constraint_relaxer import (
            IntelligentConstraintRelaxer,
        )
        from local_deep_research.advanced_search_system.constraints.base_constraint import (
            Constraint,
            ConstraintType,
        )

        relaxer = IntelligentConstraintRelaxer()

        constraint = Constraint(
            id="c1",
            type=ConstraintType.TEMPORAL,
            description="Founded date",
            value="founded in 1985",
        )

        variations = relaxer._relax_temporal_constraint(constraint)

        # Should create decade-based variations
        assert len(variations) > 0

    def test_get_constraint_type_inference(self):
        """Test type inference from text patterns."""
        from local_deep_research.advanced_search_system.constraint_checking.intelligent_constraint_relaxer import (
            IntelligentConstraintRelaxer,
        )
        from local_deep_research.advanced_search_system.constraints.base_constraint import (
            Constraint,
            ConstraintType,
        )

        relaxer = IntelligentConstraintRelaxer()

        # Test with constraint that has type attribute
        # Note: _get_constraint_type returns the enum value, which is lowercase
        name_constraint = Constraint(
            id="c1",
            type=ConstraintType.NAME_PATTERN,
            description="Name pattern",
            value="known as the Big Apple",
        )
        assert relaxer._get_constraint_type(name_constraint) == "name_pattern"

        location_constraint = Constraint(
            id="c2",
            type=ConstraintType.LOCATION,
            description="Location",
            value="located in France",
        )
        assert relaxer._get_constraint_type(location_constraint) == "location"

        temporal_constraint = Constraint(
            id="c3",
            type=ConstraintType.TEMPORAL,
            description="Time",
            value="the year 1990",
        )
        assert relaxer._get_constraint_type(temporal_constraint) == "temporal"

        comparison_constraint = Constraint(
            id="c4",
            type=ConstraintType.COMPARISON,
            description="Comparison",
            value="larger than previous",
        )
        assert (
            relaxer._get_constraint_type(comparison_constraint) == "comparison"
        )

        property_constraint = Constraint(
            id="c5",
            type=ConstraintType.PROPERTY,
            description="Property",
            value="some random text",
        )
        assert relaxer._get_constraint_type(property_constraint) == "property"
