"""Gateway SessionStore must not FTS-repair a replaced state.db (#89332)."""

import json
import os
import shutil

import pytest

from gateway.config import GatewayConfig
from gateway.session import SessionStore
from hermes_state import SessionDB


def _assert_diverted(tmp_path, sid, needle):
    pending = list((tmp_path / "pending_messages").glob("pending-*.json"))
    assert pending, "expected pending_messages/pending-*.json spool"
    spooled = False
    for path in pending:
        payload = json.loads(path.read_text(encoding="utf-8"))
        message = (payload.get("data") or {}).get("message") or {}
        if needle in str(message.get("content", "")):
            spooled = True
            break
    assert spooled, f"{needle!r} missing from pending spool"
    jsonl = tmp_path / "sessions" / f"{sid}.jsonl"
    assert jsonl.is_file()
    assert needle in jsonl.read_text(encoding="utf-8")


@pytest.mark.platforms("posix")
def test_replaced_state_db_diverts_pending_without_fts_rebuild(tmp_path, monkeypatch):
    import hermes_state

    live = tmp_path / "state.db"
    other = tmp_path / "other.db"
    monkeypatch.setenv("HERMES_HOME", str(tmp_path))
    monkeypatch.setattr(hermes_state, "DEFAULT_DB_PATH", live)

    store = SessionStore(sessions_dir=tmp_path, config=GatewayConfig())
    sid = "gw-replaced"
    store._db.create_session(session_id=sid, source="cli")
    store.append_to_transcript(
        sid, {"role": "user", "content": "before", "timestamp": 1.0}
    )
    if store._db._db_file_identity is None:
        store.close_all_db_handles()
        pytest.skip("filesystem does not expose st_dev/st_ino")

    alt = SessionDB(db_path=other)
    alt.create_session("other", "cli")
    alt.close()
    os.replace(other, live)

    store.append_to_transcript(
        sid, {"role": "user", "content": "after-replace", "timestamp": 2.0}
    )

    assert store._db._db_replaced is True
    # No FTS surgery ran on either layer: state-level fail-open never
    # detached, and the gateway one-shot rebuild was not consumed.
    assert store._db._fts_enabled is True
    assert store._db._fts_stale is False
    assert store._fts_rebuild_last_attempt_at is None
    _assert_diverted(tmp_path, sid, "after-replace")
    store.close_all_db_handles()


def test_copyfile_replaced_state_db_diverts_pending_without_fts_rebuild(
    tmp_path, monkeypatch
):
    import hermes_state

    live = tmp_path / "state.db"
    other = tmp_path / "other.db"
    monkeypatch.setenv("HERMES_HOME", str(tmp_path))
    monkeypatch.setattr(hermes_state, "DEFAULT_DB_PATH", live)

    store = SessionStore(sessions_dir=tmp_path, config=GatewayConfig())
    sid = "gw-cp-replaced"
    store._db.create_session(session_id=sid, source="cli")
    store.append_to_transcript(
        sid, {"role": "user", "content": "before-cp", "timestamp": 1.0}
    )
    if not store._db._db_file_application_id:
        store.close_all_db_handles()
        pytest.skip("generation stamp not recorded")

    alt = SessionDB(db_path=other)
    alt.create_session("other", "cli")
    alt.close()
    shutil.copyfile(other, live)

    store.append_to_transcript(
        sid, {"role": "user", "content": "after-cp", "timestamp": 2.0}
    )

    assert store._db._db_replaced is True
    # No FTS surgery ran on either layer: state-level fail-open never
    # detached, and the gateway one-shot rebuild was not consumed.
    assert store._db._fts_enabled is True
    assert store._db._fts_stale is False
    assert store._fts_rebuild_last_attempt_at is None
    _assert_diverted(tmp_path, sid, "after-cp")
    store.close_all_db_handles()
