"""ORCH-073 FR-1 — verify_merged_to_main: SHA-in-main is the SINGLE criterion.

Covers TC-01..04 / AC-2 / AC-6. The former OR-branch `pr_already_merged` was the
phantom-merge root cause and is removed: a merged docs-PR must NOT confirm a merge.
git/HTTP are mocked; the verifier honours the never-raise contract (INV-1).
"""

import pytest

from src import merge_gate


class _R:
    """Minimal completed-subprocess stand-in (returncode only)."""

    def __init__(self, rc):
        self.returncode = rc
        self.stdout = ""
        self.stderr = ""


@pytest.fixture(autouse=True)
def _settings(monkeypatch):
    monkeypatch.setattr(merge_gate.settings, "merge_verify_enabled", True)
    monkeypatch.setattr(merge_gate.settings, "merge_verify_timeout_s", 5)


# ---------------------------------------------------------------------------
# TC-01 (AC-6): sha is an ancestor of origin/main (merge-base rc=0) -> True.
# ---------------------------------------------------------------------------
def test_tc01_true_when_sha_is_ancestor(monkeypatch):
    monkeypatch.setattr(merge_gate, "ensure_worktree", lambda r, b: "/wt")
    calls = []

    def fake_run(cmd, *a, **k):
        calls.append(cmd)
        return _R(0)  # fetch ok; merge-base --is-ancestor -> 0 (ancestor)

    monkeypatch.setattr(merge_gate.subprocess, "run", fake_run)
    assert merge_gate.verify_merged_to_main("orchestrator", "feature/ORCH-073-x", "abc123") is True
    assert any(
        "merge-base" in c and "--is-ancestor" in c and "origin/main" in c for c in calls
    )


# ---------------------------------------------------------------------------
# TC-02 (AC-2): sha NOT in main AND a merged docs-PR exists -> False.
# This is the exact ORCH-067/069 bug: a merged docs-PR must not confirm.
# ---------------------------------------------------------------------------
def test_tc02_false_when_sha_not_in_main_even_with_merged_docs_pr(monkeypatch):
    # A merged docs-PR is present (mock returns True), but it must be IGNORED.
    called = {"pr": False}

    def fake_pr_already_merged(r, b):
        called["pr"] = True
        return True

    monkeypatch.setattr(merge_gate, "pr_already_merged", fake_pr_already_merged)
    monkeypatch.setattr(merge_gate, "ensure_worktree", lambda r, b: "/wt")
    monkeypatch.setattr(
        merge_gate.subprocess, "run",
        lambda cmd, *a, **k: _R(1) if "merge-base" in cmd else _R(0),
    )
    assert merge_gate.verify_merged_to_main("orchestrator", "feature/ORCH-073-x", "abc123") is False
    # The merged-PR signal is no longer consulted by the verifier at all.
    assert called["pr"] is False


# ---------------------------------------------------------------------------
# TC-03: empty sha -> inconclusive -> False (fail-closed), no git consulted.
# ---------------------------------------------------------------------------
def test_tc03_empty_sha_is_false(monkeypatch):
    def boom(*a, **k):
        raise AssertionError("git must NOT run for an empty SHA")

    monkeypatch.setattr(merge_gate, "ensure_worktree", boom)
    monkeypatch.setattr(merge_gate.subprocess, "run", boom)
    assert merge_gate.verify_merged_to_main("orchestrator", "feature/ORCH-073-x", "") is False


# ---------------------------------------------------------------------------
# TC-04 (INV-1): a git/OS error -> False, exception never propagated.
# ---------------------------------------------------------------------------
def test_tc04_never_raises_on_git_error(monkeypatch):
    monkeypatch.setattr(merge_gate, "ensure_worktree", lambda r, b: "/wt")

    def boom(*a, **k):
        raise OSError("git exploded")

    monkeypatch.setattr(merge_gate.subprocess, "run", boom)
    assert merge_gate.verify_merged_to_main("orchestrator", "feature/ORCH-073-x", "abc123") is False


def test_tc04_never_raises_on_worktree_error(monkeypatch):
    def boom(*a, **k):
        raise RuntimeError("worktree down")

    monkeypatch.setattr(merge_gate, "ensure_worktree", boom)
    assert merge_gate.verify_merged_to_main("orchestrator", "feature/ORCH-073-x", "abc123") is False
