"""Hermes tool for running Python in a separate, credential-free pod."""

from __future__ import annotations

import json
import os
from urllib.error import HTTPError, URLError
from urllib.request import Request, urlopen

from tools.registry import registry, tool_error


def _sandbox_url() -> str:
    """Return the tenant-specific sandbox endpoint injected at startup."""
    return os.environ.get("HERMES_CODE_SANDBOX_URL", "").strip()


def _sandbox_available() -> bool:
    """Expose the tool only when this tenant has an isolated endpoint."""
    return _sandbox_url().startswith("http://hermes-chat-sandbox-")


def execute_python_sandbox(code: str) -> str:
    """Execute Python remotely and return the sandbox's structured result."""
    if not isinstance(code, str) or not code.strip():
        return tool_error("Python code is required.")
    if len(code.encode("utf-8")) > 128 * 1024:
        return tool_error("Python code exceeds the 128 KiB request limit.")

    request = Request(
        _sandbox_url(),
        data=json.dumps({"code": code}).encode("utf-8"),
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    try:
        with urlopen(request, timeout=55) as response:
            payload = response.read(256 * 1024)
        return payload.decode("utf-8", errors="replace")
    except HTTPError as exc:
        detail = exc.read(4096).decode("utf-8", errors="replace")
        return tool_error(f"Python sandbox rejected the request: {detail or exc.code}")
    except (URLError, TimeoutError, OSError) as exc:
        return tool_error(f"Python sandbox is unavailable: {exc}")


registry.register(
    name="python_sandbox",
    toolset="python_sandbox",
    schema={
        "name": "python_sandbox",
        "description": (
            "Run Python in this user's credential-free computation sandbox. "
            "Its /workspace and /opt/data/workspace paths expose the same private "
            "workspace, and /tmp is writable for temporary verifiers. "
            "Use it for file verification, statistics, probability, Monte Carlo "
            "simulation, data transforms, and calculations. The sandbox has no "
            "Kubernetes, Vault, model-provider credentials, or access to other "
            "users. Public research belongs in web_search."
        ),
        "parameters": {
            "type": "object",
            "properties": {
                "code": {
                    "type": "string",
                    "description": "A self-contained Python 3 program that prints its result.",
                }
            },
            "required": ["code"],
        },
    },
    handler=lambda args, **_: execute_python_sandbox(args.get("code", "")),
    check_fn=_sandbox_available,
    emoji="🧮",
    max_result_size_chars=200_000,
)
