# This file was auto-generated by Fern from our API Definition.
# Modified by Auth0 to use Auth0 telemetry format with dynamic versioning

import base64
import platform
import sys
import typing
from json import dumps

import httpx
from .http_client import AsyncHttpClient, HttpClient
from .logging import LogConfig, Logger


class BaseClientWrapper:
    def __init__(
        self,
        *,
        token: typing.Union[str, typing.Callable[[], str]],
        headers: typing.Optional[typing.Dict[str, str]] = None,
        base_url: str,
        timeout: typing.Optional[float] = None,
        max_retries: int = 2,
        stream_reconnection_enabled: typing.Optional[bool] = None,
        max_stream_reconnection_attempts: typing.Optional[int] = None,
        logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
    ):
        self._token = token
        self._headers = headers
        self._base_url = base_url
        self._timeout = timeout
        self._max_retries = max_retries
        self._stream_reconnection_enabled = stream_reconnection_enabled
        self._max_stream_reconnection_attempts = max_stream_reconnection_attempts
        self._logging = logging

    def get_headers(self) -> typing.Dict[str, str]:
        py_version = platform.python_version()
        version = sys.modules["auth0"].__version__

        auth0_client = dumps({
            "name": "auth0-python",
            "version": version,
            "env": {"python": py_version}
        }).encode("utf-8")

        headers: typing.Dict[str, str] = {
            "User-Agent": f"Python/{py_version}",
            "Auth0-Client": base64.b64encode(auth0_client).decode(),
            **(self.get_custom_headers() or {}),
        }
        headers["Authorization"] = f"Bearer {self._get_token()}"
        return headers

    def _get_token(self) -> str:
        if isinstance(self._token, str):
            return self._token
        else:
            return self._token()

    def get_custom_headers(self) -> typing.Optional[typing.Dict[str, str]]:
        return self._headers

    def get_base_url(self) -> str:
        return self._base_url

    def get_timeout(self) -> typing.Optional[float]:
        return self._timeout

    def get_max_retries(self) -> int:
        return self._max_retries

    def get_stream_reconnection_enabled(self) -> bool:
        return self._stream_reconnection_enabled if self._stream_reconnection_enabled is not None else True

    def get_max_stream_reconnection_attempts(self) -> typing.Optional[int]:
        return self._max_stream_reconnection_attempts


class SyncClientWrapper(BaseClientWrapper):
    def __init__(
        self,
        *,
        token: typing.Union[str, typing.Callable[[], str]],
        headers: typing.Optional[typing.Dict[str, str]] = None,
        base_url: str,
        timeout: typing.Optional[float] = None,
        max_retries: int = 2,
        stream_reconnection_enabled: typing.Optional[bool] = None,
        max_stream_reconnection_attempts: typing.Optional[int] = None,
        logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
        httpx_client: httpx.Client,
    ):
        super().__init__(
            token=token,
            headers=headers,
            base_url=base_url,
            timeout=timeout,
            max_retries=max_retries,
            stream_reconnection_enabled=stream_reconnection_enabled,
            max_stream_reconnection_attempts=max_stream_reconnection_attempts,
            logging=logging,
        )
        self.httpx_client = HttpClient(
            httpx_client=httpx_client,
            base_headers=self.get_headers,
            base_timeout=self.get_timeout,
            base_url=self.get_base_url,
            base_max_retries=self.get_max_retries(),
            logging_config=self._logging,
        )


class AsyncClientWrapper(BaseClientWrapper):
    def __init__(
        self,
        *,
        token: typing.Union[str, typing.Callable[[], str]],
        headers: typing.Optional[typing.Dict[str, str]] = None,
        base_url: str,
        timeout: typing.Optional[float] = None,
        max_retries: int = 2,
        stream_reconnection_enabled: typing.Optional[bool] = None,
        max_stream_reconnection_attempts: typing.Optional[int] = None,
        logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
        async_token: typing.Optional[typing.Callable[[], typing.Awaitable[str]]] = None,
        httpx_client: httpx.AsyncClient,
    ):
        super().__init__(
            token=token,
            headers=headers,
            base_url=base_url,
            timeout=timeout,
            max_retries=max_retries,
            stream_reconnection_enabled=stream_reconnection_enabled,
            max_stream_reconnection_attempts=max_stream_reconnection_attempts,
            logging=logging,
        )
        self._async_token = async_token
        self.httpx_client = AsyncHttpClient(
            httpx_client=httpx_client,
            base_headers=self.get_headers,
            base_timeout=self.get_timeout,
            base_url=self.get_base_url,
            base_max_retries=self.get_max_retries(),
            async_base_headers=self.async_get_headers,
            logging_config=self._logging,
        )

    async def async_get_headers(self) -> typing.Dict[str, str]:
        headers = self.get_headers()
        if self._async_token is not None:
            token = await self._async_token()
            headers["Authorization"] = f"Bearer {token}"
        return headers
