"""Server wiring for stable-branch push contamination (#671).

Exercises the MCP tools and the pre-flight enforcement gate against the durable
contamination marker (isolated per-test state dir from conftest).
"""

from __future__ import annotations

import os
from unittest.mock import patch

import gitea_mcp_server as srv


def _clear_marker(remote="prgs"):
    srv._clear_stable_contamination_marker(remote=remote)


def teardown_function():
    _clear_marker()


# ── record tool marks a real direct push ─────────────────────────────────────

def test_record_tool_marks_direct_master_push():
    _clear_marker()
    res = srv.gitea_record_stable_branch_push_attempt(
        command="git push prgs master", remote="prgs"
    )
    assert res["contaminated"] is True
    assert res["marked"] is True
    assert res["marker"] is not None
    assert res["marker"]["reason_class"] == "stable_branch_push"
    # loaded back through the durable store
    loaded = srv._load_stable_contamination_marker("prgs")
    assert loaded is not None
    assert loaded["ref"] == "master"


def test_record_tool_dry_run_still_marks():
    _clear_marker()
    res = srv.gitea_record_stable_branch_push_attempt(
        command="git push --dry-run prgs master", remote="prgs"
    )
    assert res["contaminated"] is True
    assert res["marked"] is True


def test_record_tool_feature_branch_does_not_mark():
    _clear_marker()
    res = srv.gitea_record_stable_branch_push_attempt(
        command="git push prgs fix/issue-671-block-stable-branch-push",
        remote="prgs",
    )
    assert res["contaminated"] is False
    assert res["marked"] is False
    assert srv._load_stable_contamination_marker("prgs") is None


def test_record_tool_fetch_only_does_not_mark():
    _clear_marker()
    res = srv.gitea_record_stable_branch_push_attempt(
        command="git fetch prgs", remote="prgs"
    )
    assert res["contaminated"] is False
    assert res["marked"] is False


def test_record_tool_mark_false_is_readonly():
    _clear_marker()
    res = srv.gitea_record_stable_branch_push_attempt(
        command="git push prgs master", remote="prgs", mark=False
    )
    assert res["contaminated"] is True
    assert res["marked"] is False
    assert srv._load_stable_contamination_marker("prgs") is None


def test_record_tool_redacts_secret_in_marker():
    _clear_marker()
    res = srv.gitea_record_stable_branch_push_attempt(
        command="git push https://u:supersecret@host/o/r.git master",
        remote="prgs",
    )
    assert res["marked"] is True
    assert "supersecret" not in res["marker"]["command_summary"]


def test_record_tool_root_checkout_local_commit_marks():
    _clear_marker()
    res = srv.gitea_record_stable_branch_push_attempt(
        command=None,
        remote="prgs",
        current_branch="master",
        head_sha="a" * 40,
        remote_master_sha="b" * 40,
        is_under_branches=False,
    )
    assert res["contaminated"] is True
    assert res["marked"] is True
    assert res["marker"]["reason_class"] == "root_checkout_commit"


# ── audit tool: inspect + reconciler-only clear ──────────────────────────────

def test_audit_inspect_reports_marker():
    _clear_marker()
    srv.gitea_record_stable_branch_push_attempt(
        command="git push prgs master", remote="prgs"
    )
    out = srv.gitea_audit_stable_branch_contamination(action="inspect", remote="prgs")
    assert out["contaminated"] is True
    assert out["read_only"] is True


def test_audit_clear_refused_for_non_reconciler():
    _clear_marker()
    srv.gitea_record_stable_branch_push_attempt(
        command="git push prgs master", remote="prgs"
    )
    with patch.object(srv, "_actual_profile_role", return_value="author"):
        out = srv.gitea_audit_stable_branch_contamination(action="clear", remote="prgs")
    assert out["success"] is False
    assert out["reasons"]
    # marker survives a refused clear
    assert srv._load_stable_contamination_marker("prgs") is not None


def test_audit_clear_allowed_for_reconciler():
    _clear_marker()
    srv.gitea_record_stable_branch_push_attempt(
        command="git push prgs master", remote="prgs"
    )
    identity = srv._stable_contamination_profile_identity()
    with patch.object(srv, "_actual_profile_role", return_value="reconciler"):
        out = srv.gitea_audit_stable_branch_contamination(
            action="clear", remote="prgs", profile_identity=identity
        )
    assert out["success"] is True
    assert srv._load_stable_contamination_marker("prgs") is None


# ── pre-flight enforcement gate ──────────────────────────────────────────────

def _force_gate_env():
    return patch.dict(os.environ, {"GITEA_TEST_FORCE_STABLE_CONTAMINATION": "1"})


def test_gate_blocks_gated_mutation_when_contaminated():
    _clear_marker()
    srv.gitea_record_stable_branch_push_attempt(
        command="git push prgs master", remote="prgs"
    )
    with _force_gate_env(), patch.object(srv, "_actual_profile_role", return_value="author"):
        for task in ("merge_pr", "review_pr", "close_issue", "create_pr"):
            try:
                srv._enforce_stable_branch_contamination_gate(task, "prgs")
                raised = False
            except RuntimeError as exc:
                raised = True
                assert "#671" in str(exc)
            assert raised, task


def test_gate_allows_comment_for_handoff_when_contaminated():
    _clear_marker()
    srv.gitea_record_stable_branch_push_attempt(
        command="git push prgs master", remote="prgs"
    )
    with _force_gate_env(), patch.object(srv, "_actual_profile_role", return_value="author"):
        # must not raise — worker can still post the durable audit comment
        srv._enforce_stable_branch_contamination_gate("comment_issue", "prgs")
        srv._enforce_stable_branch_contamination_gate("lock_issue", "prgs")


def test_gate_exempts_reconciler_when_contaminated():
    _clear_marker()
    srv.gitea_record_stable_branch_push_attempt(
        command="git push prgs master", remote="prgs"
    )
    with _force_gate_env(), patch.object(srv, "_actual_profile_role", return_value="reconciler"):
        srv._enforce_stable_branch_contamination_gate("merge_pr", "prgs")


def test_gate_noop_when_not_contaminated():
    _clear_marker()
    with _force_gate_env(), patch.object(srv, "_actual_profile_role", return_value="author"):
        srv._enforce_stable_branch_contamination_gate("merge_pr", "prgs")
