"""recover_stalled_head_training_runs + recover_stalled_head_auto_apply_runs share
one helper (_recover_stalled_runs, DRY pass #161). These pin BOTH wrappers so the
shared source stays correct: a 'running' row with no progress past the stall
threshold flips to 'error'; a fresh 'running' row is left alone."""
from datetime import UTC, datetime, timedelta

import pytest
from sqlalchemy import select

from backend.app.models import HeadAutoApplyRun, HeadTrainingRun

pytestmark = pytest.mark.integration


def test_recover_stalled_head_training_runs_flips_stalled_keeps_fresh(db_sync):
    from backend.app.tasks.maintenance import recover_stalled_head_training_runs

    stale = HeadTrainingRun(
        params={}, status="running",
        last_progress_at=datetime.now(UTC) - timedelta(days=1),
    )
    fresh = HeadTrainingRun(
        params={}, status="running", last_progress_at=datetime.now(UTC),
    )
    db_sync.add_all([stale, fresh])
    db_sync.commit()
    stale_id, fresh_id = stale.id, fresh.id

    assert recover_stalled_head_training_runs.apply().get() == 1

    db_sync.expire_all()
    assert db_sync.execute(
        select(HeadTrainingRun.status).where(HeadTrainingRun.id == stale_id)
    ).scalar_one() == "error"
    assert db_sync.execute(
        select(HeadTrainingRun.status).where(HeadTrainingRun.id == fresh_id)
    ).scalar_one() == "running"


def test_recover_stalled_head_auto_apply_runs_flips_stalled_keeps_fresh(db_sync):
    from backend.app.tasks.maintenance import recover_stalled_head_auto_apply_runs

    stale = HeadAutoApplyRun(
        dry_run=False, params={}, status="running",
        last_progress_at=datetime.now(UTC) - timedelta(days=1),
    )
    fresh = HeadAutoApplyRun(
        dry_run=False, params={}, status="running",
        last_progress_at=datetime.now(UTC),
    )
    db_sync.add_all([stale, fresh])
    db_sync.commit()
    stale_id, fresh_id = stale.id, fresh.id

    assert recover_stalled_head_auto_apply_runs.apply().get() == 1

    db_sync.expire_all()
    assert db_sync.execute(
        select(HeadAutoApplyRun.status).where(HeadAutoApplyRun.id == stale_id)
    ).scalar_one() == "error"
    assert db_sync.execute(
        select(HeadAutoApplyRun.status).where(HeadAutoApplyRun.id == fresh_id)
    ).scalar_one() == "running"
