"""Exploration summary aggregation (v0.9 票据 05).

体验记录聚合成探索摘要：会话数、目标达成率、问题清单（blockers/misled
按出现次数降序）、judge 复核结论（已就位才纳入；findings 全量收各档发现，
poor 档排前）。缺则无痕：无会话返回 None。纯函数，不落库。
"""

from agenteval.exploration.models import ExplorationSession, ExplorationSessionStatus
from agenteval.exploration.summary import summarize_exploration


def _session(experience=None, judge_review=None, status=ExplorationSessionStatus.COMPLETED) -> ExplorationSession:
    return ExplorationSession(
        campaign_id="c-1",
        target_id="t-1",
        persona={"name": "x"},
        goal="查询账单",
        status=status,
        experience=experience,
        judge_review=judge_review,
    )


def _experience(goal_achieved: bool, blockers=None, misled=None) -> dict:
    return {
        "goal_achieved": goal_achieved,
        "blockers": blockers or [],
        "misled": misled or [],
        "emotion": "neutral",
        "notes": "",
    }


def test_no_sessions_returns_none():
    assert summarize_exploration([]) is None


def test_aggregates_counts_rate_and_issue_lists():
    sessions = [
        _session(_experience(True, blockers=["缴费入口难找"])),
        _session(_experience(False, blockers=["缴费入口难找", "验证码收不到"], misled=["被误导选了错误套餐"])),
        _session(_experience(False, blockers=["验证码收不到"])),
    ]
    summary = summarize_exploration(sessions)
    assert summary["session_count"] == 3
    assert summary["sessions_with_experience"] == 3
    assert summary["goal_achieved_count"] == 1
    assert summary["goal_achievement_rate"] == round(1 / 3, 4)
    # 问题清单按出现次数降序（同频按首次出现顺序）
    assert summary["issues"] == [
        {"issue": "缴费入口难找", "count": 2},
        {"issue": "验证码收不到", "count": 2},
    ]
    assert summary["misled"] == [{"issue": "被误导选了错误套餐", "count": 1}]


def test_sessions_without_experience_excluded_from_rate_denominator():
    sessions = [
        _session(_experience(True)),
        _session(),  # 未关闭/无体验记录
    ]
    summary = summarize_exploration(sessions)
    assert summary["session_count"] == 2
    assert summary["sessions_with_experience"] == 1
    assert summary["goal_achievement_rate"] == 1.0
    assert summary["issues"] == []


def test_no_experience_at_all_rate_is_none():
    summary = summarize_exploration([_session(), _session()])
    assert summary["goal_achievement_rate"] is None
    assert summary["issues"] == [] and summary["misled"] == []


def test_judge_review_included_only_when_completed():
    good_review = {
        "status": "completed",
        "dimensions": [
            {"dimension": "attitude", "rating": "good", "comment": "友好"},
            {"dimension": "professionalism", "rating": "acceptable", "comment": "基本准确"},
            {"dimension": "hallucination", "rating": "poor", "comment": "编造了政策"},
        ],
        "summary": "存在幻觉",
    }
    failed_review = {"status": "failed", "error": "解析失败"}
    sessions = [
        _session(_experience(True), judge_review=good_review),
        _session(_experience(False), judge_review=failed_review),
        _session(_experience(True)),  # 未复核
    ]
    summary = summarize_exploration(sessions)
    judge = summary["judge_review"]
    assert judge["reviewed_sessions"] == 1
    # 复核发现全量纳入，poor 档排前（票据 05：复核结论一并纳入）
    assert judge["findings"] == [
        {"dimension": "hallucination", "rating": "poor", "comment": "编造了政策"},
        {"dimension": "professionalism", "rating": "acceptable", "comment": "基本准确"},
        {"dimension": "attitude", "rating": "good", "comment": "友好"},
    ]
    # 复核总体结论一并纳入
    assert judge["summaries"] == ["存在幻觉"]


def test_judge_review_absent_when_none_reviewed():
    summary = summarize_exploration([_session(_experience(True))])
    assert summary["judge_review"] is None
