"""A08 — godotiq_exec: Execute arbitrary GDScript.

Supports two contexts:
- "game" (default): Runs in game process via EngineDebugger. RefCounted sandbox,
  no get_node/get_tree. Only Engine.* and static APIs. Game must be running.
- "editor": Runs in editor process. Full access to EditorInterface,
  get_tree(), edited scene root, all editor nodes. Like GDAI's execute_editor_script.
"""

from __future__ import annotations

from godotiq.bridge.session import get_bridge

TOOL_NAME = "godotiq_exec"
TOOL_DESCRIPTION = (
    "Execute arbitrary GDScript code. "
    "context='game' (default): runs in game sandbox with limited access. Game must be running. "
    "context='editor': runs in editor with full access to EditorInterface, "
    "get_tree(), scene nodes. Use for editor queries and modifications. "
    "Code MUST contain 'func run():'. Return value is stringified."
)


async def exec_code(
    code: str = "",
    context: str = "game",
    timeout_ms: int = 5000,
) -> dict:
    """Execute GDScript code.

    Args:
        code: GDScript code containing 'func run():'. The return value of run()
            will be stringified and returned.
        context: "game" (default) — sandbox, or "editor" — full editor access.
        timeout_ms: Max execution time in milliseconds (default 5000).

    Game context examples:
        code="func run():\\n\\treturn Engine.get_version_info()"
        code="func run():\\n\\treturn Engine.get_frames_per_second()"

    Editor context examples:
        code="func run():\\n\\tvar root = get_tree().edited_scene_root\\n\\treturn root.name"
        code="func run():\\n\\treturn get_tree().edited_scene_root.get_child_count()"
        code="func run():\\n\\treturn str(EditorInterface.get_edited_scene_root().scene_file_path)"

    Returns:
        Dict with status (OK/BLOCKED/COMPILE_ERROR/ERROR), result (string), error.
    """
    if not code:
        return {"status": "ERROR", "result": "", "error": "No code provided"}

    if context not in ("editor", "game"):
        return {
            "status": "ERROR",
            "result": "",
            "error": f"Invalid context: {context}. Use 'editor' or 'game'.",
        }

    bridge = await get_bridge()

    if context == "editor":
        return await bridge.request("exec_editor", params={
            "code": code,
            "timeout_ms": timeout_ms,
        }, timeout=10.0)
    else:
        return await bridge.request("exec", params={
            "code": code,
            "timeout_ms": timeout_ms,
        }, timeout=10.0)
