"""ORCH-110 TC-07: kill-switches + non-self repo => byte-for-byte pre-ORCH-110.

Covers NFR-2 / FR-5 / AC-7. Each ORCH-110 behaviour is an INDEPENDENT kill-switch;
with a flag off the affected path reverts to the prior behaviour. A non-self-hosting
repo (enduro-trails) never reaches the infra-retry / tree-kill paths at all (the
merge-gate is N/A for it).
"""
import os
import tempfile

os.environ.setdefault("ORCH_DB_PATH", os.path.join(tempfile.gettempdir(), "test_orch110_killswitch.db"))
os.environ.setdefault("ORCH_REPOS_DIR", tempfile.gettempdir())
os.environ.setdefault("ORCH_GITEA_TOKEN", "test-token")
os.environ.setdefault("ORCH_PLANE_API_TOKEN", "test-token")

import pytest  # noqa: E402

from src import merge_gate  # noqa: E402
from src.qg import checks as qg  # noqa: E402
from src.proc_group import ProcResult  # noqa: E402

_REPO = "orchestrator"
_BRANCH = "feature/ORCH-110-x"
_WI = "ORCH-110"


# ---------------------------------------------------------------------------
# D1 kill-switch: subprocess_tree_kill_enabled=False -> the fallback path.
# ---------------------------------------------------------------------------
def test_tc07_tree_kill_off_passes_tree_kill_false(tmp_path, monkeypatch):
    wt = tmp_path / "wt"
    wt.mkdir()
    monkeypatch.setattr(merge_gate, "get_worktree_path", lambda r, b: str(wt))
    monkeypatch.setattr(merge_gate.settings, "subprocess_tree_kill_enabled", False, raising=False)
    captured = {}

    def _fake(cmd, *, cwd, timeout, env=None, grace_s=5.0, tree_kill=True):
        captured["tree_kill"] = tree_kill
        return ProcResult(returncode=0, stdout="1 passed", stderr="", timed_out=False)

    monkeypatch.setattr(merge_gate, "run_in_process_group", _fake)
    ok, reason = merge_gate.retest_branch(_REPO, _BRANCH)
    assert ok is True and reason == "re-test green"
    assert captured["tree_kill"] is False  # -> run_in_process_group degrades to subprocess.run


# ---------------------------------------------------------------------------
# D4 kill-switch: merge_retest_skip_when_current_enabled=False -> always re-test
# after a rebase (even a proven no-op).
# ---------------------------------------------------------------------------
@pytest.fixture
def gate_primitives(monkeypatch):
    calls = {"retest": 0}
    monkeypatch.setattr(qg.settings, "merge_gate_enabled", True, raising=False)
    monkeypatch.setattr(qg.settings, "merge_gate_repos", "", raising=False)
    monkeypatch.setattr(qg.settings, "premerge_rebase_always", True, raising=False)
    monkeypatch.setattr(merge_gate, "acquire_merge_lease", lambda *a, **k: (True, "lease acquired"), raising=False)
    monkeypatch.setattr(merge_gate, "branch_is_behind_main", lambda r, b: True, raising=False)
    monkeypatch.setattr(merge_gate, "auto_rebase_onto_main", lambda r, b: (True, "rebased"), raising=False)
    monkeypatch.setattr(merge_gate, "release_merge_lease", lambda *a, **k: None, raising=False)
    # A PROVEN no-op rebase: HEAD is identical before/after.
    monkeypatch.setattr(merge_gate, "head_sha", lambda r, b: "deadbeefcafe", raising=False)

    def _retest(r, b):
        calls["retest"] += 1
        return True, "re-test green"

    monkeypatch.setattr(merge_gate, "retest_branch", _retest, raising=False)
    return calls


def test_tc07_skip_when_current_off_always_retests(gate_primitives, monkeypatch):
    monkeypatch.setattr(qg.settings, "merge_retest_skip_when_current_enabled", False, raising=False)
    ok, reason = qg.check_branch_mergeable(_REPO, _WI, _BRANCH)
    assert ok is True
    assert reason == "rebased onto main, re-test green"
    assert gate_primitives["retest"] == 1  # re-test STILL runs (D4 off)


def test_tc07_skip_when_current_on_skips_noop_retest(gate_primitives, monkeypatch):
    """Mirror sanity: with the flag ON, the proven no-op rebase skips the re-test."""
    monkeypatch.setattr(qg.settings, "merge_retest_skip_when_current_enabled", True, raising=False)
    ok, reason = qg.check_branch_mergeable(_REPO, _WI, _BRANCH)
    assert ok is True
    assert "re-test skipped" in reason
    assert gate_primitives["retest"] == 0  # re-test NOT run on the no-op


# ---------------------------------------------------------------------------
# Non-self repo (enduro-trails): the merge-gate is N/A -> never the new paths.
# ---------------------------------------------------------------------------
def test_tc07_non_self_repo_is_noop(monkeypatch):
    monkeypatch.setattr(qg.settings, "merge_gate_enabled", True, raising=False)
    monkeypatch.setattr(qg.settings, "merge_gate_repos", "", raising=False)
    # Guard: if the gate wrongly engaged it would touch the lease -> fail loudly.
    monkeypatch.setattr(
        merge_gate, "acquire_merge_lease",
        lambda *a, **k: pytest.fail("merge-gate must be N/A for enduro-trails"),
        raising=False,
    )
    ok, reason = qg.check_branch_mergeable("enduro-trails", "ET-1", "feature/ET-1-x")
    assert ok is True
    assert "N/A" in reason
