"""Tests for the local-release runner."""

from __future__ import annotations

import json
import os
import shutil
import subprocess
import zipfile
from pathlib import Path

import pytest

from mgf.fed import _release
from mgf.fed._release import (
    ReleaseResult,
    _validate_wheel,
    _version,
    release_local,
    release_remote,
)


def test_version_reads_pyproject(tmp_path: Path) -> None:
    (tmp_path / "pyproject.toml").write_text('[project]\nname = "x"\nversion = "1.2.3"\n')
    assert _version(tmp_path) == "1.2.3"


def test_validate_wheel(tmp_path: Path) -> None:
    good = tmp_path / "mgf_x-1.2.3-py3-none-any.whl"
    with zipfile.ZipFile(good, "w") as z:
        z.writestr("mgf/x/py.typed", "")
    assert _validate_wheel(good, "1.2.3") == (True, "")
    ok, detail = _validate_wheel(good, "9.9.9")
    assert not ok and "version" in detail

    no_typed = tmp_path / "mgf_y-1.0.0-py3-none-any.whl"
    with zipfile.ZipFile(no_typed, "w") as z:
        z.writestr("mgf/y/__init__.py", "")
    ok, detail = _validate_wheel(no_typed, "1.0.0")
    assert not ok and "py.typed" in detail


def _root(tmp_path: Path) -> Path:
    reg = {
        "release_waves": [["mgf-a"], ["mgf-b"]],
        "libraries": [
            {"repo": "mgf-a", "lang": "python", "version": "1.0.0"},
            {"repo": "mgf-b", "lang": "python", "version": "2.0.0"},
        ],
    }
    (tmp_path / "mgf-standard").mkdir()
    (tmp_path / "mgf-standard" / "MGF_LIBRARIES.json").write_text(json.dumps(reg), encoding="utf-8")
    for r in ("mgf-a", "mgf-b"):
        (tmp_path / r).mkdir()
    return tmp_path


