"""Botcoin · Python client SDK.

Uso básico:
    from freqtrade_lab_sdk import FreqtradeLabClient

    cli = FreqtradeLabClient("https://freqtrade-lab.com", api_key="ftl_live_...")
    jobs = cli.list_jobs()
    result = cli.get_backtest_metrics(job_id)

Requiere: Python 3.8+, sin deps externas (stdlib only).
"""
import json
import urllib.request
import urllib.parse
import urllib.error


class FreqtradeLabError(Exception):
    def __init__(self, status, body):
        self.status = status
        self.body = body
        super().__init__(f"HTTP {status}: {body}")


class FreqtradeLabClient:
    def __init__(self, base_url, api_key=None, jwt=None, timeout=30):
        self.base_url = base_url.rstrip("/")
        self.timeout = timeout
        self.token = api_key or jwt
        if not self.token:
            raise ValueError("api_key o jwt requerido")

    def _req(self, method, path, params=None, body=None):
        url = self.base_url + path
        if params:
            url += "?" + urllib.parse.urlencode(
                {k: v for k, v in params.items() if v is not None})
        data = json.dumps(body).encode() if body is not None else None
        headers = {
            "Authorization": f"Bearer {self.token}",
            "Accept": "application/json",
        }
        if body is not None:
            headers["Content-Type"] = "application/json"
        req = urllib.request.Request(url, data=data, headers=headers, method=method)
        try:
            with urllib.request.urlopen(req, timeout=self.timeout) as r:
                text = r.read().decode()
                return json.loads(text) if text else None
        except urllib.error.HTTPError as e:
            body_text = e.read().decode()
            raise FreqtradeLabError(e.code, body_text)

    # === Auth / profile ===
    def me(self):
        return self._req("GET", "/api/auth/me")

    # === Jobs ===
    def list_jobs(self, status=None, type_=None, limit=100):
        return self._req("GET", "/api/jobs",
                         params={"status": status, "type": type_, "limit": limit})

    def get_job(self, job_id):
        return self._req("GET", f"/api/job/{job_id}")

    def get_job_metrics(self, job_id):
        return self._req("GET", f"/api/job/{job_id}/analytics")

    def run_backtest(self, strategy, universe, timeframe, timerange, wallet=1000):
        return self._req("POST", "/api/backtest", body={
            "strategy": strategy, "universe": universe,
            "timeframe": timeframe, "timerange": timerange, "wallet": wallet,
        })

    def cancel_job(self, job_id):
        return self._req("POST", f"/api/job/{job_id}/cancel")

    # === Bots ===
    def list_bots(self):
        return self._req("GET", "/api/bots")

    def create_bot(self, name, strategy_id, config):
        return self._req("POST", "/api/bots", body={
            "name": name, "strategy_id": strategy_id, "config": config,
        })

    def start_bot(self, bot_id):
        return self._req("POST", f"/api/bots/{bot_id}/start")

    def stop_bot(self, bot_id):
        return self._req("POST", f"/api/bots/{bot_id}/stop")

    def bot_health(self, bot_id):
        return self._req("GET", f"/api/bots/{bot_id}/health")

    # === Analytics ===
    def analytics_summary(self):
        return self._req("GET", "/api/analytics/summary")

    def heatmap_strategy_month(self):
        return self._req("GET", "/api/analytics/heatmap/strategy_month")

    def monte_carlo(self, job_id, iters=1000):
        return self._req("GET", f"/api/analytics/job/{job_id}/montecarlo",
                         params={"iters": iters})

    def risk_score(self, job_id):
        return self._req("GET", f"/api/risk/score/{job_id}")

    # === Marketplace ===
    def marketplace_list(self, tag=None, limit=100):
        return self._req("GET", "/api/marketplace/list",
                         params={"tag": tag, "limit": limit})

    def marketplace_buy(self, strategy_id):
        return self._req("POST", f"/api/marketplace/{strategy_id}/buy")

    def marketplace_download(self, strategy_id):
        return self._req("GET", f"/api/marketplace/{strategy_id}/download")

    # === Vault (encrypted secrets) ===
    def vault_set(self, namespace, key, value):
        return self._req("POST", "/api/vault/set", body={
            "namespace": namespace, "key": key, "value": value,
        })

    def vault_list(self, namespace=None):
        return self._req("GET", "/api/vault/list",
                         params={"namespace": namespace})

    # === Notifications ===
    def notifications(self, unread_only=False):
        return self._req("GET", "/api/inbox",
                         params={"unread": "1" if unread_only else None})

    def unread_count(self):
        return self._req("GET", "/api/inbox/unread_count")

    # === Search ===
    def search(self, query, types=None):
        return self._req("GET", "/api/search",
                         params={"q": query,
                                 "types": ",".join(types) if types else None})

    # === Quota ===
    def quota(self):
        return self._req("GET", "/api/quota/current")

    # === Webhooks ===
    def webhooks(self):
        return self._req("GET", "/api/webhooks")

    def create_webhook(self, url, events):
        return self._req("POST", "/api/webhooks",
                         body={"url": url, "events": events})


# Ejemplo de uso rápido
if __name__ == "__main__":
    import sys
    import os
    api_key = os.environ.get("FTL_API_KEY")
    base = os.environ.get("FTL_BASE_URL", "http://localhost:8090")
    if not api_key:
        print("Falta FTL_API_KEY. Crea una en /settings#api-keys")
        sys.exit(1)
    cli = FreqtradeLabClient(base, api_key=api_key)
    print("me:", cli.me())
    print("jobs (top 3):", cli.list_jobs(limit=3))
    print("quota:", cli.quota())
