"""
Tests for judge engine data models.
"""

import pytest
from opensentinel.policy.engines.judge.models import (
    EvaluationType,
    EvaluationScope,
    ScoreScale,
    VerdictAction,
    RubricCriterion,
    Rubric,
    JudgeScore,
    JudgeVerdict,
    JudgeSessionContext,
)


class TestScoreScale:
    def test_max_score_values(self):
        assert ScoreScale.BINARY.max_score == 1
        assert ScoreScale.LIKERT_3.max_score == 3
        assert ScoreScale.LIKERT_5.max_score == 5
        assert ScoreScale.LIKERT_7.max_score == 7
        assert ScoreScale.LIKERT_10.max_score == 10

    def test_min_score_values(self):
        assert ScoreScale.BINARY.min_score == 0
        assert ScoreScale.LIKERT_5.min_score == 1


class TestJudgeScore:
    def test_normalized_binary(self):
        score = JudgeScore(criterion="test", score=1, max_score=1, reasoning="ok")
        assert score.normalized == 1.0

        score = JudgeScore(criterion="test", score=0, max_score=1, reasoning="fail")
        assert score.normalized == 0.0

    def test_normalized_likert(self):
        # 5/5 -> 1.0
        score = JudgeScore(criterion="test", score=5, max_score=5, reasoning="ok")
        assert score.normalized == 1.0

        # 1/5 -> 0.0
        score = JudgeScore(criterion="test", score=1, max_score=5, reasoning="ok")
        assert score.normalized == 0.0

        # 3/5 -> 0.5
        score = JudgeScore(criterion="test", score=3, max_score=5, reasoning="ok")
        assert score.normalized == 0.5

    def test_normalized_zero_max(self):
        score = JudgeScore(criterion="test", score=0, max_score=0, reasoning="ok")
        assert score.normalized == 0.0


class TestJudgeVerdict:
    def test_to_dict(self):
        verdict = JudgeVerdict(
            scores=[
                JudgeScore(criterion="c1", score=4, max_score=5, reasoning="good"),
            ],
            composite_score=0.75,
            action=VerdictAction.PASS,
            summary="Looks good",
            judge_model="gpt-4o-mini",
            latency_ms=500.0,
        )
        d = verdict.to_dict()
        assert d["composite_score"] == 0.75
        assert d["action"] == "pass"
        assert d["judge_model"] == "gpt-4o-mini"
        assert len(d["scores"]) == 1
        assert d["scores"][0]["criterion"] == "c1"
        assert "normalized" in d["scores"][0]


class TestRubric:
    def test_defaults(self):
        rubric = Rubric(
            name="test",
            description="test rubric",
            criteria=[RubricCriterion(name="c1", description="criterion 1")],
        )
        assert rubric.evaluation_type == EvaluationType.POINTWISE
        assert rubric.scope == EvaluationScope.TURN
        assert rubric.pass_threshold == 0.6
        assert rubric.fail_action == VerdictAction.WARN
        assert rubric.prompt_overrides == {}


class TestJudgeSessionContext:
    def test_record_verdict(self):
        session = JudgeSessionContext(session_id="s1")
        assert session.turn_count == 0

        verdict = JudgeVerdict(
            scores=[],
            composite_score=0.8,
            action=VerdictAction.PASS,
            summary="ok",
            judge_model="test",
            token_usage=100,
        )
        session.record_verdict(verdict)

        assert session.turn_count == 1
        assert session.score_trend == [0.8]
        assert session.total_tokens_used == 100
        assert len(session.evaluation_history) == 1

    def test_record_violation_counts(self):
        session = JudgeSessionContext(session_id="s1")

        warn_verdict = JudgeVerdict(
            scores=[], composite_score=0.3, action=VerdictAction.WARN,
            summary="warning", judge_model="test",
        )
        session.record_verdict(warn_verdict)
        session.record_verdict(warn_verdict)

        assert session.violation_counts["warn"] == 2

    def test_to_dict(self):
        session = JudgeSessionContext(session_id="s1")
        d = session.to_dict()
        assert d["session_id"] == "s1"
        assert d["turn_count"] == 0
        assert "created_at" in d
