"""
Ontario Protocol preflight helper for Python agents.

Usage:
    from ontario_preflight import can_pay
    decision = can_pay("https://example.com/api/paid-endpoint", max_usdc="0.05")
    if decision["decision"] != "allow":
        raise RuntimeError(decision["reasons"])
"""

from __future__ import annotations

import json
import urllib.request
from typing import Any, Dict
from urllib.parse import urlencode

ONTARIO_BASE = "https://ontarioprotocol.com"


def _post_json(path: str, payload: Dict[str, Any]) -> Dict[str, Any]:
    body = json.dumps(payload).encode("utf-8")
    req = urllib.request.Request(
        f"{ONTARIO_BASE}{path}",
        data=body,
        headers={"Content-Type": "application/json", "User-Agent": "OntarioPreflight-Python/1.0"},
        method="POST",
    )
    with urllib.request.urlopen(req, timeout=20) as res:
        return json.loads(res.read().decode("utf-8"))


def _get_json(path: str) -> Dict[str, Any]:
    req = urllib.request.Request(
        f"{ONTARIO_BASE}{path}",
        headers={"Accept": "application/json", "User-Agent": "OntarioPreflight-Python/1.1"},
        method="GET",
    )
    with urllib.request.urlopen(req, timeout=20) as res:
        return json.loads(res.read().decode("utf-8"))


def verify(endpoint: str) -> Dict[str, Any]:
    return _post_json("/api/verify/x402-readiness", {"target_url": endpoint})


def can_pay(endpoint: str, *, max_usdc: str | None = None, policy: str = "strict") -> Dict[str, Any]:
    payload: Dict[str, Any] = {"endpoint": endpoint, "agent_policy": policy}
    if max_usdc is not None:
        payload["max_usdc"] = max_usdc
    return _post_json("/api/agent/can-pay", payload)


def assert_can_pay(endpoint: str, *, max_usdc: str | None = None, policy: str = "strict") -> Dict[str, Any]:
    decision = can_pay(endpoint, max_usdc=max_usdc, policy=policy)
    if decision.get("decision") != "allow":
        reasons = "; ".join(decision.get("reasons") or [decision.get("reason", "payment denied")])
        raise RuntimeError(f"Ontario preflight blocked payment: {reasons}")
    return decision


def verified_services(*, limit: int = 100) -> Dict[str, Any]:
    return _get_json(f"/api/verify/services?{urlencode({'limit': limit})}")


def service_profile(slug: str) -> Dict[str, Any]:
    return _get_json(f"/api/verify/services/{slug}")


def history(endpoint: str, *, limit: int = 50) -> Dict[str, Any]:
    return _get_json(f"/api/verify/history?{urlencode({'target_url': endpoint, 'limit': limit})}")


if __name__ == "__main__":
    import argparse

    parser = argparse.ArgumentParser(description="Check whether an agent should pay an x402 endpoint.")
    parser.add_argument("endpoint")
    parser.add_argument("--max-usdc", default=None)
    parser.add_argument("--policy", default="strict", choices=["strict", "standard", "permissive"])
    parser.add_argument("--assert-allow", action="store_true")
    args = parser.parse_args()
    result = assert_can_pay(args.endpoint, max_usdc=args.max_usdc, policy=args.policy) if args.assert_allow else can_pay(args.endpoint, max_usdc=args.max_usdc, policy=args.policy)
    print(json.dumps(result, indent=2))
