"""Tests for resilience scoring."""

from probeagent.core.models import (
    AttackOutcome,
    AttackResult,
    ResilienceGrade,
    Severity,
)
from probeagent.core.scoring import calculate_resilience_score


class TestGradeBoundaries:
    def test_safe_no_results(self):
        score = calculate_resilience_score([])
        assert score.grade == ResilienceGrade.SAFE
        assert score.total == 0

    def test_safe_all_failed(self):
        results = [
            AttackResult(
                attack_name="prompt_injection",
                outcome=AttackOutcome.FAILED,
                severity=Severity.CRITICAL,
            ),
            AttackResult(
                attack_name="goal_hijacking",
                outcome=AttackOutcome.FAILED,
                severity=Severity.HIGH,
            ),
        ]
        score = calculate_resilience_score(results)
        assert score.grade == ResilienceGrade.SAFE
        assert score.succeeded == 0

    def test_at_risk_low_severity(self, sample_succeeded_low):
        results = [
            sample_succeeded_low,
            AttackResult(
                attack_name="goal_hijacking",
                outcome=AttackOutcome.FAILED,
                severity=Severity.HIGH,
            ),
        ]
        score = calculate_resilience_score(results)
        assert score.grade == ResilienceGrade.AT_RISK
        assert score.highest_severity_succeeded == Severity.LOW

    def test_at_risk_medium_severity(self):
        results = [
            AttackResult(
                attack_name="data_exfil",
                outcome=AttackOutcome.SUCCEEDED,
                severity=Severity.MEDIUM,
                success=True,
            ),
        ]
        score = calculate_resilience_score(results)
        assert score.grade == ResilienceGrade.AT_RISK
        assert score.highest_severity_succeeded == Severity.MEDIUM

    def test_compromised_high_severity(self):
        results = [
            AttackResult(
                attack_name="goal_hijacking",
                outcome=AttackOutcome.SUCCEEDED,
                severity=Severity.HIGH,
                success=True,
            ),
        ]
        score = calculate_resilience_score(results)
        assert score.grade == ResilienceGrade.COMPROMISED

    def test_compromised_critical_severity(self, sample_succeeded_critical):
        score = calculate_resilience_score([sample_succeeded_critical])
        assert score.grade == ResilienceGrade.COMPROMISED
        assert score.highest_severity_succeeded == Severity.CRITICAL


class TestCounting:
    def test_counts(
        self,
        sample_succeeded_critical,
        sample_failed,
        sample_error,
        sample_skipped,
    ):
        results = [
            sample_succeeded_critical,
            sample_failed,
            sample_error,
            sample_skipped,
        ]
        score = calculate_resilience_score(results)
        assert score.total == 4
        assert score.succeeded == 1
        assert score.failed == 1
        assert score.errors == 1
        assert score.skipped == 1

    def test_errors_dont_count_as_success(self, sample_error):
        score = calculate_resilience_score([sample_error])
        assert score.grade == ResilienceGrade.SAFE
        assert score.succeeded == 0

    def test_skipped_dont_count_as_success(self, sample_skipped):
        score = calculate_resilience_score([sample_skipped])
        assert score.grade == ResilienceGrade.SAFE
        assert score.succeeded == 0


class TestSummaries:
    def test_grouping(self, sample_succeeded_critical, sample_failed):
        results = [sample_succeeded_critical, sample_failed]
        score = calculate_resilience_score(results)
        assert len(score.summaries) == 2

    def test_sorted_by_severity(self, sample_succeeded_critical, sample_succeeded_low):
        results = [sample_succeeded_low, sample_succeeded_critical]
        score = calculate_resilience_score(results)
        assert score.summaries[0].severity == Severity.CRITICAL
        assert score.summaries[1].severity == Severity.LOW

    def test_summary_success_rate(self):
        results = [
            AttackResult(
                attack_name="prompt_injection",
                outcome=AttackOutcome.SUCCEEDED,
                severity=Severity.CRITICAL,
                success=True,
            ),
            AttackResult(
                attack_name="prompt_injection",
                outcome=AttackOutcome.FAILED,
                severity=Severity.CRITICAL,
            ),
        ]
        score = calculate_resilience_score(results)
        summary = score.summaries[0]
        assert summary.attack_name == "prompt_injection"
        assert summary.succeeded == 1
        assert summary.failed == 1
        assert summary.success_rate == 0.5


class TestDeterminism:
    def test_same_input_same_output(self, sample_succeeded_critical, sample_failed):
        results = [sample_succeeded_critical, sample_failed]
        s1 = calculate_resilience_score(results)
        s2 = calculate_resilience_score(results)
        assert s1.grade == s2.grade
        assert s1.total == s2.total
        assert s1.succeeded == s2.succeeded
        assert len(s1.summaries) == len(s2.summaries)
