"""SML x402 SDK Starter — MIT licensed.

Public pre-payment helpers only. This module never receives a private key,
signs an authorization, or retries a paid request.
"""

from __future__ import annotations

import base64
import json
from dataclasses import dataclass
from typing import Any, Mapping
from urllib.error import HTTPError
from urllib.request import Request, urlopen

SML_X402_REGISTRY = "https://x402.scriptmasterlabs.com/api/x402-registry"
SML_X402_DISCOVERY = "https://x402.scriptmasterlabs.com/api/x402-discovery"


@dataclass(frozen=True)
class PaymentChallenge:
    header_name: str | None
    raw: str | None
    decoded: Any | None


@dataclass(frozen=True)
class ProbeResult:
    url: str
    status: int
    headers: Mapping[str, str]
    body: str
    payment: PaymentChallenge


def _decode_base64_json(value: str) -> Any | None:
    try:
        padding = "=" * (-len(value) % 4)
        decoded = base64.urlsafe_b64decode(value + padding).decode("utf-8")
        return json.loads(decoded)
    except (UnicodeDecodeError, ValueError, json.JSONDecodeError):
        return None


def read_payment_challenge(headers: Mapping[str, str]) -> PaymentChallenge:
    normalized = {key.lower(): value for key, value in headers.items()}
    for name in ("payment-required", "x-payment-required", "x402-payment-required"):
        raw = normalized.get(name)
        if raw:
            return PaymentChallenge(name, raw, _decode_base64_json(raw))
    return PaymentChallenge(None, None, None)


def get_registry(url: str = SML_X402_REGISTRY, timeout: float = 15) -> Any:
    """Load the unified SML live-evidence registry."""
    request = Request(url, headers={"accept": "application/json"})
    with urlopen(request, timeout=timeout) as response:
        return json.loads(response.read().decode("utf-8"))


def probe_route(
    url: str,
    *,
    method: str = "GET",
    json_body: Any | None = None,
    timeout: float = 15,
) -> ProbeResult:
    """Make an unpaid public request and return any real 402 challenge."""
    body = None
    headers = {"accept": "application/json, text/plain;q=0.9, */*;q=0.5"}
    if json_body is not None:
        body = json.dumps(json_body).encode("utf-8")
        headers["content-type"] = "application/json"

    request = Request(url, data=body, method=method.upper(), headers=headers)
    try:
        with urlopen(request, timeout=timeout) as response:
            raw_body = response.read().decode("utf-8", errors="replace")
            response_headers = dict(response.headers.items())
            return ProbeResult(url, response.status, response_headers, raw_body, read_payment_challenge(response_headers))
    except HTTPError as response:
        raw_body = response.read().decode("utf-8", errors="replace")
        response_headers = dict(response.headers.items())
        return ProbeResult(url, response.code, response_headers, raw_body, read_payment_challenge(response_headers))


# When probe_route() returns HTTP 402, inspect payment.decoded and let your
# wallet/policy layer independently validate and sign before it retries the
# request directly with the provider.
