"""Dependency-free CalcGard bot client for Python 3.10+."""

from __future__ import annotations

import hashlib
import hmac
import json
import urllib.error
import urllib.parse
import urllib.request


class CalcGardClient:
    def __init__(self, base_url: str, api_key: str) -> None:
        self.base_url = base_url.rstrip("/")
        self.api_key = api_key

    def create_payment(
        self,
        external_id: str,
        amount_rial: int,
        metadata: dict | None = None,
        expires_in_minutes: int = 30,
    ) -> dict:
        return self._request(
            "POST",
            "/api/v1/payments",
            {
                "external_id": external_id,
                "amount_rial": amount_rial,
                "expires_in_minutes": expires_in_minutes,
                "metadata": metadata or {},
            },
        )["data"]

    def get_payment(self, external_id: str) -> dict:
        path = "/api/v1/payments/" + urllib.parse.quote(external_id, safe="")
        return self._request("GET", path)["data"]

    def cancel_payment(self, external_id: str) -> dict:
        path = "/api/v1/payments/" + urllib.parse.quote(external_id, safe="") + "/cancel"
        return self._request("POST", path, {})["data"]

    def _request(self, method: str, path: str, payload: dict | None = None) -> dict:
        body = None if payload is None else json.dumps(payload, ensure_ascii=False).encode()
        request = urllib.request.Request(
            self.base_url + path,
            data=body,
            method=method,
            headers={
                "Accept": "application/json",
                "Content-Type": "application/json",
                "Authorization": f"Bearer {self.api_key}",
            },
        )
        try:
            with urllib.request.urlopen(request, timeout=10) as response:
                return json.load(response)
        except urllib.error.HTTPError as error:
            details = json.loads(error.read().decode() or "{}")
            raise RuntimeError(details.get("error", {}).get("message", f"HTTP {error.code}")) from error


def verify_webhook(raw_body: bytes, signature_header: str, secret: str) -> bool:
    if not signature_header.startswith("sha256="):
        return False
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature_header.removeprefix("sha256="))
