"""
Statistics of the World — official Python client (single file, stdlib only).

    from sotw import SOTW
    sotw = SOTW()                       # anonymous / free tier
    sotw = SOTW(api_key="YOUR_KEY")     # higher limits

    sotw.indicators(category="Economy")
    sotw.country("USA")
    sotw.history("NY.GDP.MKTP.CD", "USA")
    sotw.rankings("NY.GDP.MKTP.CD")
    sotw.series_observations("UST.YC.10Y")
    sotw.calendar(institution="BLS")

Data is sourced from primary institutions (IMF, World Bank, OECD, BIS, national
statistical offices) under each source's licence. No dependencies. MIT licensed.
Docs: https://statisticsoftheworld.com/api-docs
"""
import json
import urllib.parse
import urllib.request

__version__ = "1.0.0"


class SOTWError(Exception):
    pass


class SOTW:
    def __init__(self, api_key=None, base_url="https://statisticsoftheworld.com", timeout=30):
        self.api_key = api_key
        self.base_url = base_url.rstrip("/")
        self.timeout = timeout

    def _get(self, path, params=None):
        url = f"{self.base_url}/api/v1/{path.lstrip('/')}"
        if params:
            clean = {k: v for k, v in params.items() if v is not None}
            if clean:
                url += "?" + urllib.parse.urlencode(clean, doseq=True)
        req = urllib.request.Request(url, headers={"User-Agent": f"sotw-python/{__version__}"})
        if self.api_key:
            req.add_header("X-API-Key", self.api_key)
        try:
            with urllib.request.urlopen(req, timeout=self.timeout) as resp:
                return json.loads(resp.read().decode("utf-8"))
        except urllib.error.HTTPError as e:
            body = e.read().decode("utf-8", "replace")
            raise SOTWError(f"HTTP {e.code}: {body}") from None

    # ── Indicators & countries ─────────────────────────────────────
    def indicators(self, category=None, limit=None, offset=None):
        return self._get("indicators", {"category": category, "limit": limit, "offset": offset})

    def indicator(self, indicator_id):
        return self._get(f"indicators/{urllib.parse.quote(indicator_id)}")

    def countries(self):
        return self._get("countries")

    def country(self, country_id):
        return self._get(f"countries/{urllib.parse.quote(country_id)}")

    # ── Time series ────────────────────────────────────────────────
    def history(self, indicator_id, country_id):
        return self._get(f"history/{urllib.parse.quote(indicator_id)}/{urllib.parse.quote(country_id)}")

    def rankings(self, indicator_id):
        return self._get(f"rankings/{urllib.parse.quote(indicator_id)}")

    def compare(self, countries, indicators):
        return self._get("compare", {"countries": ",".join(countries), "indicators": ",".join(indicators)})

    # ── High-frequency series (rates, yields, energy) ──────────────
    def series(self):
        return self._get("series")

    def series_observations(self, series_id, geo=None, start=None, end=None, limit=None):
        return self._get(f"series/{urllib.parse.quote(series_id)}",
                         {"geo": geo, "start": start, "end": end, "limit": limit})

    # ── Discovery & calendar ───────────────────────────────────────
    def search(self, query):
        return self._get("search", {"q": query})

    def calendar(self, institution=None, country=None, from_=None, to=None):
        return self._get("calendar", {"institution": institution, "country": country, "from": from_, "to": to})


if __name__ == "__main__":
    api = SOTW()
    print(json.dumps(api.country("USA"), indent=2)[:1000])
