"""Tests for 50% rule validation.

The 50% rule prevents context exhaustion by ensuring no single issue
consumes more than 50% of the target agent's context limit.
"""


from src.models import IssueMetadata
from src.validation import validate_fifty_percent_rule


class TestFiftyPercentRule:
    """Test 50% rule prevents context exhaustion."""

    def test_oversized_issue_rejected(self) -> None:
        """Should reject issue that exceeds 50% of agent context limit."""
        # 120K tokens for sonnet (200K limit) = 60% > 50% threshold
        metadata = IssueMetadata(
            estimated_context=120000,
            assigned_agent="sonnet",
        )

        result = validate_fifty_percent_rule(metadata)

        assert result.valid is False
        assert "exceeds 50%" in result.reason.lower()
        assert "120000" in result.reason  # Should mention actual size
        assert "100000" in result.reason  # Should mention max allowed

    def test_properly_sized_issue_accepted(self) -> None:
        """Should accept issue that is well below 50% threshold."""
        # 80K tokens for sonnet (200K limit) = 40% < 50% threshold
        metadata = IssueMetadata(
            estimated_context=80000,
            assigned_agent="sonnet",
        )

        result = validate_fifty_percent_rule(metadata)

        assert result.valid is True
        assert result.reason == ""

    def test_edge_case_exactly_fifty_percent(self) -> None:
        """Should accept issue at exactly 50% of context limit."""
        # Exactly 100K tokens for sonnet (200K limit) = 50%
        metadata = IssueMetadata(
            estimated_context=100000,
            assigned_agent="sonnet",
        )

        result = validate_fifty_percent_rule(metadata)

        assert result.valid is True
        assert result.reason == ""

    def test_multiple_sequential_issues_within_limit(self) -> None:
        """Should accept multiple medium-sized issues without exhaustion."""
        # Simulate sequential assignment of 3 medium issues
        # Each 60K for sonnet = 30% each, total would be 90% over time
        # But 50% rule only checks INDIVIDUAL issues, not cumulative
        issues = [
            IssueMetadata(estimated_context=60000, assigned_agent="sonnet"),
            IssueMetadata(estimated_context=60000, assigned_agent="sonnet"),
            IssueMetadata(estimated_context=60000, assigned_agent="sonnet"),
        ]

        results = [validate_fifty_percent_rule(issue) for issue in issues]

        # All should pass individually
        assert all(r.valid for r in results)

    def test_opus_agent_200k_limit(self) -> None:
        """Should use correct 200K limit for opus agent."""
        # 110K for opus (200K limit) = 55% > 50%
        metadata = IssueMetadata(
            estimated_context=110000,
            assigned_agent="opus",
        )

        result = validate_fifty_percent_rule(metadata)

        assert result.valid is False

    def test_haiku_agent_200k_limit(self) -> None:
        """Should use correct 200K limit for haiku agent."""
        # 90K for haiku (200K limit) = 45% < 50%
        metadata = IssueMetadata(
            estimated_context=90000,
            assigned_agent="haiku",
        )

        result = validate_fifty_percent_rule(metadata)

        assert result.valid is True

    def test_glm_agent_128k_limit(self) -> None:
        """Should use correct 128K limit for glm agent (self-hosted)."""
        # 70K for glm (128K limit) = 54.7% > 50%
        metadata = IssueMetadata(
            estimated_context=70000,
            assigned_agent="glm",
        )

        result = validate_fifty_percent_rule(metadata)

        assert result.valid is False
        assert "64000" in result.reason  # 50% of 128K

    def test_glm_agent_at_threshold(self) -> None:
        """Should accept issue at exactly 50% for glm agent."""
        # Exactly 64K for glm (128K limit) = 50%
        metadata = IssueMetadata(
            estimated_context=64000,
            assigned_agent="glm",
        )

        result = validate_fifty_percent_rule(metadata)

        assert result.valid is True

    def test_validation_result_structure(self) -> None:
        """Should return properly structured ValidationResult."""
        metadata = IssueMetadata(
            estimated_context=50000,
            assigned_agent="sonnet",
        )

        result = validate_fifty_percent_rule(metadata)

        # Result should have required attributes
        assert hasattr(result, "valid")
        assert hasattr(result, "reason")
        assert isinstance(result.valid, bool)
        assert isinstance(result.reason, str)

    def test_rejection_reason_contains_context(self) -> None:
        """Should provide detailed rejection reason with context."""
        metadata = IssueMetadata(
            estimated_context=150000,
            assigned_agent="sonnet",
        )

        result = validate_fifty_percent_rule(metadata)

        # Reason should be informative
        assert result.valid is False
        assert "sonnet" in result.reason.lower()
        assert "150000" in result.reason
        assert "100000" in result.reason
        assert len(result.reason) > 20  # Should be descriptive

    def test_zero_context_estimate_accepted(self) -> None:
        """Should accept issue with zero context estimate."""
        metadata = IssueMetadata(
            estimated_context=0,
            assigned_agent="sonnet",
        )

        result = validate_fifty_percent_rule(metadata)

        assert result.valid is True

    def test_very_small_issue_accepted(self) -> None:
        """Should accept very small issues (< 1% of limit)."""
        metadata = IssueMetadata(
            estimated_context=1000,  # 0.5% of 200K
            assigned_agent="sonnet",
        )

        result = validate_fifty_percent_rule(metadata)

        assert result.valid is True
