"""
HTTP client for Dryft server: POST /context, GET /context/:projectId, POST /push-notify.
"""

import json
import ssl
import urllib.error
import urllib.request
from urllib.parse import quote

try:
    import certifi
    _ssl_context = ssl.create_default_context(cafile=certifi.where())
except ImportError:
    _ssl_context = ssl.create_default_context()
    # macOS Python often lacks system certs; fall back to unverified if needed
    try:
        urllib.request.urlopen("https://example.com", context=_ssl_context, timeout=5)
    except ssl.SSLCertVerificationError:
        _ssl_context = ssl.create_unverified_context()
    except Exception:
        pass


def _base(base_url: str, path: str) -> str:
    base_url = base_url.rstrip("/")
    path = path if path.startswith("/") else f"/{path}"
    return f"{base_url}{path}"


def post_context(base_url: str, payload: dict) -> None:
    url = _base(base_url, "/context")
    data = json.dumps(payload).encode("utf-8")
    req = urllib.request.Request(url, data=data, method="POST")
    req.add_header("Content-Type", "application/json")
    try:
        with urllib.request.urlopen(req, context=_ssl_context) as res:
            if res.status >= 400:
                raise RuntimeError(f"POST /context failed: {res.status} {res.read().decode()}")
    except urllib.error.HTTPError as e:
        body = e.read().decode() if e.fp else ""
        raise RuntimeError(f"POST /context failed: {e.code} {body}") from e
    except urllib.error.URLError as e:
        raise RuntimeError(f"POST /context failed: {e.reason}") from e


def get_context(base_url: str, project_id: str) -> dict:
    url = _base(base_url, f"/context/{quote(project_id, safe='')}")
    req = urllib.request.Request(url, method="GET")
    try:
        with urllib.request.urlopen(req, context=_ssl_context) as res:
            return json.loads(res.read().decode())
    except urllib.error.HTTPError as e:
        body = e.read().decode() if e.fp else ""
        raise RuntimeError(f"GET /context failed: {e.code} {body}") from e
    except urllib.error.URLError as e:
        raise RuntimeError(f"GET /context failed: {e.reason}") from e


def post_push_notify(base_url: str, body: dict) -> None:
    url = _base(base_url, "/push-notify")
    data = json.dumps(body).encode("utf-8")
    req = urllib.request.Request(url, data=data, method="POST")
    req.add_header("Content-Type", "application/json")
    try:
        with urllib.request.urlopen(req, context=_ssl_context) as res:
            if res.status >= 400:
                raise RuntimeError(f"POST /push-notify failed: {res.status} {res.read().decode()}")
    except urllib.error.HTTPError as e:
        body_text = e.read().decode() if e.fp else ""
        raise RuntimeError(f"POST /push-notify failed: {e.code} {body_text}") from e
    except urllib.error.URLError as e:
        raise RuntimeError(f"POST /push-notify failed: {e.reason}") from e
