import json
import os
import urllib.error
import urllib.parse
import urllib.request
from datetime import datetime, timedelta, timezone

BASE_URL = os.environ.get("ENERGY_API_URL", "https://energy.netzhandwerker.de")
PAYMENT_SIGNATURE = os.environ.get("X402_PAYMENT_SIGNATURE")


def request_json(url, method="GET", body=None, headers=None):
    encoded = None if body is None else json.dumps(body).encode("utf-8")
    request = urllib.request.Request(
        url,
        data=encoded,
        method=method,
        headers={
            "Accept": "application/json",
            "User-Agent": "Netzhandwerker-Energy-Agent/3.0",
            **({"Content-Type": "application/json"} if body else {}),
            **(headers or {}),
        },
    )
    try:
        response = urllib.request.urlopen(request, timeout=30)
        return response.status, dict(response.headers), json.loads(response.read())
    except urllib.error.HTTPError as error:
        return error.code, dict(error.headers), json.loads(error.read())


deadline = (datetime.now(timezone.utc) + timedelta(hours=5)).isoformat()
workload = {
    "region": "DE-LU",
    "use_case": "compute",
    "duration_minutes": 60,
    "deadline": deadline,
    "power_kw": 25,
    "energy_kwh": 25,
}
query = urllib.parse.urlencode(workload)
status, _, opportunity = request_json(f"{BASE_URL}/v3/opportunities?{query}")
if status != 200:
    raise RuntimeError(f"Preflight failed before payment: {status} {opportunity}")
print("Preflight:", json.dumps(opportunity, indent=2))

dispatch_input = {
    "opportunity_id": opportunity["opportunity_id"],
    "power_kw": workload["power_kw"],
    "energy_kwh": workload["energy_kwh"],
    "deadline": deadline,
    "risk_profile": "balanced",
}
status, _, challenge = request_json(f"{BASE_URL}/v3/dispatch-plan", "POST", dispatch_input)
if status == 409:
    raise RuntimeError(f"Opportunity rejected before payment: {challenge}")
if status != 402:
    raise RuntimeError(f"Expected 402, got {status}: {challenge}")
print("402 challenge:", json.dumps(challenge, indent=2))

if not PAYMENT_SIGNATURE:
    print("Set X402_PAYMENT_SIGNATURE to the proof produced by your Base USDC wallet for this challenge; then rerun immediately.")
    raise SystemExit(0)

status, headers, result = request_json(
    f"{BASE_URL}/v3/dispatch-plan",
    "POST",
    dispatch_input,
    {"PAYMENT-SIGNATURE": PAYMENT_SIGNATURE},
)
if status != 200:
    raise RuntimeError(f"Settlement/result failed: {status} {result}")
print("Settled result:", json.dumps(result, indent=2))
print("Settlement receipt header:", headers.get("Payment-Response"))
