"""공유 test DB 수명 — `safe_drop_all` 뒤에도 스키마가 남아야 한다.

## 무엇이 깨져 있었나

`safe_drop_all` 은 **공유** `theroad_test` 의 ORM 테이블 22개를 통째로
지웠다. 그런데 스키마를 세우는 `tests/conftest.py::_ensure_d6_test_db_schema`
는 **session-scope 1회**라 뒤에 일어난 drop 을 못 메운다. 그래서 이 함수를
쓴 파일(16곳) **뒤에 오는 모든 시험**이 없는 테이블을 만났다.

    UndefinedTable: relation "scene_still" does not exist
    UndefinedTable: relation "world_guide" does not exist
    UndefinedTable: table "scene_plan" does not exist

★한 번 걷기에서 **매번 다른 테이블**이 나온다 — 그 시점에 어느 파일이 먼저
돌았느냐가 달라서다. 파일 하나만 돌리면 안 나고 합산에서만 난다. 그래서
「내 수정 탓인가」를 여러 판 헛짚게 만든다. 실제로 그랬다.
"""
from sqlalchemy import inspect


def _orm_tables():
    from app.core.database import Base, register_models

    register_models()
    return set(Base.metadata.tables)


def test_truncating_keeps_the_schema():
    """★행은 비우되 테이블은 남긴다. 되돌리면 22개가 사라진다."""
    from app.core.database import Base, engine
    from tests._safety_guards import safe_drop_all

    want = _orm_tables()
    Base.metadata.create_all(engine)
    safe_drop_all(engine, Base.metadata)
    have = set(inspect(engine).get_table_names())
    assert want - have == set(), f"지워진 테이블 {sorted(want - have)[:6]}"


def test_it_actually_empties_the_rows():
    """★격리는 그대로여야 한다 — 안 비우면 시험끼리 샌다."""
    from sqlalchemy import text

    from app.core.database import Base, engine
    from tests._safety_guards import safe_drop_all

    Base.metadata.create_all(engine)
    with engine.begin() as conn:
        conn.execute(text(
            "INSERT INTO llm_call_log "
            "(id, model_name, user_prompt, status, created_at) "
            "VALUES ('probe-lifetime', 'm', 'p', 'ok', 'now')"))
        assert conn.execute(text(
            "SELECT count(*) FROM llm_call_log WHERE id = 'probe-lifetime'"
        )).scalar() == 1
    safe_drop_all(engine, Base.metadata)
    with engine.begin() as conn:
        n = conn.execute(text(
            "SELECT count(*) FROM llm_call_log WHERE id = 'probe-lifetime'"
        )).scalar()
    assert n == 0, "행을 안 비웠다 — 시험끼리 샌다"


def test_it_still_refuses_a_non_test_database():
    """★production 보호 가드는 그대로다 (2026-04-27 사고 회귀 가드)."""
    import pytest
    from sqlalchemy import create_engine

    from app.core.database import Base
    from tests._safety_guards import safe_drop_all

    prod = create_engine("postgresql://u:p@localhost:5432/theroad")
    with pytest.raises(RuntimeError, match="REFUSING"):
        safe_drop_all(prod, Base.metadata)


def test_it_works_on_sqlite_too():
    """★가드가 sqlite memory 를 허용한다 — 거기서도 돌아야 한다.

    `TRUNCATE … CASCADE` 는 PostgreSQL 것이다. sqlite 에서 그대로 치면
    `OperationalError` 로 선다. 지금 호출부는 전부 PG 지만, 가드가 허용하는
    자리에서 죽으면 다음 사람이 「내 수정 탓」을 먼저 의심한다.
    """
    from sqlalchemy import create_engine, inspect, text

    from app.core.database import Base
    from tests._safety_guards import safe_drop_all

    eng = create_engine("sqlite:///:memory:")
    Base.metadata.create_all(eng)
    with eng.begin() as conn:
        conn.execute(text(
            "INSERT INTO llm_call_log "
            "(id, model_name, user_prompt, status, created_at) "
            "VALUES ('probe-sqlite', 'm', 'p', 'ok', 'now')"))
    safe_drop_all(eng, Base.metadata)
    with eng.begin() as conn:
        assert conn.execute(text("SELECT count(*) FROM llm_call_log")).scalar() == 0
    assert set(Base.metadata.tables) - set(inspect(eng).get_table_names()) == set()
