"""tests/core 공용 fixture — resume 무결성 framework 테스트용.

`make_step_runner` 팩토리는 StepRunner 인스턴스를 만들 때 사용한다.
recovery counter 메서드(_record_recovery 등)는 step_run 테이블에 raw SQL UPDATE를
호출하므로 진짜 PG 세션이 필요하다. tests/conftest.py가 ENVIRONMENT/DATABASE_URL을
test DB(`theroad_test`)로 강제한 뒤 import되므로, SessionLocal은 이미 test DB에
연결돼 있다. 진짜 세션을 기본으로 yield해 verify/cleanup 단위 테스트와 recovery
counter 테스트 모두 동일한 fixture에서 돌아가도록 한다.

Task 5의 verify/cleanup default 메서드는 DB를 건드리지 않으므로 진짜 세션을
넘겨도 영향 없음.
"""
from __future__ import annotations

import pytest
from sqlalchemy import text


@pytest.fixture
def tmp_project_id() -> str:
    """결정적 임시 project_id — DB row 생성 없음 (string-only fixture)."""
    return "p-test-resilience"


@pytest.fixture
def tmp_episode_id() -> str:
    """결정적 임시 episode_id — DB row 생성 없음."""
    return "e-test-resilience"


@pytest.fixture
def db_session(tmp_project_id, tmp_episode_id):
    """test DB(`theroad_test`)에 연결된 SQLAlchemy 세션.

    tests/conftest.py가 DATABASE_URL을 test DB로 이미 override했고 step_run
    테이블은 init_db()로 보장된다. fixture 진입/종료 시 본 테스트 pid/eid의
    step_run row를 정리해 테스트 간 격리를 보장한다.
    """
    from app.core.database import SessionLocal, init_db

    init_db()
    session = SessionLocal()
    # 진입 시 정리 — 직전 fail 잔여 row 회수.
    session.execute(text(
        "DELETE FROM step_run WHERE project_id = :pid AND episode_id = :eid"
    ), {"pid": tmp_project_id, "eid": tmp_episode_id})
    session.commit()
    try:
        yield session
    finally:
        try:
            session.execute(text(
                "DELETE FROM step_run WHERE project_id = :pid AND episode_id = :eid"
            ), {"pid": tmp_project_id, "eid": tmp_episode_id})
            session.commit()
        except Exception:
            session.rollback()
        session.close()


@pytest.fixture
def make_step_runner(tmp_project_id, tmp_episode_id, db_session):
    """StepRunner 인스턴스 팩토리. step_id 임의 변경 가능.

    db는 진짜 PG 세션(`theroad_test`). recovery counter 메서드는 raw SQL UPDATE
    이므로 mock으로는 검증 불가. verify/cleanup default 메서드는 DB 미터치라 영향 없음.
    """
    def _make(step_id: str):
        from app.core.step_runner import StepRunner
        return StepRunner(
            step_id=step_id,
            project_id=tmp_project_id,
            episode_id=tmp_episode_id,
            db=db_session,
            project_config={},
        )
    return _make
