"""Tests for six-level nuanced vote evaluation.

Levels: 0-CONTRE, 1-PAS DU TOUT, 2-PAS D'ACCORD, 3-NEUTRE, 4-D'ACCORD, 5-TOUT A FAIT
Positive = levels 3 + 4 + 5
Adoption requires: positive_pct >= threshold (80%) AND total >= min_participants (59).
"""

import pytest

from app.engine.nuanced_vote import evaluate_nuanced


class TestNuancedVoteAdoption:
    """Cases where the vote should be adopted."""

    def test_59_positive_10_negative_adopted(self):
        """59 positive (levels 3-5) + 10 negative = 69 total.
        positive_pct = 59/69 ~ 85.5% >= 80% and 69 >= 59 => adopted.
        """
        votes = [5] * 20 + [4] * 20 + [3] * 19 + [2] * 5 + [1] * 3 + [0] * 2
        result = evaluate_nuanced(votes, threshold_pct=80, min_participants=59)

        assert result["total"] == 69
        assert result["positive_count"] == 59
        assert result["positive_pct"] == pytest.approx(85.51, abs=0.1)
        assert result["threshold_met"] is True
        assert result["min_participants_met"] is True
        assert result["adopted"] is True

    def test_all_tout_a_fait_adopted(self):
        """All 59 voters at level 5 => 100% positive, adopted."""
        votes = [5] * 59
        result = evaluate_nuanced(votes, threshold_pct=80, min_participants=59)

        assert result["total"] == 59
        assert result["positive_count"] == 59
        assert result["positive_pct"] == 100.0
        assert result["adopted"] is True


class TestNuancedVoteRejection:
    """Cases where the vote should be rejected."""

    def test_40_positive_30_negative_rejected(self):
        """40 positive + 30 negative = 70 total.
        positive_pct = 40/70 ~ 57.14% < 80% => threshold not met.
        """
        votes = [5] * 15 + [4] * 15 + [3] * 10 + [2] * 10 + [1] * 10 + [0] * 10
        result = evaluate_nuanced(votes, threshold_pct=80, min_participants=59)

        assert result["total"] == 70
        assert result["positive_count"] == 40
        assert result["positive_pct"] == pytest.approx(57.14, abs=0.1)
        assert result["threshold_met"] is False
        assert result["min_participants_met"] is True  # 70 >= 59
        assert result["adopted"] is False

    def test_min_participants_not_met(self):
        """50 positive + 5 negative = 55 total < 59 min_participants.
        Even though 50/55 ~ 90.9% > 80%, adoption fails on min_participants.
        """
        votes = [5] * 30 + [4] * 10 + [3] * 10 + [1] * 3 + [0] * 2
        result = evaluate_nuanced(votes, threshold_pct=80, min_participants=59)

        assert result["total"] == 55
        assert result["positive_count"] == 50
        assert result["positive_pct"] > 80
        assert result["threshold_met"] is True
        assert result["min_participants_met"] is False
        assert result["adopted"] is False


class TestNuancedVoteEdgeCases:
    """Edge cases and exact boundary conditions."""

    def test_exact_threshold_80_percent(self):
        """Exactly 80% positive votes should pass the threshold."""
        # 80 positive out of 100 = exactly 80%
        votes = [5] * 40 + [4] * 20 + [3] * 20 + [2] * 10 + [1] * 5 + [0] * 5
        result = evaluate_nuanced(votes, threshold_pct=80, min_participants=59)

        assert result["total"] == 100
        assert result["positive_count"] == 80
        assert result["positive_pct"] == 80.0
        assert result["threshold_met"] is True
        assert result["min_participants_met"] is True
        assert result["adopted"] is True

    def test_just_below_threshold(self):
        """79 positive out of 100 = 79% < 80% => rejected."""
        votes = [5] * 39 + [4] * 20 + [3] * 20 + [2] * 11 + [1] * 5 + [0] * 5
        result = evaluate_nuanced(votes, threshold_pct=80, min_participants=59)

        assert result["total"] == 100
        assert result["positive_count"] == 79
        assert result["positive_pct"] == 79.0
        assert result["threshold_met"] is False
        assert result["adopted"] is False

    def test_empty_votes(self):
        """Zero votes => not adopted."""
        result = evaluate_nuanced([], threshold_pct=80, min_participants=59)
        assert result["total"] == 0
        assert result["positive_count"] == 0
        assert result["positive_pct"] == 0.0
        assert result["adopted"] is False

    def test_invalid_vote_level(self):
        """Vote level outside 0-5 raises ValueError."""
        with pytest.raises(ValueError, match="invalide"):
            evaluate_nuanced([5, 3, 6])

    def test_per_level_counts(self):
        """Verify per-level breakdown is correct."""
        votes = [0, 1, 2, 3, 4, 5, 5, 4, 3]
        result = evaluate_nuanced(votes, threshold_pct=50, min_participants=1)

        assert result["per_level_counts"] == {0: 1, 1: 1, 2: 1, 3: 2, 4: 2, 5: 2}
        assert result["positive_count"] == 6  # 2+2+2
        assert result["total"] == 9
