"""Shared fixtures and helpers for `specify self upgrade` tests.

These helpers patch subprocess, PATH lookup, and release-tag resolution so
the focused test modules stay isolated from the real environment.
"""

import os
import subprocess

import pytest
from typer.testing import CliRunner

from specify_cli._version import (
    _InstallMethod,
    _UpgradePlan,
    _assemble_installer_argv,
    _detect_install_method,
    _verify_upgrade,
)
from tests.conftest import strip_ansi
from tests.http_helpers import mock_urlopen_response

__all__ = (
    "SENTINEL_GH_TOKEN",
    "SENTINEL_GITHUB_TOKEN",
    "_InstallMethod",
    "_UpgradePlan",
    "_assemble_installer_argv",
    "_completed_process",
    "_detect_install_method",
    "_verify_upgrade",
    "mock_urlopen_response",
    "requires_posix",
    "runner",
    "strip_ansi",
)

runner = CliRunner()

# Some installer error-path tests create a relative `./uv` fixture, `chdir`
# into the tmp dir, and assert POSIX executable-bit semantics (chmod / X_OK).
# None of that maps cleanly onto Windows: `os.access(path, X_OK)` ignores the
# mode bits, and pytest cannot rmtree a tmp dir that is still the cwd, so the
# fixtures raise PermissionError during teardown. Skip these on Windows — the
# realistic absolute-path and bare-PATH-command branches stay covered there.
requires_posix = pytest.mark.skipif(
    os.name == "nt",
    reason="relative-path / executable-bit semantics are POSIX-only",
)

SENTINEL_GH_TOKEN = "SENTINEL-GH-TOKEN-VALUE"
SENTINEL_GITHUB_TOKEN = "SENTINEL-GITHUB-TOKEN-VALUE"


def _completed_process(
    returncode: int, stdout: str = "", stderr: str = ""
) -> subprocess.CompletedProcess:
    """Build a subprocess.CompletedProcess for installer / verification calls."""
    return subprocess.CompletedProcess(
        args=["mocked"],
        returncode=returncode,
        stdout=stdout,
        stderr=stderr,
    )
