"""Startup cleanup of orphan runs (interrupted by server restart)."""

from agenteval.models import Campaign, CampaignPlanEntry, CampaignStatus, EvalRun, RunStatus
from agenteval.storage.repository import CampaignRepository, RunRepository


def _make_run(session, status: RunStatus) -> str:
    run = RunRepository(session).create(EvalRun(
        target_id="t-1", scenario_id="s-1", status=status,
    ))
    return run.id


def test_mark_orphans_failed(db_session):
    repo = RunRepository(db_session)
    running_id = _make_run(db_session, RunStatus.RUNNING)
    pending_id = _make_run(db_session, RunStatus.PENDING)
    completed_id = _make_run(db_session, RunStatus.COMPLETED)
    failed_id = _make_run(db_session, RunStatus.FAILED)

    count = repo.mark_orphans_failed()

    assert count == 2
    for rid in (running_id, pending_id):
        run = repo.get(rid)
        assert run.status == RunStatus.FAILED
        assert run.summary.error.code == "interrupted"
        assert run.completed_at is not None
    # 已完结的运行不受影响
    assert repo.get(completed_id).status == RunStatus.COMPLETED
    assert repo.get(failed_id).status == RunStatus.FAILED
    assert repo.get(completed_id).summary is None


def test_mark_orphans_failed_noop_when_clean(db_session):
    repo = RunRepository(db_session)
    _make_run(db_session, RunStatus.COMPLETED)
    assert repo.mark_orphans_failed() == 0


def test_mark_orphans_preserves_only_recoverable_campaign_pending(db_session):
    campaign = CampaignRepository(db_session).create(
        Campaign(
            id="campaign-1",
            name="running",
            target_id="t-1",
            status=CampaignStatus.RUNNING,
            window_seconds=60,
            plan=[CampaignPlanEntry(scenario_id="s-1", offset_seconds=0, count=2)],
        )
    )
    repo = RunRepository(db_session)
    pending = repo.create(
        EvalRun(
            target_id="t-1",
            scenario_id="s-1",
            campaign_id=campaign.id,
            campaign_plan_index=0,
            campaign_occurrence_index=0,
            status=RunStatus.PENDING,
        )
    )
    running = repo.create(
        EvalRun(
            target_id="t-1",
            scenario_id="s-1",
            campaign_id=campaign.id,
            campaign_plan_index=0,
            campaign_occurrence_index=1,
            status=RunStatus.RUNNING,
        )
    )

    count = repo.mark_orphans_failed()

    assert count == 1
    assert repo.get(pending.id).status is RunStatus.PENDING
    assert repo.get(running.id).status is RunStatus.FAILED


def test_update_preserves_scenario_version_and_triggered_by(db_session):
    """update() 不得丢字段：scenario_version / triggered_by 必须回写（漂移回归）。"""
    from agenteval.models import RunTrigger

    repo = RunRepository(db_session)
    run = repo.create(EvalRun(
        target_id="t-1", scenario_id="s-1", status=RunStatus.RUNNING,
        scenario_version=4, triggered_by=RunTrigger.AI_ASSISTANT,
    ))
    run.scenario_version = 5
    run.triggered_by = RunTrigger.CLI
    run.status = RunStatus.COMPLETED
    updated = repo.update(run)

    assert updated.scenario_version == 5
    assert updated.triggered_by == RunTrigger.CLI
