"""Shared pytest fixtures for the Gitea-Tools test suite."""
import os
import sys

import pytest

sys.path.insert(0, str(__import__("pathlib").Path(__file__).resolve().parent.parent))


@pytest.fixture(autouse=True)
def _reset_mutation_authority(monkeypatch):
    """Isolate the in-process mutation authority between tests (#199).

    The mutation-authority gate stays LIVE in every test — this fixture only
    clears the per-process record and the session profile lock so one test's
    seeded authority (or an intentionally mismatched one) cannot leak into
    the next test. It must never replace verify_mutation_authority with a
    no-op: individual tests that need a specific authority state set it up
    explicitly.

    Session-state isolation (#559 / #590 / #594): many tests use
    ``patch.dict(os.environ, ..., clear=True)``, which drops
    ``GITEA_MCP_SESSION_STATE_DIR``. Relying only on the env var therefore
    re-exposes the operator host cache
    (``~/.cache/gitea-tools/session-state``) and its review-mutation ledger.
    Pin ``default_state_dir`` / ``DEFAULT_STATE_DIR`` to a per-test temp dir
    so durable load/save never touches host state even after env clears.
    """
    import session_context_binding as session_ctx

    # Each pytest item is an independent logical MCP session. Reset both before
    # and after the item; the post-yield reset is in a finally block so an
    # assertion, exception, or unittest teardown failure cannot pollute the
    # next item. Production code has no automatic per-call reset path.
    session_ctx._reset_session_context_for_testing()

    for env_key in [
        "GITEA_SESSION_PROFILE_LOCK",
        "GITEA_ACTIVE_WORKTREE",
        "GITEA_AUTHOR_WORKTREE",
        "GITEA_REVIEWER_WORKTREE",
        "GITEA_MERGER_WORKTREE",
        "GITEA_RECONCILER_WORKTREE",
    ]:
        monkeypatch.delenv(env_key, raising=False)

    # Isolate durable session-state files so tests never share host cache (#559).
    import tempfile

    _state_tmp = tempfile.TemporaryDirectory(prefix="gitea-session-state-")
    state_dir = _state_tmp.name
    monkeypatch.setenv("GITEA_MCP_SESSION_STATE_DIR", state_dir)
    try:
        import mcp_session_state
    except Exception:
        mcp_session_state = None
    if mcp_session_state is not None:
        # Survive patch.dict(..., clear=True) that drops the env var (#590).
        # Still honor an explicit GITEA_MCP_SESSION_STATE_DIR when tests set
        # their own temp dir (see tests/test_mcp_session_state.py).
        monkeypatch.setattr(
            mcp_session_state, "DEFAULT_STATE_DIR", state_dir, raising=False
        )

        def _isolated_default_state_dir(
            _fallback: str = state_dir,
            _env_key: str = mcp_session_state.STATE_DIR_ENV,
        ) -> str:
            # #695 AC2: when production native transport has pinned a session
            # state root, that pin is authoritative even under test isolation
            # (PR #701 redirected-state regression).
            try:
                import mcp_daemon_guard

                pinned = mcp_daemon_guard.pinned_session_state_dir()
                if pinned:
                    return pinned
            except Exception:
                pass
            raw = (os.environ.get(_env_key) or "").strip()
            return raw or _fallback

        monkeypatch.setattr(
            mcp_session_state,
            "default_state_dir",
            _isolated_default_state_dir,
        )
    try:
        import mcp_server
    except Exception:
        try:
            yield
        finally:
            session_ctx._reset_session_context_for_testing()
            _state_tmp.cleanup()
        return
    import gitea_config

    monkeypatch.setattr(gitea_config, "_active_profile_override", None)
    monkeypatch.setattr(mcp_server, "_MUTATION_AUTHORITY", None)
    monkeypatch.setattr(mcp_server, "_IDENTITY_CACHE", {})
    # #714: clear both module namespaces. mcp_server.py execs gitea_mcp_server.py
    # into its own globals, so `import gitea_mcp_server` is a separate module
    # object with its own identity caches; leaving it dirty leaks login across
    # tests that import the implementation module directly.
    try:
        import gitea_mcp_server as _gitea_impl

        monkeypatch.setattr(_gitea_impl, "_IDENTITY_CACHE", {})
        if hasattr(_gitea_impl, "_ACTOR_IDENTITY_CACHE"):
            monkeypatch.setattr(_gitea_impl, "_ACTOR_IDENTITY_CACHE", {})
    except Exception:
        pass
    if hasattr(mcp_server, "_ACTOR_IDENTITY_CACHE"):
        monkeypatch.setattr(mcp_server, "_ACTOR_IDENTITY_CACHE", {})
    monkeypatch.setattr(mcp_server, "_REVIEW_DECISION_LOCK", None)
    monkeypatch.setattr(mcp_server, "_LIVE_NAMESPACE_HEALTH", {})
    monkeypatch.setattr(mcp_server, "_preflight_whoami_called", False)
    monkeypatch.setattr(mcp_server, "_preflight_capability_called", False)
    monkeypatch.setattr(mcp_server, "_preflight_resolved_role", None)
    monkeypatch.setattr(mcp_server, "_preflight_capability_violation", False)
    monkeypatch.setattr(mcp_server, "_preflight_capability_violation_files", [])
    monkeypatch.setattr(mcp_server, "_preflight_capability_baseline_porcelain", None)
    monkeypatch.setattr(mcp_server, "_preflight_resolved_task", None)
    monkeypatch.setattr(mcp_server, "_preflight_reviewer_violation_files", [])
    # Unit tests must not depend on live host MCP process health. Tests that
    # use patch.dict(..., clear=True) drop PYTEST_CURRENT_TEST, which would
    # otherwise re-enable the stale-runtime probe against operator daemons.
    monkeypatch.setattr(
        mcp_server,
        "_check_mcp_runtimes_diagnostics",
        lambda *args, **kwargs: [],
    )
    try:
        import review_workflow_load
        review_workflow_load._REVIEW_WORKFLOW_LOAD = None
    except Exception:
        pass
    try:
        import capability_stop_terminal
        capability_stop_terminal.clear()
    except Exception:
        pass
    try:
        yield
    finally:
        try:
            import capability_stop_terminal
            capability_stop_terminal.clear()
        except Exception:
            pass
        try:
            import review_workflow_load
            review_workflow_load._REVIEW_WORKFLOW_LOAD = None
        except Exception:
            pass
        try:
            mcp_server._REVIEW_DECISION_LOCK = None
        except Exception:
            pass
        gitea_config._active_profile_override = None
        session_ctx._reset_session_context_for_testing()
        _state_tmp.cleanup()


# #714: deterministic workspace remotes only (no host git dependency).
import pytest


@pytest.fixture(autouse=True)
def _deterministic_workspace_remotes():
    try:
        from mutation_profile_fixture import install_deterministic_remote_urls
        install_deterministic_remote_urls()
    except Exception:
        pass
    yield
