"""HTTP request tools for Sentinel agents (via the `requests` library).

Requires: requests  (Sentinel offers a one-click, leashed install of detected requirements).
Runs in the leashed sandbox under Leash egress control — the target host must be in the
operator's allow-list (`leash network allow <host>`). All functions return a short error
string on failure rather than raising.
"""
from __future__ import annotations

import requests

_MAX = 6000


def _norm(url: str) -> str | None:
    if not isinstance(url, str) or not url.lower().startswith(("http://", "https://")):
        return None
    return url


def http_get(url: str, headers: dict = None, max_chars: int = _MAX) -> str:
    """HTTP GET `url` and return "<status>\\n<body>" (body truncated to `max_chars`).

    Pass optional `headers` (a dict of header name -> value). Use this for JSON or text
    APIs and simple pages. `url` must be an http(s) URL."""
    if _norm(url) is None:
        return "error: url must start with http:// or https://"
    try:
        r = requests.get(url, headers=headers or {}, timeout=25)
    except requests.RequestException as exc:
        return f"error: GET {url} failed: {exc}"
    body = r.text or ""
    if len(body) > max_chars:
        body = body[:max_chars].rstrip() + "\n…[truncated]"
    return f"{r.status_code} {r.reason}\n{body}"


def http_post(url: str, body: dict = None, headers: dict = None, max_chars: int = _MAX) -> str:
    """HTTP POST JSON `body` (a dict) to `url` and return "<status>\\n<response body>".

    Pass optional `headers`. Use this to call JSON APIs that take a POST payload. `url`
    must be an http(s) URL."""
    if _norm(url) is None:
        return "error: url must start with http:// or https://"
    try:
        r = requests.post(url, json=body or {}, headers=headers or {}, timeout=25)
    except requests.RequestException as exc:
        return f"error: POST {url} failed: {exc}"
    text = r.text or ""
    if len(text) > max_chars:
        text = text[:max_chars].rstrip() + "\n…[truncated]"
    return f"{r.status_code} {r.reason}\n{text}"
