"""Google Gemini integration for Baponi sandbox execution.

Usage::

    from baponi.google import code_sandbox

    chat = client.chats.create(
        model="gemini-2.5-flash",
        config={"tools": [code_sandbox]},
    )

For custom configuration::

    from baponi.google import create_code_sandbox

    sandbox = create_code_sandbox(api_key="sk-...", thread_id="my-session")
"""

from __future__ import annotations

from typing import Any

try:
    import google.genai as _genai_module  # noqa: F401
except ImportError as e:
    raise ImportError(
        "google-genai is required for the Gemini integration. "
        "Install it with: pip install baponi[google]"
    ) from e

from baponi._base import result_to_llm_text
from baponi._client import Baponi

_DEFAULT_THREAD_ID: str | None = None
_DEFAULT_TIMEOUT: int = 30
_DEFAULT_METADATA: dict[str, str] | None = None
_DEFAULT_ENV_VARS: dict[str, str] | None = None
_CLIENT: Baponi | None = None
_API_KEY: str | None = None
_BASE_URL: str | None = None


def _get_client() -> Baponi:
    global _CLIENT
    if _CLIENT is None:
        kwargs: dict[str, Any] = {}
        if _API_KEY is not None:
            kwargs["api_key"] = _API_KEY
        if _BASE_URL is not None:
            kwargs["base_url"] = _BASE_URL
        _CLIENT = Baponi(**kwargs, _client_id="baponi-python/google")
    return _CLIENT


def code_sandbox(
    code: str,
    language: str = "python",
    thread_id: str | None = None,
    timeout: int | None = None,
    metadata: dict[str, str] | None = None,
    env_vars: dict[str, str] | None = None,
) -> str:
    """Execute code in a secure, isolated sandbox. Supports bash, python, and node.

    Stateless by default. Nothing persists between calls. Pass a thread_id
    for persistent state (files, pip packages) across calls.

    Storage volumes mounted at /data/<volume-name>/ if configured.

    Returns stdout, stderr, and exit code.

    Args:
        code: The code to execute.
        language: Programming language: python, bash, node.
        thread_id: Pass for persistent state across calls (files, pip packages).
            Must be unique. Use a descriptive prefix + random suffix
            (e.g. data-analysis-x8k2m9p4z1) or a UUID.
        timeout: Execution timeout in seconds. Increase for long-running tasks, max 3600.
        metadata: Key-value metadata for audit trail. Max 10 keys.
        env_vars: Environment variables to set. Keys must be uppercase (e.g. MY_VAR).

    Returns:
        Execution result as text.
    """  # noqa: E501
    client = _get_client()
    tid = thread_id if thread_id is not None else _DEFAULT_THREAD_ID
    to = timeout if timeout is not None else _DEFAULT_TIMEOUT
    meta: dict[str, str] | None
    if metadata is not None:
        meta = {**(_DEFAULT_METADATA or {}), **metadata}
    else:
        meta = _DEFAULT_METADATA
    evars: dict[str, str] | None
    if env_vars is not None:
        evars = {**(_DEFAULT_ENV_VARS or {}), **env_vars}
    else:
        evars = _DEFAULT_ENV_VARS

    result = client.execute(
        code, language=language, timeout=to, thread_id=tid, metadata=meta, env_vars=evars
    )
    return result_to_llm_text(result)


def create_code_sandbox(
    *,
    api_key: str | None = None,
    base_url: str | None = None,
    thread_id: str | None = None,
    timeout: int = 30,
    metadata: dict[str, str] | None = None,
    env_vars: dict[str, str] | None = None,
) -> Any:
    """Create a configured code sandbox function for Gemini.

    Configures the module-level ``code_sandbox`` function and returns it.
    Only call once per process. Subsequent calls overwrite the previous
    configuration. For multiple configurations, use the core ``Baponi``
    client directly.

    Args:
        api_key: Baponi API key. Falls back to BAPONI_API_KEY env var.
        base_url: Custom API base URL (for self-hosted deployments).
        thread_id: Default thread_id for persistent state across calls.
        timeout: Default execution timeout in seconds.
        metadata: Default metadata merged into every call.
        env_vars: Default environment variables merged into every call.

    Returns:
        The configured ``code_sandbox`` function.
    """
    global _API_KEY, _BASE_URL, _DEFAULT_THREAD_ID, _DEFAULT_TIMEOUT, _DEFAULT_METADATA, _DEFAULT_ENV_VARS, _CLIENT
    _API_KEY = api_key
    _BASE_URL = base_url
    _DEFAULT_THREAD_ID = thread_id
    _DEFAULT_TIMEOUT = timeout
    _DEFAULT_METADATA = metadata
    _DEFAULT_ENV_VARS = env_vars
    _CLIENT = None
    return code_sandbox
