"""Engine-spawned macOS desktop-control MCP (macos-mcp), over local HTTP.

macOS-only. On Windows this module is a no-op stub: enabled() returns False so
start()/wait_ready() do nothing, because Windows desktop control is provided
IN-PROCESS by voice/desktop_control.py (no HTTP server, no macos-mcp).

Why not a normal stdio MCP server: the Claude CLI spawns stdio MCP servers, and
macOS attributes their TCC permissions to the CLI helper — NOT Jarvis.app. So a
desktop-control server spawned that way is DENIED Accessibility and macos-mcp
exits on startup ("Missing permissions: Accessibility"). Exactly the
responsible-process wall that broke screenshots (see voice/screen.py).

Fix: the ENGINE launches macos-mcp here as its own child, so it inherits
Jarvis.app's Accessibility + Screen Recording grants and runs. Jarvis reaches it
over loopback HTTP (llm.py wires the "desktop" server as an http MCP to
DESKTOP_URL with the bearer key). Localhost-only; the key just satisfies the
server's auth. Set MCP_DESKTOP=0 to disable.
"""

from __future__ import annotations

import os
import socket
import subprocess
import time
from pathlib import Path

DESKTOP_PORT = int(os.environ.get("DESKTOP_MCP_PORT", "8765"))
DESKTOP_KEY = os.environ.get("DESKTOP_MCP_KEY", "jarvis-desktop-local-key")
DESKTOP_URL = f"http://127.0.0.1:{DESKTOP_PORT}/mcp"

_proc: subprocess.Popen | None = None


def enabled() -> bool:
    # macOS-only: on Windows (os.name == 'nt') this HTTP server must never run;
    # desktop control there is in-process via voice/desktop_control.py.
    return os.name != "nt" and os.environ.get("MCP_DESKTOP", "1") != "0"


def start() -> subprocess.Popen | None:
    """Launch macos-mcp (HTTP) as a child of the engine. Idempotent-ish: kills
    any stale server on the port first (a prior engine that was SIGKILLed can
    orphan it and hold the port)."""
    global _proc
    if not enabled():
        return None
    # clear a stale server from a previous run so the port is free
    subprocess.run(["pkill", "-f", "macos_mcp serve"],
                   stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    venv_py = str(Path(__file__).resolve().parent.parent / ".venv" / "bin" / "python")
    try:
        log = open("/tmp/desktop_mcp.log", "a")
        _proc = subprocess.Popen(
            [venv_py, "-m", "macos_mcp", "serve",
             "--transport", "streamable-http",
             "--host", "127.0.0.1", "--port", str(DESKTOP_PORT),
             "--auth-key", DESKTOP_KEY],
            stdout=log, stderr=log,
        )
        return _proc
    except Exception as e:  # noqa: BLE001
        print(f"  desktop MCP failed to launch ({e})")
        _proc = None
        return None


def wait_ready(timeout: float = 8.0) -> bool:
    """Block until the HTTP server is listening, so the brain doesn't connect to
    the desktop MCP before it's up (that would leave Jarvis with no app tools)."""
    if not enabled():
        return False
    end = time.time() + timeout
    while time.time() < end:
        try:
            with socket.create_connection(("127.0.0.1", DESKTOP_PORT), timeout=0.5):
                return True
        except OSError:
            time.sleep(0.3)
    return False


def stop() -> None:
    global _proc
    if _proc and _proc.poll() is None:
        _proc.terminate()
        try:
            _proc.wait(timeout=5)
        except Exception:  # noqa: BLE001
            _proc.kill()
    _proc = None
