"""``_read_process_cmdline`` asks the cheapest source that can answer, and still answers.

The gateway-identity check reads a live PID's command line, and `list_profiles` runs it per profile
with a live gateway — on every 5s roster poll, per connection. On macOS there is no ``/proc``, so
this used to fork ``ps`` every time (measured 4.2ms) when psutil answers the same string in 0.02ms.
psutil cannot always answer (macOS raises ``AccessDenied`` across users), so ``ps`` must remain the
fallback, not be replaced.
"""
from __future__ import annotations

import os
import subprocess
import sys
import time

import pytest

from gateway import status


@pytest.fixture
def no_proc(monkeypatch):
    """Force the non-Linux shape: /proc unreadable, so the source choice is psutil vs ps."""
    real_read_bytes = status.Path.read_bytes

    def _read_bytes(self, *a, **kw):
        if str(self).startswith("/proc/"):
            raise OSError("no /proc")
        return real_read_bytes(self, *a, **kw)

    monkeypatch.setattr(status.Path, "read_bytes", _read_bytes)


def _no_fork(monkeypatch):
    """Fail loudly if anything forks a subprocess."""
    def _boom(*a, **kw):
        raise AssertionError(f"forked a subprocess: {a[0] if a else kw}")

    monkeypatch.setattr(status.subprocess, "run", _boom)


def test_psutil_answers_without_forking_ps(no_proc, monkeypatch):
    _no_fork(monkeypatch)

    cmdline = status._read_process_cmdline(os.getpid())

    assert cmdline and sys.executable.split("/")[-1] in cmdline


def test_ps_still_answers_when_psutil_cannot(no_proc, monkeypatch):
    """macOS raises AccessDenied across users; ps still reports those, so it stays the fallback."""
    import psutil

    def _denied(_pid):
        raise psutil.AccessDenied(_pid)

    monkeypatch.setattr(psutil, "Process", _denied)
    forked: list = []
    real_run = status.subprocess.run

    def _watching(cmd, *a, **kw):
        forked.append(cmd)
        return real_run(cmd, *a, **kw)

    monkeypatch.setattr(status.subprocess, "run", _watching)

    cmdline = status._read_process_cmdline(os.getpid())

    assert cmdline, "the ps fallback must still answer when psutil refuses"
    assert forked and forked[0][:2] == ["ps", "-p"]
