"""__init__-level guards that must take effect before transitive imports."""

import os
import subprocess
import sys

import pytest


_LEAK_PREFIX = "/__mempalace_leak_test_sentinel__"


@pytest.mark.parametrize(
    "pythonpath",
    [
        f"{_LEAK_PREFIX}/single",
        f"{_LEAK_PREFIX}/a{os.pathsep}{_LEAK_PREFIX}/b",
        f"{_LEAK_PREFIX}/with-trailing{os.sep}",
        f"{os.pathsep}{_LEAK_PREFIX}/leading-sep",
        ".",
        "",
        None,
    ],
    ids=["single", "multi", "trailing-sep", "leading-pathsep", "dot", "empty", "unset"],
)
def test_init_filters_sys_path_from_leaked_pythonpath(pythonpath):
    """Package init must remove sentinel-prefixed entries from sys.path
    so transitive imports do not pull compiled extensions from the
    leaked PYTHONPATH. os.environ['PYTHONPATH'] is left intact so host
    applications embedding mempalace as a library keep their env for
    their own subprocesses; the env strip lives in the CLI/MCP entry
    points (see test_cli.py / test_mcp_server.py).

    Asserts on the sentinel substring directly so the test does not
    couple to the production normalization logic. The dot/empty/unset
    cases additionally exercise the early-return / collision paths
    without crashing."""
    env = os.environ.copy()
    if pythonpath is None:
        env.pop("PYTHONPATH", None)
    else:
        env["PYTHONPATH"] = pythonpath
    code = (
        "import mempalace, os, sys; "
        f"prefix = {_LEAK_PREFIX!r}; "
        "mempalace_parent = os.path.dirname(os.path.dirname(mempalace.__file__)); "
        "print('ENV:', repr(os.environ.get('PYTHONPATH'))); "
        "print('SENTINEL_IN_PATH:', any(prefix in (p or '') for p in sys.path)); "
        "print('MEMPALACE_PARENT_PRESENT:', any("
        "os.path.normcase(os.path.normpath(p)) == os.path.normcase(os.path.normpath(mempalace_parent)) "
        "for p in sys.path if p))"
    )
    result = subprocess.run(
        [sys.executable, "-c", code],
        env=env,
        capture_output=True,
        text=True,
        check=False,
    )
    diag = (
        f"input={pythonpath!r}; rc={result.returncode}; "
        f"stdout={result.stdout!r}; stderr={result.stderr!r}"
    )
    assert result.returncode == 0, f"subprocess failed: {diag}"
    out = result.stdout
    # Env must be preserved verbatim: embedded callers may need it.
    expected_env = repr(pythonpath) if pythonpath is not None else repr(None)
    assert f"ENV: {expected_env}" in out, (
        f"PYTHONPATH should be preserved by package import: {diag}"
    )
    assert "SENTINEL_IN_PATH: False" in out, f"sentinel-prefix leak: {diag}"
    # Filter must not over-strip: the mempalace package itself must remain
    # importable, so its parent directory must survive on sys.path.
    assert "MEMPALACE_PARENT_PRESENT: True" in out, (
        f"filter over-stripped sys.path (mempalace parent gone): {diag}"
    )


def test_init_preserves_cwd_marker_when_pythonpath_collides():
    """PYTHONPATH='.' normalizes to the same value as the empty-string
    CWD marker on sys.path. The strip must remove '.' from sys.path
    without collapsing the implicit current-directory entry."""
    env = os.environ.copy()
    env["PYTHONPATH"] = "."
    code = (
        "import mempalace, sys; "
        "print('CWD_IN_PATH:', '' in sys.path); "
        "print('DOT_IN_PATH:', '.' in sys.path)"
    )
    result = subprocess.run(
        [sys.executable, "-c", code],
        env=env,
        capture_output=True,
        text=True,
        check=False,
    )
    diag = f"rc={result.returncode}; stdout={result.stdout!r}; stderr={result.stderr!r}"
    assert result.returncode == 0, f"subprocess failed: {diag}"
    assert "CWD_IN_PATH: True" in result.stdout, f"cwd marker dropped: {diag}"
    assert "DOT_IN_PATH: False" in result.stdout, f"dot leak survived: {diag}"
