from __future__ import annotations

import base64
import hashlib
import time

import httpx
import jwt


class MiauClient:
    def __init__(self, *, api_url: str, app_secret: str) -> None:
        if not api_url or not app_secret:
            raise ValueError(
                "Invalid MiauClient configuration. Please provide api_url and app_secret."
            )

        self._api_url = api_url
        self._app_secret = app_secret
        self._jwt_token: str | None = None
        self._http = httpx.Client(timeout=10.0)

        api_key = app_secret[7:32]
        hashed_secret = hashlib.sha256(app_secret.encode()).hexdigest()
        self._basic_auth_token = base64.b64encode(
            f"{api_key}:{hashed_secret}".encode()
        ).decode()

    def close(self) -> None:
        self._http.close()

    def __enter__(self) -> MiauClient:
        return self

    def __exit__(self, *args: object) -> None:
        self.close()

    def get_token(self) -> str:
        if self._jwt_token:
            decoded = jwt.decode(
                self._jwt_token, options={"verify_signature": False}
            )
            one_minute_from_now = int(time.time()) + 60

            if decoded["exp"] > one_minute_from_now:
                return self._jwt_token

        response = self._http.get(
            f"{self._api_url}/v1/oauth/token",
            headers={
                "Authorization": f"Basic {self._basic_auth_token}",
                "Content-Type": "application/json",
            },
        )

        data = response.json()

        if response.status_code != 200:
            error_message = (
                data.get("message")
                or data.get("error_description")
                or f"OAuth error: {data.get('error', '')}"
                or "Failed to fetch JWT token"
            )
            raise RuntimeError(error_message)

        self._jwt_token = data["access_token"]
        return self._jwt_token
