"""PaperReady Python SDK: zero-dependency client for the cloud print API.
    pr = PaperReady("pr_live_...")
    pr.print(printer="Zebra ZD421", template="Shipping label", data={"name": "…", "sku": "…"})
"""
import json
import urllib.request
import urllib.error


class PaperReadyError(RuntimeError):
    def __init__(self, message, status=None, body=None):
        super().__init__(message)
        self.status = status
        self.body = body


class PaperReady:
    def __init__(self, api_key, base="https://paperready.studio/api"):
        self.key = api_key
        self.base = base

    def _req(self, method, path, body=None, headers=None):
        data = json.dumps(body).encode() if body is not None else None
        h = {"Authorization": "Bearer " + self.key}
        if data:
            h["content-type"] = "application/json"
        if headers:
            h.update(headers)
        req = urllib.request.Request(self.base + path, data=data, headers=h, method=method)
        try:
            with urllib.request.urlopen(req, timeout=30) as r:
                return json.loads(r.read() or b"{}")
        except urllib.error.HTTPError as e:
            b = {}
            try:
                b = json.loads(e.read() or b"{}")
            except Exception:
                pass
            raise PaperReadyError(b.get("message") or b.get("error") or ("HTTP %d" % e.code), e.code, b)

    def whoami(self):
        return self._req("GET", "/v1/whoami")

    def printers(self):
        return self._req("GET", "/v1/printers")

    def templates(self):
        return self._req("GET", "/v1/templates")

    def jobs(self):
        return self._req("GET", "/v1/jobs")

    def print(self, idempotency_key=None, **req):
        # For a management key, pass subaccount_id=... to print into a child workspace.
        headers = {"Idempotency-Key": idempotency_key} if idempotency_key else None
        return self._req("POST", "/v1/print", req, headers)

    def print_bulk(self, **req):
        return self._req("POST", "/v1/print/bulk", req)

    # ----- sub-accounts (requires a management key: subaccounts scope) -----
    def subaccounts(self):
        return self._req("GET", "/v1/subaccounts")

    def create_subaccount(self, name, external_id=None):
        body = {"name": name}
        if external_id is not None:
            body["external_id"] = external_id
        return self._req("POST", "/v1/subaccounts", body)

    def subaccount(self, sub_id):
        return self._req("GET", "/v1/subaccounts/" + sub_id)

    def delete_subaccount(self, sub_id):
        return self._req("DELETE", "/v1/subaccounts/" + sub_id)

    def create_subaccount_key(self, sub_id, name=None):
        return self._req("POST", "/v1/subaccounts/" + sub_id + "/keys", {"name": name} if name else {})

    def subaccount_pair_code(self, sub_id):
        return self._req("POST", "/v1/subaccounts/" + sub_id + "/pair-code")

    def subaccount_usage(self, sub_id):
        return self._req("GET", "/v1/subaccounts/" + sub_id + "/usage")
