"""AICD 工具出站策略：可在「禁止外向联网」模式下仅允许本机回环 HTTP(S)（不含 LLM 客户端）。"""

from __future__ import annotations

import os
from ipaddress import ip_address
from typing import Any
from urllib.parse import urlparse

from aicd.config import AppConfig


def apply_cli_block_external_network_flag(enabled: bool) -> None:
    """与 ``aicd --block-external-network`` 一致：写入环境变量，供 ``merge_env_block_external_network`` 读取。"""
    if enabled:
        os.environ["AICD_BLOCK_EXTERNAL_NETWORK"] = "1"


def merge_env_block_external_network(cfg: AppConfig) -> None:
    """环境变量 ``AICD_BLOCK_EXTERNAL_NETWORK=1|true|yes|on`` 时强制开启。"""
    v = (os.environ.get("AICD_BLOCK_EXTERNAL_NETWORK") or "").strip().lower()
    if v in ("1", "true", "yes", "on"):
        cfg.agent.block_external_network = True


def aicd_runtime_flags_from_config(cfg: AppConfig) -> dict[str, Any]:
    return {
        "block_external_network": bool(cfg.agent.block_external_network),
    }


_BLOCK_HINT_ZH = (
    "已启用 **agent.blockExternalNetwork**（或 ``AICD_BLOCK_EXTERNAL_NETWORK=1`` / 启动参数 "
    "**--block-external-network**）：AICD **工具**不得访问公网 HTTP(S)，"
    "仅允许 **127.0.0.1** / **localhost** / **::1** 等回环地址及 **file:**。"
    "**LLM API** 不受影响；用户项目内由 **run_command** 等发起的网络不受本策略约束。"
)


def block_external_network_hint_zh() -> str:
    return _BLOCK_HINT_ZH


def outbound_tool_url_blocked_reason(url: str, *, block_external: bool) -> str | None:
    """
    若应拦截则返回中文/英文原因串；否则 ``None``。
    **file:**、**about:**、**blob:**（部分环境）— 仅 **file:** 允许且视为本地。
    """
    if not block_external:
        return None
    raw = (url or "").strip()
    if not raw:
        return "空 URL"
    try:
        p = urlparse(raw)
    except Exception:  # noqa: BLE001
        return "无法解析的 URL"

    scheme = (p.scheme or "").lower()
    if scheme in ("file", "about"):
        return None
    if scheme not in ("http", "https", "ws", "wss"):
        return (
            f"在 block_external_network 模式下仅允许 http(s)/ws(s)/file 类 URL 由工具发出；"
            f"当前 scheme={scheme!r}"
        )

    host = p.hostname
    if host is None or host == "":
        return "缺少主机名"

    if _host_is_loopback(host):
        return None
    return (
        "block_external_network：目标主机非本机回环。"
        f" 允许示例：http://127.0.0.1/、http://localhost/、http://[::1]/；"
        f" 当前 host={host!r}。{_BLOCK_HINT_ZH}"
    )


def _host_is_loopback(host: str) -> bool:
    h = host.strip().lower()
    if h == "localhost":
        return True
    if h.startswith("[") and h.endswith("]"):
        h = h[1:-1]
    try:
        return bool(ip_address(h).is_loopback)
    except ValueError:
        return h.endswith(".localhost")  # RFC 6761
