"""Cross-platform subprocess-launch helpers shared by tests.

Lives outside ``conftest.py`` so it can be imported as a regular module from
both the integration-test conftest *and* lightweight unit tests that exist
purely to assert the helper's contract on each platform — see issue #55.

Keeping the helper here (rather than inline in ``conftest.py``) means a
single source of truth for the Windows ``CREATE_NO_WINDOW`` value the suite
applies to spawned subprocesses, and lets POSIX CI cover the no-op branch
without needing the integration harness to be enabled.
"""

from __future__ import annotations

import sys

from tests import process

# Documented value of the Win32 ``CREATE_NO_WINDOW`` process-creation flag.
# We hard-code it here (rather than only relying on ``process.CREATE_NO_WINDOW``)
# so the unit test can assert the *exact* bit pattern even when the test is
# running off-Windows where the attribute does not exist.
CREATE_NO_WINDOW: int = 0x0800_0000
CREATE_NEW_PROCESS_GROUP: int = 0x0000_0200


def windows_no_window_flags() -> dict[str, int]:
    """Return ``{"creationflags": CREATE_NO_WINDOW}`` on Windows, ``{}`` else.

    Use this helper when launching a piped, non-interactive child process
    from the test suite (or from any harness code that wants to suppress
    Windows' default conhost allocation). On POSIX the returned dict is
    empty, so spreading ``**windows_no_window_flags()`` into a
    ``process.Popen``/``process.run`` call is a portable no-op.

    See issue #55: every subprocess the integration suite spawns on Windows
    (clud, mock agents, daemon helpers, attach clients) inherits Windows'
    default of allocating a fresh console window — each one a visible flash
    that steals focus from the developer's editor during a ``pytest`` run.
    Setting CREATE_NO_WINDOW on the parent's CreateProcess call suppresses
    the allocation for piped/non-interactive children without changing any
    other launch semantics.
    """
    if sys.platform != "win32":
        return {}
    # ``getattr`` keeps the helper safe on hypothetical Python builds where
    # ``process.CREATE_NO_WINDOW`` was not exposed; the documented bit
    # pattern is the source of truth.
    return {"creationflags": getattr(process, "CREATE_NO_WINDOW", CREATE_NO_WINDOW)}


def add_windows_create_no_window(kwargs: dict) -> None:
    """Add ``CREATE_NO_WINDOW`` to ordinary Windows subprocess launches.

    Leave ``CREATE_NEW_PROCESS_GROUP`` launches alone: those tests send
    ``CTRL_BREAK_EVENT`` to the child process group, and hidden-window
    process groups have proven unreliable for that on Windows runners.

    No-op on non-Windows platforms.
    """
    if sys.platform != "win32":
        return
    creationflags = kwargs.get("creationflags", 0)
    if not isinstance(creationflags, int):
        creationflags = 0
    if creationflags & CREATE_NEW_PROCESS_GROUP:
        kwargs["creationflags"] = creationflags
        return
    kwargs["creationflags"] = creationflags | getattr(
        process, "CREATE_NO_WINDOW", CREATE_NO_WINDOW
    )
