"""
ProofRail Python SDK — proof-of-execution in one call. Zero dependencies (stdlib only).

    from proofrail import ProofRail
    pr = ProofRail("prk_your_key")
    r  = pr.prove({"agent": "legal-team", "output_hash": "..."}, label="NDA draft")
    print(r.receipt_url)          # public, human-readable receipt
    print(r.anchors)              # [{chain, tx_hash, explorer_url, status}, ...]
    print(pr.verify(r.proof_id).signature_valid)

Get a free key at https://proofrail.ripitlabs.com/dashboard
"""
import json
import urllib.request
import urllib.error

__version__ = "1.0.0"
DEFAULT_BASE = "https://proofrail.ripitlabs.com"


class ProofRailError(Exception):
    """Raised on any non-2xx response. `.status` and `.detail` carry the specifics."""
    def __init__(self, status, detail):
        super().__init__(f"{status}: {detail}")
        self.status = status
        self.detail = detail


class Receipt:
    """The result of prove(). Attribute access + .to_dict()."""
    def __init__(self, d):
        self._d = d
        self.proof_id = d.get("proof_id")
        self.content_hash = d.get("content_hash")
        self.signature = d.get("signature")
        self.pubkey = d.get("pubkey")
        self.anchors = d.get("anchors", []) or []
        self.verify_url = d.get("verify_url")
        self.receipt_url = d.get("receipt_url")
        self.usage = d.get("usage")

    @property
    def chains(self):
        return [a.get("chain") for a in self.anchors if a.get("tx_hash")]

    def to_dict(self):
        return self._d

    def __repr__(self):
        return f"<Receipt {self.proof_id} chains={self.chains}>"


class Verdict:
    """The result of verify()."""
    def __init__(self, d):
        self._d = d
        self.proof_id = d.get("proof_id")
        self.content_hash = d.get("content_hash")
        self.signature_valid = bool(d.get("signature_valid"))
        self.anchors = d.get("anchors", []) or []

    @property
    def onchain(self):
        """True if at least one chain confirms the proof on-chain."""
        return any(a.get("onchain_valid") for a in self.anchors)

    @property
    def ok(self):
        """Signature valid AND (on-chain confirmed, or it was a sign-only proof)."""
        return self.signature_valid and (self.onchain or not self.anchors)

    def to_dict(self):
        return self._d

    def __repr__(self):
        return f"<Verdict {self.proof_id} ok={self.ok}>"


class ProofRail:
    def __init__(self, api_key=None, base_url=DEFAULT_BASE, timeout=90):
        self.api_key = api_key
        self.base_url = base_url.rstrip("/")
        self.timeout = timeout

    def _req(self, method, path, body=None, auth=True):
        data = json.dumps(body).encode() if body is not None else None
        headers = {"Content-Type": "application/json", "User-Agent": f"proofrail-python/{__version__}"}
        if auth and self.api_key:
            headers["Authorization"] = "Bearer " + self.api_key
        req = urllib.request.Request(self.base_url + path, data=data, headers=headers, method=method)
        try:
            with urllib.request.urlopen(req, timeout=self.timeout) as resp:
                return json.load(resp)
        except urllib.error.HTTPError as e:
            try:
                detail = json.load(e).get("detail")
            except Exception:
                detail = e.reason
            raise ProofRailError(e.code, detail)

    # ── core ──
    def prove(self, payload, label="", chains=None):
        """Sign + anchor a payload. `chains=[]` = sign-only (no gas). Returns a Receipt."""
        body = {"payload": payload, "label": label}
        if chains is not None:
            body["chains"] = chains
        return Receipt(self._req("POST", "/api/proof", body))

    def verify(self, proof_id):
        """Independently re-verify a proof (public, no key needed). Returns a Verdict."""
        return Verdict(self._req("GET", f"/api/verify/{proof_id}", auth=False))

    def chains(self):
        """List supported chains + live status."""
        return self._req("GET", "/api/chains", auth=False).get("chains", [])

    # ── account (optional) ──
    def signup(self, email, password):
        """Create an account; returns {token, api_key, tier}."""
        return self._req("POST", "/api/signup", {"email": email, "password": password}, auth=False)

    def login(self, email, password):
        return self._req("POST", "/api/login", {"email": email, "password": password}, auth=False)
