"""
MeteoFeed — official lightweight Python client for the MeteoFeed weather API.

  Site:  https://meteofeed.com
  Docs:  https://meteofeed.com/docs
  Spec:  https://meteofeed.com/openapi/v1.yaml   (generate a full typed client from this if you prefer)

A single file with one dependency (`requests`). Vendor it, or `pip install requests` and drop
it in. Every endpoint is one bearer-token GET returning JSON; use the named helpers for the
common ones, or `.get(path, **params)` for anything in the API.

    pip install requests

    from meteofeed import MeteoFeed
    mf = MeteoFeed("mtfd_your_key")

    now = mf.current(52.37, 4.89)
    print(now["data"]["temperature"], "°C")

    # pick a forecast model:
    gfs = mf.forecast(52.37, 4.89, hours=48, model="gfs")

    # any endpoint via the generic getter:
    quakes = mf.get("earthquakes", min_mag=5, limit=10)

MIT-licensed. Python 3.8+.
"""

import requests

__version__ = "1.0.0"


class MeteoFeedError(Exception):
    """Raised on any non-2xx API response. `.status` is the HTTP code; `.code`/`.message`
    come from the API error envelope; `.retry_after` is set on 429 (seconds)."""

    def __init__(self, status, code=None, message=None, retry_after=None):
        self.status = status
        self.code = code
        self.message = message
        self.retry_after = retry_after
        detail = f" [{code}]" if code else ""
        detail += f": {message}" if message else ""
        super().__init__(f"MeteoFeed API error {status}{detail}")


class MeteoFeed:
    def __init__(self, api_key, base_url="https://api.meteofeed.com", timeout=30, session=None):
        if not api_key:
            raise ValueError("an API key is required (mtfd_…)")
        self.base_url = base_url.rstrip("/")
        self.timeout = timeout
        self._s = session or requests.Session()
        self._s.headers.update({"Authorization": f"Bearer {api_key}", "Accept": "application/json"})

    def get(self, path, **params):
        """GET /v1/<path> with the given query params (None values dropped); returns parsed JSON."""
        clean = {k: v for k, v in params.items() if v is not None}
        r = self._s.get(f"{self.base_url}/v1/{str(path).lstrip('/')}", params=clean, timeout=self.timeout)
        if r.status_code >= 400:
            code = message = None
            try:
                body = r.json()
                err = body.get("error") if isinstance(body, dict) else None
                if isinstance(err, dict):
                    code, message = err.get("code"), err.get("message")
                message = message or (body.get("message") if isinstance(body, dict) else None)
            except ValueError:
                pass
            raise MeteoFeedError(r.status_code, code, message, r.headers.get("Retry-After"))
        return r.json()

    # ---- convenience helpers (everything else: self.get(path, **params)) ----
    def me(self): return self.get("me")
    def current(self, lat, lng, **kw): return self.get("current", lat=lat, lng=lng, **kw)
    def stations(self, country, **kw): return self.get("stations", country=country, **kw)
    def forecast(self, lat, lng, hours=None, model=None, **kw): return self.get("forecast", lat=lat, lng=lng, hours=hours, model=model, **kw)
    def forecast_short(self, lat, lng, days=None, **kw): return self.get("forecast/short", lat=lat, lng=lng, days=days, **kw)
    def historical(self, lat, lng, metric, **kw): return self.get("historical", lat=lat, lng=lng, metric=metric, **kw)
    def climate(self, lat, lng, metric, **kw): return self.get("climate", lat=lat, lng=lng, metric=metric, **kw)
    def warnings(self, region, **kw): return self.get("warnings", region=region, **kw)
    def marine_forecast(self, lat, lng, **kw): return self.get("marine/forecast", lat=lat, lng=lng, **kw)
    def sst(self, lat, lng, **kw): return self.get("marine/sst", lat=lat, lng=lng, **kw)
    def air_quality(self, lat, lng, **kw): return self.get("air-quality", lat=lat, lng=lng, **kw)
    def pollen(self, lat, lng, **kw): return self.get("pollen", lat=lat, lng=lng, **kw)
    def sun(self, lat, lng, **kw): return self.get("sun", lat=lat, lng=lng, **kw)
    def uv(self, lat, lng, **kw): return self.get("uv", lat=lat, lng=lng, **kw)
    def solar(self, lat, lng, **kw): return self.get("solar", lat=lat, lng=lng, **kw)
    def geocode(self, q, **kw): return self.get("geocode", q=q, **kw)
    def typhoons(self, **kw): return self.get("typhoons", **kw)
    def space_weather(self, **kw): return self.get("space-weather", **kw)
    def aurora(self, lat, lng, **kw): return self.get("aurora", lat=lat, lng=lng, **kw)
    def earthquakes(self, **kw): return self.get("earthquakes", **kw)
    def tsunamis(self, **kw): return self.get("tsunamis", **kw)
    def volcanoes(self, **kw): return self.get("volcanoes", **kw)
    def avalanche(self, lat, lng, **kw): return self.get("avalanche", lat=lat, lng=lng, **kw)
