"""Tests that src/commands.py has NO top-level src.command_palette import.

Per spec.md:2.2 Layer 1, the main thread's import chain must not include
heavy feature-gated modules. src.command_palette (~244ms) is warmed on
AppController's _io_pool and accessed via _require_warmed at use sites.

src/commands.py is a particularly tricky case: it has 32 `@registry.register`
decorators on its command functions. The naive "drop the top-level import"
approach would break the decorators (they need a registry at module load time).

Solution: a lazy registry proxy. The @registry.register decorator becomes a
no-op that queues the function; the real CommandRegistry is created on first
attribute access to the proxy (e.g. registry.all, registry.get). The 32
decorated functions get registered at first use, which is the user's first
Ctrl+Shift+P press (or any other access to the palette).

These tests run in a fresh subprocess to ensure no warmup state leaks
from the test runner. We assert:
  - `src.command_palette` is NOT in `sys.modules` after `import src.commands`
  - The lazy registry proxy works: `from src.commands import registry` succeeds
  - Accessing `registry.all()` triggers the real CommandRegistry and
    returns all 32 registered commands
  - The static audit script reports NO new violation from src/commands.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_commands_does_not_import_command_palette_at_module_level() -> None:
 res = _run_in_subprocess("""
  import sys
  import src.commands
  print('src.command_palette' in sys.modules)
 """)
 assert res.returncode == 0, f"stderr: {res.stderr}"
 assert res.stdout.strip() == "False", f"src.commands triggered src.command_palette import: {res.stdout}"


def test_commands_lazy_registry_proxies_to_real_registry() -> None:
 """Accessing registry.all() should trigger real init and return registered commands."""
 res = _run_in_subprocess("""
  from src.commands import registry
  # Access .all() triggers real CommandRegistry creation
  all_cmds = registry.all()
  print(len(list(all_cmds)))
  # After access, src.command_palette SHOULD be in sys.modules
  import sys
  print('src.command_palette' in sys.modules)
 """)
 assert res.returncode == 0, f"stderr: {res.stderr}"
 lines = res.stdout.strip().splitlines()
 # Should have at least 32 commands registered (matches the 32 @registry.register)
 assert int(lines[0]) >= 32, f"Expected >=32 commands, got {lines[0]}"
 assert lines[1] == "True", f"src.command_palette should be loaded after registry access, got {lines[1]}"


def test_commands_register_decorator_is_lazy() -> None:
 """The @registry.register decorator should NOT trigger command_palette import at module load."""
 res = _run_in_subprocess("""
  # Fresh subprocess, just import commands
  import sys
  import src.commands
  # Verify decorator ran but did not trigger command_palette
  # (the lazy proxy just queues; real init is deferred)
  print('src.command_palette' in sys.modules)
  # Verify the function references still exist
  from src.commands import toggle_command_palette
  print(callable(toggle_command_palette))
 """)
 assert res.returncode == 0, f"stderr: {res.stderr}"
 lines = res.stdout.strip().splitlines()
 assert lines[0] == "False", f"Decorator should not trigger command_palette, got {lines[0]}"
 assert lines[1] == "True", f"toggle_command_palette should be a callable, got {lines[1]}"


def test_audit_main_thread_imports_sees_no_new_violation_from_commands() -> None:
 """Run the static audit and check that src/commands.py contributes no
 new command_palette violations.
 """
 res = _run_in_subprocess("""
  import ast
  from pathlib import Path
  root = Path('.').resolve()
  commands_path = root / 'src' / 'commands.py'
  tree = ast.parse(commands_path.read_text(encoding='utf-8'))
  heavy = ['src.command_palette', 'command_palette']
  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
