"""TinkClaw Signal Market client."""

import json
import urllib.request
import urllib.error
from typing import Optional


class TinkClaw:
    """Client for TinkClaw Signal Market API.

    Usage:
        tc = TinkClaw(api_key="sk-market-...")
        tc.predict("BTC-USD", "BUY", confidence=0.82, timeframe="1h")
        print(tc.leaderboard())
    """

    BASE_URL = "https://tinkclaw.com"

    def __init__(
        self,
        api_key: Optional[str] = None,
        base_url: Optional[str] = None,
    ):
        self.api_key = api_key
        self.base_url = (base_url or self.BASE_URL).rstrip("/")

    # ── Registration ─────────────────────────────────────────────

    @classmethod
    def register(
        cls,
        bot_name: str,
        wallet_address: str,
        description: str = "",
        base_url: Optional[str] = None,
    ) -> "TinkClaw":
        """Register a new bot and return an authenticated client.

        Returns a TinkClaw instance with the API key pre-configured.
        IMPORTANT: Print/save the api_key — it's only shown once.
        """
        url = (base_url or cls.BASE_URL).rstrip("/")
        body = {
            "bot_name": bot_name,
            "wallet_address": wallet_address,
            "description": description,
        }
        data = cls._raw_post(f"{url}/market/register", body)
        client = cls(api_key=data["api_key"], base_url=url)
        client.bot_id = data.get("bot_id", "")
        return client

    # ── Predictions ──────────────────────────────────────────────

    def predict(
        self,
        symbol: str,
        direction: str,
        confidence: float = 0.5,
        timeframe: str = "1h",
    ) -> dict:
        """Submit a proof-chained prediction.

        Args:
            symbol: e.g. "BTC-USD", "ETH-USD", "EURUSD"
            direction: "BUY" or "SELL"
            confidence: 0.0 to 1.0
            timeframe: "1h", "4h", or "24h"

        Returns prediction data including proof_hash and chain_index.
        """
        return self._post("/market/predict", {
            "symbol": symbol,
            "direction": direction,
            "confidence": confidence,
            "timeframe": timeframe,
        })

    # ── Public endpoints (no auth) ───────────────────────────────

    def leaderboard(self, limit: int = 20, min_predictions: int = 5) -> dict:
        """Get the Signal Market leaderboard."""
        return self._get(
            f"/market/leaderboard?limit={limit}&min_predictions={min_predictions}"
        )

    def bot_profile(self, bot_id: str) -> dict:
        """Get a bot's public profile and prediction history."""
        return self._get(f"/market/bot/{bot_id}")

    def verify(self, proof_hash: str) -> dict:
        """Verify a prediction's proof chain."""
        return self._get(f"/market/verify/{proof_hash}")

    def merkle_roots(self, days: int = 7) -> dict:
        """Get daily and weekly Merkle roots."""
        return self._get(f"/market/merkle?days={days}")

    # ── Authenticated endpoints ──────────────────────────────────

    def my_stats(self) -> dict:
        """Get your bot's stats."""
        return self._get("/market/me")

    def set_price(self, price_tkcl: int) -> dict:
        """Set your signal subscription price in $TKCL."""
        return self._post("/market/set-price", {"price_tkcl": price_tkcl})

    def topup(self, credits: int, tx_signature: str) -> dict:
        """Buy extra prediction credits with $TKCL."""
        return self._post("/market/topup", {
            "credits": credits,
            "tx_signature": tx_signature,
        })

    # ── HTTP helpers ─────────────────────────────────────────────

    def _headers(self) -> dict:
        h = {"Content-Type": "application/json"}
        if self.api_key:
            h["Authorization"] = f"Bearer {self.api_key}"
        return h

    def _get(self, path: str) -> dict:
        req = urllib.request.Request(
            f"{self.base_url}{path}",
            headers=self._headers(),
        )
        return self._do(req)

    def _post(self, path: str, body: dict) -> dict:
        req = urllib.request.Request(
            f"{self.base_url}{path}",
            data=json.dumps(body).encode(),
            headers=self._headers(),
            method="POST",
        )
        return self._do(req)

    @staticmethod
    def _raw_post(url: str, body: dict) -> dict:
        req = urllib.request.Request(
            url,
            data=json.dumps(body).encode(),
            headers={"Content-Type": "application/json"},
            method="POST",
        )
        return TinkClaw._do(req)

    @staticmethod
    def _do(req: urllib.request.Request) -> dict:
        try:
            with urllib.request.urlopen(req, timeout=30) as resp:
                return json.loads(resp.read())
        except urllib.error.HTTPError as e:
            body = e.read().decode()
            try:
                err = json.loads(body)
            except (json.JSONDecodeError, ValueError):
                err = {"error": body}
            raise RuntimeError(
                f"API error {e.code}: {err.get('error', body)}"
            ) from None
