"""Tests that scripts/audit_main_thread_imports.py LEAN_ALLOWLIST is kept in sync with actually-lean src.* modules.

The audit script has a conservative allowlist of src.* modules known to be
safe at top-level import. When a module is refactored to remove heavy
imports (sub-tracks 2A-2F of startup_speedup_20260606), it should be added
to the allowlist so sloppy.py can import it without being flagged.

Modules currently in the allowlist:
  - src.imgui_scopes, src.theme_2, src.theme_models, src.paths, src.models,
    src.events, src.config, src.module_loader (added sub-track 2C)
  - src.startup_profiler, src.api_hooks (added sub-track 2D)

Modules NOT yet in the allowlist (awaiting sub-tracks 2E and 2F):
  - src.app_controller (23 violations remaining)
  - src.gui_2 (24 violations remaining)
"""

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_startup_profiler_is_lean_and_in_allowlist() -> None:
 res = _run_in_subprocess("""
  import sys
  import src.startup_profiler
  heavy = {'google.genai', 'anthropic', 'openai', 'fastapi', 'requests', 'numpy', 'tkinter', 'pydantic'}
  leaked = [m for m in heavy if m in sys.modules or any(k in sys.modules for k in [m, m + '.types', m + '.security'])]
  for m in heavy:
   top = m.split('.')[0]
   if top in sys.modules:
    leaked.append(top)
  print('LEAKED', leaked)
 """)
 assert res.returncode == 0, f"stderr: {res.stderr}"
 assert res.stdout.strip() == "LEAKED []", f"src.startup_profiler leaks heavy: {res.stdout}"


def test_api_hooks_is_lean_and_in_allowlist() -> None:
 res = _run_in_subprocess("""
  import sys
  import src.api_hooks
  heavy_top = {'google', 'anthropic', 'openai', 'fastapi', 'requests', 'numpy', 'tkinter', 'pydantic', 'websockets'}
  leaked = [m for m in heavy_top if m in sys.modules]
  print('LEAKED', leaked)
 """)
 assert res.returncode == 0, f"stderr: {res.stderr}"
 assert res.stdout.strip() == "LEAKED []", f"src.api_hooks leaks heavy: {res.stdout}"


def test_allowlist_includes_startup_profiler_and_api_hooks() -> None:
 res = _run_in_subprocess("""
  from scripts.audit_main_thread_imports import LEAN_ALLOWLIST
  print('startup_profiler', 'src.startup_profiler' in LEAN_ALLOWLIST)
  print('api_hooks', 'src.api_hooks' in LEAN_ALLOWLIST)
  print('module_loader', 'src.module_loader' in LEAN_ALLOWLIST)
 """)
 assert res.returncode == 0, f"stderr: {res.stderr}"
 lines = res.stdout.strip().splitlines()
 assert lines[0] == "startup_profiler True", f"src.startup_profiler not in allowlist: {res.stdout}"
 assert lines[1] == "api_hooks True", f"src.api_hooks not in allowlist: {res.stdout}"
 assert lines[2] == "module_loader True", f"src.module_loader not in allowlist: {res.stdout}"


def test_app_controller_and_gui_2_not_yet_in_allowlist() -> None:
 res = _run_in_subprocess("""
  from scripts.audit_main_thread_imports import LEAN_ALLOWLIST
  print('app_controller', 'src.app_controller' in LEAN_ALLOWLIST)
  print('gui_2', 'src.gui_2' in LEAN_ALLOWLIST)
 """)
 assert res.returncode == 0, f"stderr: {res.stderr}"
 lines = res.stdout.strip().splitlines()
 assert lines[0] == "app_controller False", f"src.app_controller should NOT be in allowlist yet: {res.stdout}"
 assert lines[1] == "gui_2 False", f"src.gui_2 should NOT be in allowlist yet: {res.stdout}"
