"""Paylinky Python SDK (requires `requests`). Keep your secret key on the server.

    from paylinky import Paylinky
    plk = Paylinky(os.environ["PAYLINKY_KEY"], base_url="https://YOUR_PAYLINKY_DOMAIN")
    tx = plk.collect(amount=1000, currency="XAF", country_code="CM",
                     operator="MTN Mobile Money", phone="+237000000001")
"""
import hashlib
import hmac
import time

import requests


class PaylinkyError(Exception):
    def __init__(self, status, body):
        super().__init__((body or {}).get("message", "Paylinky request failed"))
        self.status = status
        self.code = (body or {}).get("error")
        self.body = body


class Paylinky:
    def __init__(self, api_key, base_url="https://YOUR_PAYLINKY_DOMAIN", timeout=30):
        if not api_key:
            raise ValueError("A Paylinky API key is required")
        self.api_key, self.base_url, self.timeout = api_key, base_url.rstrip("/"), timeout

    def request(self, method, path, json=None, headers=None):
        h = {"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"}
        h.update(headers or {})
        r = requests.request(method, f"{self.base_url}/api/v1{path}", json=json, headers=h, timeout=self.timeout)
        data = r.json() if r.content else {}
        if not r.ok:
            raise PaylinkyError(r.status_code, data)
        return data

    def countries(self): return self.request("GET", "/countries")
    def crypto_assets(self): return self.request("GET", "/crypto/assets")
    def fees(self): return self.request("GET", "/fees")
    def balance(self): return self.request("GET", "/balance")
    def collect(self, **params): return self.request("POST", "/collect", params)
    def crypto_collect(self, **params): return self.request("POST", "/crypto/collect", params)
    def transaction(self, id): return self.request("GET", f"/transaction/{id}")
    def create_payment_link(self, idempotency_key=None, **params):
        return self.request("POST", "/payment-links", params, {"Idempotency-Key": idempotency_key} if idempotency_key else None)
    def payment_link(self, id): return self.request("GET", f"/payment-links/{id}")
    def simulate(self, transaction_id, status="success"):
        return self.request("POST", "/sandbox/simulate", {"transaction_id": transaction_id, "status": status})

    @staticmethod
    def verify_webhook(raw_body: bytes, headers: dict, secret: str, tolerance=300) -> bool:
        ts = headers.get("X-Paylinky-Timestamp", "")
        sig = headers.get("X-Paylinky-Signature", "").replace("sha256=", "")
        if not ts or not sig or abs(time.time() - float(ts)) > tolerance:
            return False
        expected = hmac.new(secret.encode(), f"{ts}.".encode() + raw_body, hashlib.sha256).hexdigest()
        return hmac.compare_digest(sig, expected)