def test_release_local_runs_in_wave_order(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
    monkeypatch.setattr(_release.shutil, "which", lambda _n: "/usr/bin/uv")
    monkeypatch.setattr(_release, "_find_ruff", lambda: None)
    seen: list[str] = []

    def _fake_one(m: object, uv: str, ruff: str | None) -> ReleaseResult:
        repo = m.repo  # type: ignore[attr-defined]
        seen.append(repo)
        return ReleaseResult(repo, "1.0.0", "publish", True, "ok")

    monkeypatch.setattr(_release, "_release_one", _fake_one)
    rc = release_local(["mgf-b", "mgf-a"], root=_root(tmp_path))  # arg order reversed
    assert rc == 0
    assert seen == ["mgf-a", "mgf-b"]  # processed in WAVE order, not arg order
    assert "2/2 published" in capsys.readouterr().out


def test_release_local_no_uv(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setattr(_release.shutil, "which", lambda _n: None)
    assert release_local(["mgf-a"]) == 2


def test_release_remote_dry_run(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
    # The REL-13 gate is exercised by its own tests; here it must not stand between
    # this test and the publish path it is named for. In CI there is no mgf-standard
    # checkout, so the real gate returns "cannot verify" and refuses — correctly.
    monkeypatch.setattr(_release, "federation_gate", lambda root=None: (True, "GREEN"))
    monkeypatch.setattr(_release.shutil, "which", lambda _n: "/usr/bin/uv")
    monkeypatch.setattr(_release, "_local_wheel", lambda repo, ver: tmp_path / f"{repo}.whl")
    monkeypatch.setattr(_release, "_git", lambda args, cwd: (True, ""))
    monkeypatch.setattr(_release, "_devpi_has", lambda pkg, ver: False)
    rc = release_remote(["mgf-a"], dry_run=True, root=_root(tmp_path))
    out = capsys.readouterr().out
    assert rc == 0 and "would tag" in out and "on devpi" in out


def test_release_remote_already_published_is_noop(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
    # The REL-13 gate is exercised by its own tests; here it must not stand between
    # this test and the publish path it is named for. In CI there is no mgf-standard
    # checkout, so the real gate returns "cannot verify" and refuses — correctly.
    monkeypatch.setattr(_release, "federation_gate", lambda root=None: (True, "GREEN"))
    monkeypatch.setattr(_release.shutil, "which", lambda _n: "/usr/bin/uv")
    monkeypatch.setattr(_release, "_local_wheel", lambda repo, ver: tmp_path / f"{repo}.whl")
    monkeypatch.setattr(_release, "_git", lambda args, cwd: (True, ""))
    monkeypatch.setattr(_release, "_devpi_has", lambda pkg, ver: True)
    monkeypatch.setenv(_release.DEVPI_PASSWORD_ENV, "pw")
    rc = release_remote(["mgf-a"], root=_root(tmp_path))
    assert rc == 0 and "already published" in capsys.readouterr().out


def test_release_remote_requires_local_release_first(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
    monkeypatch.setattr(_release.shutil, "which", lambda _n: "/usr/bin/uv")
    monkeypatch.setattr(_release, "_local_wheel", lambda repo, ver: None)
    monkeypatch.setenv(_release.DEVPI_PASSWORD_ENV, "pw")
    rc = release_remote(["mgf-a"], root=_root(tmp_path))
    assert rc == 1 and "run `release-local" in capsys.readouterr().out


def test_release_remote_no_password_no_dry_run(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
    monkeypatch.setattr(_release.shutil, "which", lambda _n: "/usr/bin/uv")
    monkeypatch.delenv(_release.DEVPI_PASSWORD_ENV, raising=False)
    assert release_remote(["mgf-a"], dry_run=False, root=_root(tmp_path)) == 2
    assert "DEVPI_PASSWORD" in capsys.readouterr().out


def _member(tmp_path: Path, repo: str = "mgf-x", version: str = "1.0.0"):
    from mgf.fed._roster import Member

    d = tmp_path / repo
    d.mkdir()
    (d / "pyproject.toml").write_text(f'[project]\nname = "{repo}"\nversion = "{version}"\n')
    return Member(repo=repo, lang="python", registry_version=version, root=tmp_path)


def test_release_one_publishes(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
    m = _member(tmp_path)
    monkeypatch.setattr(_release, "_run", lambda *a, **k: (True, ""))
    monkeypatch.setattr(
        _release, "_newest_wheel", lambda d, v: tmp_path / "mgf_x-1.0.0-py3-none-any.whl"
    )
    monkeypatch.setattr(_release, "_validate_wheel", lambda w, v: (True, ""))
    monkeypatch.setattr(_release._index, "publish", lambda w: tmp_path / "idx" / Path(w).name)
    res = _release._release_one(m, "/usr/bin/uv", None)  # ruff=None → gate skipped
    assert res.ok and res.reached == "publish"


def test_release_one_build_fail(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
    m = _member(tmp_path)
    monkeypatch.setattr(
        _release, "_run", lambda args, cwd=None: (False, "boom") if "build" in args else (True, "")
    )
    res = _release._release_one(m, "/usr/bin/uv", None)
    assert not res.ok and res.reached == "build"


def test_release_remote_one_publishes_and_verifies(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
    # The REL-13 gate is exercised by its own tests; here it must not stand between
    # this test and the publish path it is named for. In CI there is no mgf-standard
    # checkout, so the real gate returns "cannot verify" and refuses — correctly.
    monkeypatch.setattr(_release, "federation_gate", lambda root=None: (True, "GREEN"))
    m = _member(tmp_path)
    monkeypatch.setattr(
        _release, "_local_wheel", lambda r, v: tmp_path / "mgf_x-1.0.0-py3-none-any.whl"
    )
    monkeypatch.setattr(_release, "_git", lambda a, c: (True, ""))
    seen: list[int] = []

    def _has(_p: str, _v: str) -> bool:
        seen.append(1)
        return len(seen) > 1  # 1st (pre-req) absent → publish; 2nd (verify) present

    monkeypatch.setattr(_release, "_devpi_has", _has)
    monkeypatch.setattr(_release, "_run", lambda *a, **k: (True, ""))  # uv publish
    res = _release._release_remote_one(m, "pw", "/usr/bin/uv", dry_run=False)
    assert res.ok and res.reached == "publish"


# --- §3.5: the publish target + auth shape derive from $DEVPI_URL ---------------


def test_upload_url_and_user_derived_from_devpi_url(monkeypatch: pytest.MonkeyPatch) -> None:
    """URL/auth derivation (re-pinned target contract): the upload endpoint is the
    index root ($DEVPI_URL minus the `+simple` tail — the CI publish step's
    ${DEVPI_URL%%+simple*} derivation) and the upload account is the index's owner
    segment (magogi/prod → magogi)."""
    monkeypatch.setenv("DEVPI_URL", "https://example.test/alice/dev/+simple/")
    assert _release._upload_url() == "https://example.test/alice/dev/"
    assert _release._upload_user() == "alice"
    monkeypatch.delenv("DEVPI_URL", raising=False)  # the documented default
    assert _release._upload_url().endswith("/magogi/prod/")
    assert "+simple" not in _release._upload_url()
    assert _release._upload_user() == "magogi"


def test_release_remote_one_uploads_to_devpi_index_root_with_env_auth(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
    """The upload is `uv publish --publish-url <index root>` with the account/password
    passed via UV_PUBLISH_* env — the password NEVER appears in argv (SC-11)."""
    # The REL-13 gate is exercised by its own tests; here it must not stand between
    # this test and the publish path it is named for. In CI there is no mgf-standard
    # checkout, so the real gate returns "cannot verify" and refuses — correctly.
    monkeypatch.setattr(_release, "federation_gate", lambda root=None: (True, "GREEN"))
    monkeypatch.setenv("DEVPI_URL", "https://example.test/magogi/prod/+simple/")
    m = _member(tmp_path)
    monkeypatch.setattr(
        _release, "_local_wheel", lambda r, v: tmp_path / "mgf_x-1.0.0-py3-none-any.whl"
    )
    monkeypatch.setattr(_release, "_git", lambda a, c: (True, ""))
    monkeypatch.setattr(_release, "_devpi_has", lambda p, v: False)
    calls: list[tuple[list[str], dict[str, str] | None]] = []

    def _run(args: list[str], cwd: str | None = None, env: dict[str, str] | None = None):
        calls.append((args, env))
        return True, ""

    monkeypatch.setattr(_release, "_run", _run)
    _release._release_remote_one(m, "s3cret", "/usr/bin/uv", dry_run=False)
    publish = next(c for c in calls if c[0][:2] == ["/usr/bin/uv", "publish"])
    args, env = publish
    assert args[args.index("--publish-url") + 1] == "https://example.test/magogi/prod/"
    assert env is not None
    assert env["UV_PUBLISH_USERNAME"] == "magogi"
    assert env["UV_PUBLISH_PASSWORD"] == "s3cret"  # noqa: S105 — test fixture value
    assert "s3cret" not in " ".join(args)  # never argv (SC-11)


def test_devpi_has_reads_the_simple_listing(monkeypatch: pytest.MonkeyPatch) -> None:
    """PKG-05: presence == the +simple listing serves the version. The match is the
    wheel-name shape `-<version>-`, so 0.1.1 never false-positives on 0.1.10; a 404
    project page is False (absent); a network error is None (unknown)."""
    import io
    import urllib.error

    class _Resp(io.BytesIO):
        def __enter__(self) -> _Resp:
            return self

        def __exit__(self, *a: object) -> None:
            self.close()

    served = {"url": ""}

    def _fake_urlopen(url: str, timeout: int = 0) -> _Resp:
        served["url"] = url
        return _Resp(b'<a href="x/mgf_x-0.1.10-py3-none-any.whl">mgf_x-0.1.10</a>')

    monkeypatch.setenv("DEVPI_URL", "https://example.test/magogi/prod/+simple/")
    monkeypatch.setattr(_release.urllib.request, "urlopen", _fake_urlopen)
    assert _release._devpi_has("mgf-x", "0.1.10") is True
    assert served["url"] == "https://example.test/magogi/prod/+simple/mgf-x/"
    assert _release._devpi_has("mgf-x", "0.1.1") is False  # no substring false-positive

    def _boom_404(url: str, timeout: int = 0) -> _Resp:
        raise urllib.error.HTTPError(url, 404, "not found", None, None)  # type: ignore[arg-type]

    monkeypatch.setattr(_release.urllib.request, "urlopen", _boom_404)
    assert _release._devpi_has("mgf-x", "0.1.10") is False

    def _boom_net(url: str, timeout: int = 0) -> _Resp:
        raise urllib.error.URLError("unreachable")

    monkeypatch.setattr(_release.urllib.request, "urlopen", _boom_net)
    assert _release._devpi_has("mgf-x", "0.1.10") is None


# --- SC-11: the publish token must never reach a log/argv ---------------------
def test_redact_cmd_strips_secret_flag_values() -> None:
    leaked = (
        "Command '['uv', 'publish', '--password', 'SECRET_TOKEN', 'x.whl']' "
        "timed out after 600 seconds"
    )
    out = _release._redact_cmd(leaked)
    assert "SECRET_TOKEN" not in out
    assert "<redacted>" in out


def test_run_does_not_leak_secret_on_subprocess_failure(monkeypatch: pytest.MonkeyPatch) -> None:
    import subprocess

    def _boom(*_a: object, **_k: object) -> None:
        raise subprocess.TimeoutExpired(["uv", "publish", "--password", "SECRET_TOKEN"], 600)

    monkeypatch.setattr(_release.subprocess, "run", _boom)
    ok, detail = _release._run(["uv", "publish", "--password", "SECRET_TOKEN"])
    assert ok is False
    assert "SECRET_TOKEN" not in detail


# ── REL-13 in an exit code, not a checklist ──────────────────────────────────
# On 2026-08-09 mgf-common 0.52.0 was tagged and uploaded to a NON-VOLATILE index
# with the federation gate RED and the REL-10 cohort wave not started: for 67
# minutes four siblings' declared windows excluded a version any `pip install -U`
# would resolve. Nothing stopped it, because the rule lived only in RELEASING §8.


def _member(tmp_path, repo="mgf-x", version="1.2.3"):
    from mgf.fed._roster import Member

    d = tmp_path / repo
    d.mkdir(parents=True, exist_ok=True)
    (d / "pyproject.toml").write_text(f'[project]\nname = "{repo}"\nversion = "{version}"\n')
    return Member(repo=repo, lang="python", registry_version=version, root=tmp_path)


def test_release_remote_refuses_while_the_federation_gate_is_red(tmp_path, monkeypatch):
    m = _member(tmp_path)
    monkeypatch.setattr(_release, "_local_wheel", lambda r, v: tmp_path / "w.whl")
    monkeypatch.setattr(_release, "_git", lambda a, cwd: (True, ""))
    monkeypatch.setattr(
        _release, "federation_gate", lambda root=None: (False, "REL-13 gate RED: x")
    )
    res = _release._release_remote_one(m, "pw", "uv", dry_run=False)
    assert res.ok is False
    assert res.reached == "pre-req"
    assert "RED" in res.detail and "irreversible" in res.detail


def test_release_remote_refuses_when_the_gate_CANNOT_BE_RUN(tmp_path, monkeypatch):
    """ "Could not verify" must not share an outcome with "verified" — the estate's rule."""
    m = _member(tmp_path)
    monkeypatch.setattr(_release, "_local_wheel", lambda r, v: tmp_path / "w.whl")
    monkeypatch.setattr(_release, "_git", lambda a, cwd: (True, ""))
    monkeypatch.setattr(
        _release, "federation_gate", lambda root=None: (None, "generator not found")
    )
    res = _release._release_remote_one(m, "pw", "uv", dry_run=False)
    assert res.ok is False
    assert "cannot verify" in res.detail


def test_the_override_is_explicit_and_still_publishes(tmp_path, monkeypatch):
    """The override exists so a deliberate publish is possible — but it must be asked for."""
    m = _member(tmp_path)
    monkeypatch.setattr(_release, "_local_wheel", lambda r, v: tmp_path / "w.whl")
    monkeypatch.setattr(_release, "_git", lambda a, cwd: (True, ""))
    monkeypatch.setattr(_release, "_devpi_has", lambda r, v: False)
    called: list[bool] = []
    monkeypatch.setattr(
        _release, "federation_gate", lambda root=None: (called.append(True), (False, "RED"))[1]
    )
    res = _release._release_remote_one(m, "pw", "uv", dry_run=True, skip_federation_gate=True)
    assert called == [], "the gate must not even be consulted when explicitly skipped"
    assert res.ok is True


def test_artefacts_promotes_the_sdist_beside_the_wheel(tmp_path):
    """`uv publish str(wheel)` promoted NO sdist; every prior release had one only
    because the tag pipeline happened to publish it too."""
    d = tmp_path / "dist"
    d.mkdir()
    wheel = d / "mgf_x-1.2.3-py3-none-any.whl"
    wheel.touch()
    (d / "mgf_x-1.2.3.tar.gz").touch()
    (d / "mgf_x-1.2.2.tar.gz").touch()  # a stale sdist must NOT ride along
    got = [Path(p).name for p in _release._artefacts(wheel)]
    assert got == ["mgf_x-1.2.3-py3-none-any.whl", "mgf_x-1.2.3.tar.gz"], got


def test_release_local_builds_the_sdist_too(tmp_path, monkeypatch):
    """Pins the CALL SITE, not just the helper: `uv build --wheel` is what left
    release-remote with no sdist to promote, and a helper nobody invokes is a
    check that does not exist."""
    m = _member(tmp_path)
    seen: list[list[str]] = []

    def fake_run(args, cwd=None, env=None):
        seen.append(list(args))
        return (False, "stop here")  # fail fast; we only care about the build argv

    monkeypatch.setattr(_release, "_run", fake_run)
    monkeypatch.setattr(_release, "_lint_dirs", lambda d: [])
    _release._release_one(m, "uv", None)
    build = [a for a in seen if a[:2] == ["uv", "build"]]
    assert build, seen
    assert "--wheel" not in build[0], "must build BOTH wheel and sdist"


def test_release_remote_publishes_the_sdist_beside_the_wheel(tmp_path, monkeypatch):
    """Pins that `_artefacts` is actually wired into the publish argv."""
    m = _member(tmp_path)
    dist = tmp_path / "dist"
    dist.mkdir()
    wheel = dist / "mgf_x-1.2.3-py3-none-any.whl"
    wheel.touch()
    (dist / "mgf_x-1.2.3.tar.gz").touch()

    monkeypatch.setattr(_release, "_local_wheel", lambda r, v: wheel)
    monkeypatch.setattr(_release, "_git", lambda a, cwd: (True, ""))
    monkeypatch.setattr(_release, "_devpi_has", lambda r, v: False)
    monkeypatch.setattr(_release, "federation_gate", lambda root=None: (True, "GREEN"))
    seen: list[list[str]] = []

    def fake_run(args, cwd=None, env=None):
        seen.append(list(args))
        return (False, "stop after publish")

    monkeypatch.setattr(_release, "_run", fake_run)
    _release._release_remote_one(m, "pw", "uv", dry_run=False)
    pub = [a for a in seen if "publish" in a]
    assert pub, seen
    assert any(x.endswith(".tar.gz") for x in pub[0]), f"sdist not published: {pub[0]}"
    assert any(x.endswith(".whl") for x in pub[0])


# --- preflight: `dist/` must be ours to clear before we build into it -----------
#
# `_clear_dist` replaced `shutil.rmtree(dist, ignore_errors=True)`. These tests are
# deliberately uid-INDEPENDENT: CI runs as **root**, and root bypasses the very
# permission checks a chmod-based test would rely on, so such a test passes there
# whatever the code does. The one test that does use real permissions is skipped
# under uid 0 and states why.


def _fake_access(unwritable: Path):
    """`os.access` that denies write on `unwritable` and everything under it."""
    real = os.access

    def _access(path, mode, **kw):
        p = Path(path)
        if mode & os.W_OK and (p == unwritable or unwritable in p.parents):
            return False
        return real(path, mode, **kw)

    return _access


def test_clear_dist_removes_a_clean_dist(tmp_path: Path) -> None:
    dist = tmp_path / "dist"
    (dist / "sub").mkdir(parents=True)
    (dist / "sub" / "old-0.1.0.whl").write_text("stale")
    assert _release._clear_dist(tmp_path) is None
    assert not dist.exists()


def test_clear_dist_is_fine_when_there_is_no_dist(tmp_path: Path) -> None:
    assert _release._clear_dist(tmp_path) is None


def test_clear_dist_unlinks_a_dist_that_is_a_file(tmp_path: Path) -> None:
    (tmp_path / "dist").write_text("not a directory")
    assert _release._clear_dist(tmp_path) is None
    assert not (tmp_path / "dist").exists()


def test_clear_dist_reports_the_stuck_dir_its_owner_and_the_fix(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
    """The whole point of the change: a real reason instead of a silent no-op."""
    dist = tmp_path / "dist"
    (dist / "root-owned").mkdir(parents=True)
    (dist / "root-owned" / "x.whl").write_text("x")

    def _boom(_p):
        raise PermissionError(13, "Permission denied")

    monkeypatch.setattr(_release.shutil, "rmtree", _boom)
    monkeypatch.setattr(os, "access", _fake_access(dist))

    reason = _release._clear_dist(tmp_path)
    assert reason is not None
    assert "cannot clear" in reason
    assert "dist" in reason
    assert "owner" in reason  # names who holds it, so the fix is obvious
    assert f"sudo rm -rf {dist}" in reason  # ...and the exact command


def test_clear_dist_falls_back_when_the_failure_is_not_permissions(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
    """`could not verify` must not masquerade as the permissions diagnosis."""
    (tmp_path / "dist").mkdir()

    def _boom(_p):
        raise OSError(5, "Input/output error")

    monkeypatch.setattr(_release.shutil, "rmtree", _boom)
    reason = _release._clear_dist(tmp_path)
    assert reason is not None
    assert "Input/output error" in reason
    assert "sudo rm -rf" not in reason  # wrong advice for an I/O fault


def test_clear_dist_refuses_when_the_repo_dir_itself_is_unwritable(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
    monkeypatch.setattr(os, "access", _fake_access(tmp_path))
    reason = _release._clear_dist(tmp_path)
    assert reason is not None and "cannot create dist/" in reason


def test_unremovable_does_not_double_report_below_a_stuck_dir(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
    dist = tmp_path / "dist"
    (dist / "a" / "b" / "c").mkdir(parents=True)
    monkeypatch.setattr(os, "access", _fake_access(dist / "a"))
    stuck = _release._unremovable(dist)
    assert stuck == [dist / "a"], stuck  # not a, a/b, a/b/c


def test_release_one_refuses_at_preflight_and_never_builds(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
    """The gate must REFUSE, not warn: `uv build` is never reached.

    Building anyway is how `_newest_wheel` picks up a *previous* run's artifact for
    this same version and publishes it — and devpi is non-volatile (PKG-07), so that
    is unrecoverable.
    """
    m = _member(tmp_path)
    ran: list[list[str]] = []

    def _record(args, cwd=None, env=None):
        ran.append(args)
        return True, ""

    monkeypatch.setattr(_release, "_run", _record)
    monkeypatch.setattr(_release, "_clear_dist", lambda d: "cannot clear dist: mocked")

    res = _release._release_one(m, "/usr/bin/uv", None)
    assert not res.ok and res.reached == "preflight"
    assert "mocked" in res.detail
    assert ran == [], f"uv was invoked despite the preflight refusing: {ran}"


@pytest.mark.skipif(
    os.geteuid() == 0, reason="root bypasses the permission bits this test relies on"
)
def test_clear_dist_against_real_permissions(tmp_path: Path) -> None:
    """The uid-independent tests above mock `os.access`; this one proves the real
    thing behaves the same way on a real filesystem."""
    dist = tmp_path / "dist"
    stuck = dist / "stuck"
    stuck.mkdir(parents=True)
    (stuck / "artifact.whl").write_text("x")
    stuck.chmod(0o500)  # r-x: cannot unlink what is inside it
    try:
        reason = _release._clear_dist(tmp_path)
        assert reason is not None, "a directory we cannot empty was reported as cleared"
        assert "stuck" in reason
        assert dist.exists()
    finally:
        stuck.chmod(0o700)


#: The house marker (test_origin_view.py). These drive a REAL git repo, and the
#: `mgf-common-matrix` CI step runs an image with no git — which is exactly how
#: this branch went red after passing locally.
requires_git = pytest.mark.skipif(
    shutil.which("git") is None, reason="git not on PATH (e.g. the slim CI image)"
)


# --- PAPER-130: main vs the published artifact ---------------------------------
#
# `mgf-alembic`'s main sat 28 commits past `v0.4.10` while still declaring
# `0.4.10`, so the published 0.4.10 and main's 0.4.10 were DIFFERENT CODE under
# the same number — and the registry check passed, because it compares
# declared-vs-registry and neither had moved.


def _repo_with_tag(tmp_path: Path, version: str = "1.0.0") -> Path:
    d = tmp_path / "r"
    (d / "src" / "pkg").mkdir(parents=True)
    (d / "pyproject.toml").write_text(f'[project]\nname = "r"\nversion = "{version}"\n')
    (d / "src" / "pkg" / "__init__.py").write_text("x = 1\n")
    for args in (
        ["init", "-q", str(d)],
        ["-C", str(d), "config", "user.email", "t@t"],
        ["-C", str(d), "config", "user.name", "t"],
        ["-C", str(d), "add", "-A"],
        ["-C", str(d), "commit", "-q", "--no-verify", "-m", "seed"],
        ["-C", str(d), "tag", f"v{version}"],
    ):
        subprocess.run(  # noqa: S603 — fixed git argv over a tmp_path fixture
            ["git", *args],  # noqa: S607
            check=True,
            capture_output=True,
        )
    return d


def _commit(d: Path, rel: str, body: str) -> None:
    p = d / rel
    p.parent.mkdir(parents=True, exist_ok=True)
    p.write_text(body)
    for args in (["add", "-A"], ["commit", "-q", "--no-verify", "-m", f"touch {rel}"]):
        subprocess.run(  # noqa: S603 — fixed git argv over a tmp_path fixture
            ["git", "-C", str(d), *args],  # noqa: S607
            check=True,
            capture_output=True,
        )


@requires_git
def test_currency_passes_when_the_tag_matches(tmp_path: Path) -> None:
    ok, detail = _release.release_currency(_repo_with_tag(tmp_path), "1.0.0")
    assert ok and "matches HEAD" in detail


@requires_git
def test_currency_refuses_when_SOURCE_moved_past_the_tag(tmp_path: Path) -> None:
    d = _repo_with_tag(tmp_path)
    _commit(d, "src/pkg/thing.py", "y = 2\n")
    ok, detail = _release.release_currency(d, "1.0.0")
    assert not ok
    assert "src/pkg/thing.py" in detail and "already taken" in detail


@requires_git
def test_currency_refuses_when_pyproject_moved(tmp_path: Path) -> None:
    """A dependency or licence change is installable content — this is the class
    that shipped `License: MIT` wheels after the relicence."""
    d = _repo_with_tag(tmp_path)
    _commit(d, "pyproject.toml", '[project]\nname = "r"\nversion = "1.0.0"\ndependencies = ["x"]\n')
    ok, detail = _release.release_currency(d, "1.0.0")
    assert not ok and "pyproject.toml" in detail


@requires_git
@pytest.mark.parametrize(
    "path",
    [
        "docs/guide.md",
        "CHANGELOG.md",
        "fed-resources/generated/architecture.json",
        "pending-feedback/mgf-common.md",
        "tests/unit/test_x.py",
        ".woodpecker.yml",
    ],
)
def test_currency_ignores_what_a_consumer_never_installs(tmp_path: Path, path: str) -> None:
    """The recorded failure of the tool this replaces: `verify_release_currency.py`
    reported 28 drifted distributions of which **26 were false positives**, all of
    them generated or non-shipped files. A gate that cries wolf is a gate ignored."""
    d = _repo_with_tag(tmp_path)
    _commit(d, path, "noise\n")
    ok, _ = _release.release_currency(d, "1.0.0")
    assert ok, f"{path} is not installable content and must not block a release"


@requires_git
def test_currency_passes_when_there_is_no_tag_yet(tmp_path: Path) -> None:
    """A version with no tag is the normal pre-release state, not drift. Blocking
    it would make the FIRST release of every version impossible."""
    d = _repo_with_tag(tmp_path, "1.0.0")
    ok, detail = _release.release_currency(d, "2.0.0")
    assert ok and "no tag" in detail


@requires_git
def test_currency_REFUSES_when_it_cannot_compare(tmp_path: Path, monkeypatch) -> None:
    """ "I could not check" must not pass — that is the whole defect one level up."""
    d = _repo_with_tag(tmp_path)
    real = _release._git

    def fake(args, cwd=None):
        if args[:1] == ["diff"]:
            return False, "boom"
        return real(args, cwd)

    monkeypatch.setattr(_release, "_git", fake)
    ok, detail = _release.release_currency(d, "1.0.0")
    assert not ok and "cannot compare" in detail


def test_release_remote_refuses_before_tagging(tmp_path: Path, monkeypatch) -> None:
    """The gate must sit BEFORE the tag: the tag over drifted source IS the lie,
    and devpi is non-volatile so nothing after it is recoverable."""
    m = _member(tmp_path)
    monkeypatch.setattr(_release, "federation_gate", lambda root=None: (True, "GREEN"))
    monkeypatch.setattr(_release, "_local_wheel", lambda r, v: tmp_path / "w.whl")
    monkeypatch.setattr(_release, "release_currency", lambda d, v: (False, "drifted"))
    tagged: list[list[str]] = []
    monkeypatch.setattr(_release, "_git", lambda a, c=None: (tagged.append(a), (True, ""))[1])
    res = _release._release_remote_one(m, "pw", "uv", dry_run=False)
    assert not res.ok and "release currency" in res.detail
    assert not any(a[:1] == ["tag"] for a in tagged), f"tagged despite drift: {tagged}"
