"""Tests that src/app_controller.py has NO top-level fastapi imports.

Per spec.md:2.2 Layer 1, the main thread's import chain must not include
heavy modules. FastAPI is heavy (~470ms) and is only needed when
`--enable-test-hooks` or `--web-host` is passed. The warmup loads it
on the AppController's _io_pool; functions that need it call
`_require_warmed("fastapi")` to get the module from sys.modules.

These tests run in a fresh subprocess to ensure no warmup state leaks
from the test runner. We assert:
  - `fastapi` is NOT in `sys.modules` after `import src.app_controller`
  - `fastapi.security.api_key` is NOT in `sys.modules` either
  - The static audit script reports NO new violation from app_controller.py
"""

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_app_controller_does_not_import_fastapi_at_module_level() -> None:
 res = _run_in_subprocess("""
  import sys
  import src.app_controller
  print('fastapi' in sys.modules)
 """)
 assert res.returncode == 0, f"stderr: {res.stderr}"
 assert res.stdout.strip() == "False", f"app_controller triggered fastapi import: {res.stdout}"


def test_app_controller_does_not_import_fastapi_security_at_module_level() -> None:
 res = _run_in_subprocess("""
  import sys
  import src.app_controller
  print('fastapi.security.api_key' in sys.modules)
 """)
 assert res.returncode == 0, f"stderr: {res.stderr}"
 assert res.stdout.strip() == "False", f"app_controller triggered fastapi.security.api_key import: {res.stdout}"


def test_app_controller_create_api_still_resolvable() -> None:
 """Even without fastapi in sys.modules, the function reference must be
 importable (it just returns a lazy FastAPI app on call)."""
 res = _run_in_subprocess("""
  import src.app_controller
  print(hasattr(src.app_controller.AppController, 'create_api'))
  print(callable(src.app_controller.AppController.create_api))
 """)
 assert res.returncode == 0, f"stderr: {res.stderr}"
 assert res.stdout.strip() == "True\nTrue"


def test_audit_main_thread_imports_sees_no_new_violation_from_app_controller() -> None:
 """Run the static audit and check that src/app_controller.py contributes no
 new fastapi violations (any remaining violations are pre-existing in OTHER
 files; this just verifies app_controller is clean).
 """
 res = _run_in_subprocess("""
  import ast
  from pathlib import Path
  root = Path('.').resolve()
  app_controller_path = root / 'src' / 'app_controller.py'
  tree = ast.parse(app_controller_path.read_text(encoding='utf-8'))
  heavy = ['fastapi', 'fastapi.security', 'fastapi.security.api_key']
  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 node.module == h or node.module.startswith(h + '.'):
       print('VIOLATION:', node.module)
  print('OK')
 """)
 assert res.returncode == 0, f"stderr: {res.stderr}"
 assert "OK" in res.stdout
 assert "VIOLATION" not in res.stdout
