"""Tests that src/gui_2.py has NO top-level heavy feature-gated imports.

Per spec.md:2.2 Layer 1, the main thread's import chain must not include
heavy feature-gated modules. The audit (scripts/audit_gui2_imports.py)
identified several candidates in src/gui_2.py:

  - theme_nerv_fx: NEVER USED in gui_2.py (dead import; the actual NERV
    FX is created in src/theme_2.py and accessed via render_post_fx)
  - tomli_w: NEVER USED in gui_2.py (dead import; the actual TOML
    write happens in src/io_pool.py or other modules)
  - numpy: used in 1 place (plot_lines). Lazy lookup at use site.
  - tkinter: used in 13 file dialogs. Lazy lookup via a helper.

Phase 5D removes the dead imports and defers the heavy ones to the
use site via _require_warmed. After this refactor, the main thread's
import chain is meaningfully smaller (theme_nerv_fx alone is 254ms).
"""

import subprocess
import sys
import textwrap
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent


def _run_in_subprocess(snippet: str) -> subprocess.CompletedProcess:
 script = textwrap.dedent(snippet)
 return subprocess.run(
  [sys.executable, "-c", script],
  capture_output=True,
  text=True,
  cwd=str(ROOT),
  timeout=30,
 )


def test_gui_2_does_not_import_theme_nerv_fx_at_module_level() -> None:
 res = _run_in_subprocess("""
  import sys
  import src.gui_2
  print('src.theme_nerv_fx' in sys.modules)
 """)
 assert res.returncode == 0, f"stderr: {res.stderr}"
 assert res.stdout.strip() == "False", f"gui_2 triggered src.theme_nerv_fx import: {res.stdout}"


def test_gui_2_does_not_import_tomli_w_at_module_level() -> None:
 res = _run_in_subprocess("""
  import sys
  import src.gui_2
  print('tomli_w' in sys.modules)
 """)
 assert res.returncode == 0, f"stderr: {res.stderr}"
 assert res.stdout.strip() == "False", f"gui_2 triggered tomli_w import: {res.stdout}"


def test_gui_2_does_not_import_numpy_at_module_level() -> None:
 """numpy is only used in 1 place (plot_lines). Lazy lookup at use site.

 NOTE: The runtime check is too strict because imgui_bundle (which is
 required for the ImGui hot path) transitively imports numpy. What we
 control is that gui_2.py itself doesn't have a top-level numpy import.
 """
 res = _run_in_subprocess("""
  import ast
  from pathlib import Path
  root = Path('.').resolve()
  gui2_path = root / 'src' / 'gui_2.py'
  tree = ast.parse(gui2_path.read_text(encoding='utf-8'))
  has_top_level_numpy = False
  for node in tree.body:
   if isinstance(node, ast.Import):
    for alias in node.names:
     if alias.name == 'numpy' or alias.name.startswith('numpy.'):
      has_top_level_numpy = True
   elif isinstance(node, ast.ImportFrom):
    if node.module and (node.module == 'numpy' or node.module.startswith('numpy.')):
      has_top_level_numpy = True
  print('HAS_TOP_LEVEL_NUMPY:', has_top_level_numpy)
 """)
 assert res.returncode == 0, f"stderr: {res.stderr}"
 assert "HAS_TOP_LEVEL_NUMPY: False" in res.stdout


def test_gui_2_does_not_import_tkinter_at_module_level() -> None:
 """tkinter is only used for file dialogs. Lazy lookup at use site.

 NOTE: The runtime check is unreliable because tkinter may be brought in
 by other transitive imports. What we control is that gui_2.py itself
 doesn't have a top-level tkinter import.
 """
 res = _run_in_subprocess("""
  import ast
  from pathlib import Path
  root = Path('.').resolve()
  gui2_path = root / 'src' / 'gui_2.py'
  tree = ast.parse(gui2_path.read_text(encoding='utf-8'))
  has_top_level_tkinter = False
  for node in tree.body:
   if isinstance(node, ast.Import):
    for alias in node.names:
     if alias.name == 'tkinter' or alias.name.startswith('tkinter.'):
      has_top_level_tkinter = True
   elif isinstance(node, ast.ImportFrom):
    if node.module and (node.module == 'tkinter' or node.module.startswith('tkinter.')):
      has_top_level_tkinter = True
  print('HAS_TOP_LEVEL_TKINTER:', has_top_level_tkinter)
 """)
 assert res.returncode == 0, f"stderr: {res.stderr}"
 assert "HAS_TOP_LEVEL_TKINTER: False" in res.stdout


def test_gui_2_does_not_import_tomli_w_at_module_level() -> None:
 """tomli_w is never used in gui_2.py. Verify no top-level import.

 NOTE: Similar to numpy/tkinter, tomli_w may be transitively brought in
 by other src.* modules. The AST check confirms gui_2.py's own top-level
 imports are clean.
 """
 res = _run_in_subprocess("""
  import ast
  from pathlib import Path
  root = Path('.').resolve()
  gui2_path = root / 'src' / 'gui_2.py'
  tree = ast.parse(gui2_path.read_text(encoding='utf-8'))
  has_top_level_tomli = False
  for node in tree.body:
   if isinstance(node, ast.Import):
    for alias in node.names:
     if alias.name == 'tomli_w' or alias.name.startswith('tomli_w.'):
      has_top_level_tomli = True
   elif isinstance(node, ast.ImportFrom):
    if node.module and (node.module == 'tomli_w' or node.module.startswith('tomli_w.')):
      has_top_level_tomli = True
  print('HAS_TOP_LEVEL_TOMLI:', has_top_level_tomli)
 """)
 assert res.returncode == 0, f"stderr: {res.stderr}"
 assert "HAS_TOP_LEVEL_TOMLI: False" in res.stdout


def test_audit_gui_2_sees_no_new_violations() -> None:
 """Run the static audit and check that gui_2.py has no new top-level
 imports of the heavy modules above."""
 res = _run_in_subprocess("""
  import ast
  from pathlib import Path
  root = Path('.').resolve()
  gui2_path = root / 'src' / 'gui_2.py'
  tree = ast.parse(gui2_path.read_text(encoding='utf-8'))
  heavy = ['numpy', 'tomli_w', 'tkinter', 'src.theme_nerv_fx']
  for node in tree.body:
   if isinstance(node, ast.Import):
    for alias in node.names:
     for h in heavy:
      if alias.name == h or alias.name.startswith(h + '.'):
       print('VIOLATION:', alias.name)
   elif isinstance(node, ast.ImportFrom):
    if node.module:
     for h in heavy:
      if h == 'src.theme_nerv_fx':
       if node.module == h:
        print('VIOLATION:', node.module)
      # Don't flag 'from src.theme_nerv_fx import ...' because the
      # parent module path 'src.theme_nerv_fx' would match; only
      # flag exact equality.
  print('OK')
 """)
 assert res.returncode == 0, f"stderr: {res.stderr}"
 assert "OK" in res.stdout
 assert "VIOLATION" not in res.stdout
