"""
Built-in tool: http_request

Makes an outbound HTTP request with safety constraints:
  - Timeout: 30 seconds
  - Response size cap: 1MB
  - Allowed methods: GET, POST, PUT, DELETE

This tool requires_confirmation=True (set in registry) because outbound HTTP
requests can have side effects and should always be user-approved.
"""

from __future__ import annotations

import logging

import httpx

logger = logging.getLogger(__name__)

_ALLOWED_METHODS = frozenset({"GET", "POST", "PUT", "DELETE"})
_REQUEST_TIMEOUT = httpx.Timeout(timeout=30.0, connect=10.0)
_MAX_RESPONSE_BYTES = 1 * 1024 * 1024  # 1MB


async def http_request(
    url: str,
    method: str = "GET",
    body: str | None = None,
    **kwargs: object,
) -> str:
    """
    Make an outbound HTTP request.

    Args:
        url:    The target URL.
        method: HTTP method — GET, POST, PUT, or DELETE.
        body:   Optional request body string (used for POST/PUT).

    Returns:
        Response body as a string (capped at 1MB), or an error message.
    """
    method = method.upper()
    if method not in _ALLOWED_METHODS:
        return f"Invalid HTTP method '{method}'. Allowed: {', '.join(sorted(_ALLOWED_METHODS))}"

    try:
        async with httpx.AsyncClient(timeout=_REQUEST_TIMEOUT) as client:
            request_kwargs: dict = {}
            if body is not None:
                request_kwargs["content"] = body.encode("utf-8")

            response = await client.request(method, url, **request_kwargs)
            response.raise_for_status()

            # Cap response size at 1MB
            content_bytes = response.content[:_MAX_RESPONSE_BYTES]
            content = content_bytes.decode("utf-8", errors="replace")

            truncated = len(response.content) > _MAX_RESPONSE_BYTES
            suffix = "\n[Response truncated at 1MB limit]" if truncated else ""

            return f"HTTP {response.status_code} {method} {url}\n\n{content}{suffix}"

    except httpx.HTTPStatusError as exc:
        logger.warning("http_request HTTP error: %s %s -> %s", method, url, exc.response.status_code)
        return f"HTTP {exc.response.status_code} error from {url}"
    except httpx.TimeoutException:
        logger.warning("http_request timeout: %s %s", method, url)
        return f"Request to {url} timed out after 30 seconds."
    except httpx.RequestError as exc:
        logger.warning("http_request connection error: %s", exc)
        return f"Failed to connect to {url}: {exc}"
