from functools import wraps
from pathlib import Path
import os
import subprocess
import sys

from byteb4rb1e.testing.pytest import get_current_test


def run_in_subprocess_once():
    """
    A decorator that reruns th test in a subprocess if not already inside one.
    Requires pytest to be installed and test to be run by pytest.

    For what? Anything that can't be done in a thread-safe manner, e.g. modifying PYTHON_PATH
    """
    def decorator(test_func):
        @wraps(test_func)
        def wrapper(*args, **kwargs):
            if os.environ.get("XPYTEST_INSIDE_SUBPROCESS") == "1":
                return test_func(*args, **kwargs)

            suite_path, case_name = get_current_test()

            cmd = [
                sys.executable,
                "-m", "pytest",
                f"{suite_path}::{case_name}",
            ] 

            result = subprocess.run(
                cmd,
                env={**os.environ, "XPYTEST_INSIDE_SUBPROCESS": "1"},
                capture_output=True,
                text=True,
            )

            if result.returncode != 0:
                print(' '.join(cmd))
                print("==== Subprocess stdout ====")
                print(result.stdout)
                print("==== Subprocess stderr ====")
                print(result.stderr)
                raise AssertionError(f"Subprocess test failed with exit code {result.returncode}")
        return wrapper
    return decorator

