"""周期对比读模型与校验合一直测（架构保养第二轮候选 3）。

load_comparison_view 单一出口返回 GET /comparison 完整响应形状；
validate_comparison_request 共享校验入口抛 ComparisonError，router
映射 400、执行器落 failed 行。
"""

from datetime import datetime, timezone
from uuid import uuid4

import pytest
from agenteval.evaluation.comparison import (
    ComparisonError,
    load_comparison_view,
    validate_comparison_request,
)
from agenteval.models import (
    Campaign,
    CampaignPlanEntry,
    CampaignStatus,
    Case,
    CaseType,
    EvalTarget,
    Scenario,
)
from agenteval.storage.repository import (
    CampaignAnalysisRepository,
    CampaignPeriodComparisonRepository,
    CampaignRepository,
    ScenarioRepository,
    TargetRepository,
)
from sqlmodel import Session, SQLModel, create_engine

T0 = datetime(2026, 1, 1, 0, 0, 0, tzinfo=timezone.utc)


@pytest.fixture()
def db_session(tmp_path):
    from agenteval.storage.db import (  # noqa: F401
        CampaignAnalysisDB,
        CampaignDB,
        CampaignPeriodComparisonDB,
        EvalRunDB,
        EvalTargetDB,
        ScenarioDB,
    )

    engine = create_engine(
        f"sqlite:///{tmp_path / 'comparison.db'}",
        connect_args={"check_same_thread": False},
    )
    SQLModel.metadata.create_all(engine)
    session = Session(engine)
    try:
        yield session
    finally:
        session.close()
        engine.dispose()


def _seed_campaign(db_session, *, status=CampaignStatus.COMPLETED):
    target = TargetRepository(db_session).create(
        EvalTarget(id=f"t-{uuid4().hex[:8]}", name="数字员工")
    )
    scenario = ScenarioRepository(db_session).create(
        Scenario(id=f"s-{uuid4().hex[:8]}", name="查账单", target_id=target.id, cases=[Case(id="c-1", type=CaseType.SINGLE, messages=["你好"])])
    )
    campaign = CampaignRepository(db_session).create(
        Campaign(
            name="cycle",
            target_id=target.id,
            window_seconds=3600,
            time_scale=1.0,
            plan=[CampaignPlanEntry(scenario_id=scenario.id, offset_seconds=0, count=1)],
            status=status,
            started_at=T0,
        )
    )
    return campaign


def test_load_comparison_view_no_row_returns_none_status(db_session):
    campaign = _seed_campaign(db_session)
    view = load_comparison_view(db_session, campaign)
    assert view["status"] == "none"
    assert view["comparison"] is None
    assert "auto_baseline" in view
    assert "metric_diff" in view


def test_load_comparison_view_generating_row(db_session):
    campaign = _seed_campaign(db_session)
    CampaignPeriodComparisonRepository(db_session).upsert(
        campaign.id,
        status="generating",
        baseline_campaign_id="baseline-1",
        triggered_by="manual",
    )
    view = load_comparison_view(db_session, campaign)
    assert view["status"] == "generating"
    assert view["comparison"] is not None
    assert view["comparison"]["baseline_campaign_id"] == "baseline-1"


def test_load_comparison_view_completed_row_includes_model_name(db_session):
    campaign = _seed_campaign(db_session)
    CampaignPeriodComparisonRepository(db_session).upsert(
        campaign.id,
        status="completed",
        baseline_campaign_id="baseline-1",
        result={"trend": "improving"},
        model_config_id="mc-1",
        triggered_by="manual",
    )
    view = load_comparison_view(db_session, campaign)
    assert view["status"] == "completed"
    assert view["comparison"]["result"] == {"trend": "improving"}
    assert "model_name" in view["comparison"]


def test_validate_rejects_non_completed_campaign(db_session):
    campaign = _seed_campaign(db_session, status=CampaignStatus.RUNNING)
    with pytest.raises(ComparisonError, match="活动完成后"):
        validate_comparison_request(db_session, campaign)


def test_validate_rejects_missing_analysis_model(db_session, monkeypatch):
    campaign = _seed_campaign(db_session)
    monkeypatch.setattr(
        "agenteval.evaluation.comparison.resolve_analysis_model",
        lambda *a, **kw: None,
    )
    with pytest.raises(ComparisonError, match="未配置分析模型"):
        validate_comparison_request(db_session, campaign)


def test_validate_rejects_incomplete_current_analysis(db_session, monkeypatch):
    campaign = _seed_campaign(db_session)
    monkeypatch.setattr(
        "agenteval.evaluation.comparison.resolve_analysis_model",
        lambda *a, **kw: object(),
    )
    CampaignAnalysisRepository(db_session).upsert(
        campaign.id, status="generating", triggered_by="auto"
    )
    with pytest.raises(ComparisonError, match="请先生成本期活动的智能分析"):
        validate_comparison_request(db_session, campaign)


def test_validate_rejects_missing_explicit_baseline(db_session, monkeypatch):
    campaign = _seed_campaign(db_session)
    monkeypatch.setattr(
        "agenteval.evaluation.comparison.resolve_analysis_model",
        lambda *a, **kw: object(),
    )
    CampaignAnalysisRepository(db_session).upsert(
        campaign.id, status="completed", result={}, triggered_by="auto"
    )
    with pytest.raises(ComparisonError, match="基线活动不存在"):
        validate_comparison_request(db_session, campaign, explicit_baseline_id="missing")


def test_validate_rejects_incomplete_baseline_analysis(db_session, monkeypatch):
    campaign = _seed_campaign(db_session)
    monkeypatch.setattr(
        "agenteval.evaluation.comparison.resolve_analysis_model",
        lambda *a, **kw: object(),
    )
    baseline = _seed_campaign(db_session)
    CampaignAnalysisRepository(db_session).upsert(
        campaign.id, status="completed", result={}, triggered_by="auto"
    )
    CampaignAnalysisRepository(db_session).upsert(
        baseline.id, status="generating", triggered_by="auto"
    )
    with pytest.raises(ComparisonError, match="基线活动没有已完成的智能分析"):
        validate_comparison_request(db_session, campaign, explicit_baseline_id=baseline.id)
