# This file was auto-generated by Fern from our API Definition.

import typing
from json.decoder import JSONDecodeError

from .....core.api_error import ApiError
from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from .....core.http_response import AsyncHttpResponse, HttpResponse
from .....core.pydantic_utilities import parse_obj_as
from .....core.request_options import RequestOptions
from .errors.invalid_content_type_error import InvalidContentTypeError
from .errors.too_many_requests_error import TooManyRequestsError
from .types.auth_get_token_response import AuthGetTokenResponse
from .types.invalid_content_type_error_type import InvalidContentTypeErrorType
from .types.too_many_requests_error_type import TooManyRequestsErrorType

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class RawDefaultClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._client_wrapper = client_wrapper

    def get_token(
        self, *, client_id: str, client_secret: str, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[AuthGetTokenResponse]:
        """
        <Callout intent="info">
        Candid Health SDKs automatically handle authentication workflows after configuring them with the `client_id` and
        `client_secret`.
        </Callout>

        Candid Health utilizes the [OAuth 2.0 bearer token authentication scheme](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) in our auth flow. You obtain the bearer token for all
        subsequent API requests via the `/auth/v2/token` endpoint defined below, which requires you to provide your `client_id` and `client_secret`. Your `client_id` and `client_secret` can be [generated](https://support.joincandidhealth.com/hc/en-us/articles/23065219476244--Generating-Candid-API-Keys) from the "Users & Credentials" tab by your org admin.

        The `/auth/v2/token` endpoint accepts both `Content-Type: application/json` and `Content-Type: application/x-www-form-urlencoded`. The request body should contain the `client_id` and `client_secret` as follows:

        ```json
        {
          "client_id": "YOUR_CLIENT_ID",
          "client_secret": "YOUR_CLIENT_SECRET"
        }
        ```
        or as URL-encoded form data:

        ```
        client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET
        ```

        The bearer token is a signed [JWT](https://jwt.io/). The public key for the JWT can be found [here](https://candidhealth.auth0.com/pem) for any verification workflows.

        The bearer token should be provided in the `Authorization` header for all subsequent API calls.

        <Callout intent="warning">
        The bearer token expires 5 hours after it has been created. After it has expired, the client will receive an "HTTP 401
        Unauthorized" error, at which point the client should generate a new token. It is important that tokens be reused between
        requests; if the client attempts to generate a token too often, it will be rate-limited and will receive an `HTTP 429 Too Many Requests` error.
        </Callout>

        Parameters
        ----------
        client_id : str
            Your application's Client ID.

        client_secret : str
            Your application's Client Secret.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[AuthGetTokenResponse]
        """
        _response = self._client_wrapper.httpx_client.request(
            "api/auth/v2/token",
            base_url=self._client_wrapper.get_environment().candid_api,
            method="POST",
            json={
                "client_id": client_id,
                "client_secret": client_secret,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        if 200 <= _response.status_code < 300:
            _data = typing.cast(
                AuthGetTokenResponse,
                parse_obj_as(
                    type_=AuthGetTokenResponse,  # type: ignore
                    object_=_response_json,
                ),
            )
            return HttpResponse(response=_response, data=_data)
        if "errorName" in _response_json:
            if _response_json["errorName"] == "TooManyRequestsError":
                raise TooManyRequestsError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        TooManyRequestsErrorType,
                        parse_obj_as(
                            type_=TooManyRequestsErrorType,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    ),
                )
            if _response_json["errorName"] == "InvalidContentTypeError":
                raise InvalidContentTypeError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        InvalidContentTypeErrorType,
                        parse_obj_as(
                            type_=InvalidContentTypeErrorType,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    ),
                )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)


class AsyncRawDefaultClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def get_token(
        self, *, client_id: str, client_secret: str, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[AuthGetTokenResponse]:
        """
        <Callout intent="info">
        Candid Health SDKs automatically handle authentication workflows after configuring them with the `client_id` and
        `client_secret`.
        </Callout>

        Candid Health utilizes the [OAuth 2.0 bearer token authentication scheme](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) in our auth flow. You obtain the bearer token for all
        subsequent API requests via the `/auth/v2/token` endpoint defined below, which requires you to provide your `client_id` and `client_secret`. Your `client_id` and `client_secret` can be [generated](https://support.joincandidhealth.com/hc/en-us/articles/23065219476244--Generating-Candid-API-Keys) from the "Users & Credentials" tab by your org admin.

        The `/auth/v2/token` endpoint accepts both `Content-Type: application/json` and `Content-Type: application/x-www-form-urlencoded`. The request body should contain the `client_id` and `client_secret` as follows:

        ```json
        {
          "client_id": "YOUR_CLIENT_ID",
          "client_secret": "YOUR_CLIENT_SECRET"
        }
        ```
        or as URL-encoded form data:

        ```
        client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET
        ```

        The bearer token is a signed [JWT](https://jwt.io/). The public key for the JWT can be found [here](https://candidhealth.auth0.com/pem) for any verification workflows.

        The bearer token should be provided in the `Authorization` header for all subsequent API calls.

        <Callout intent="warning">
        The bearer token expires 5 hours after it has been created. After it has expired, the client will receive an "HTTP 401
        Unauthorized" error, at which point the client should generate a new token. It is important that tokens be reused between
        requests; if the client attempts to generate a token too often, it will be rate-limited and will receive an `HTTP 429 Too Many Requests` error.
        </Callout>

        Parameters
        ----------
        client_id : str
            Your application's Client ID.

        client_secret : str
            Your application's Client Secret.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[AuthGetTokenResponse]
        """
        _response = await self._client_wrapper.httpx_client.request(
            "api/auth/v2/token",
            base_url=self._client_wrapper.get_environment().candid_api,
            method="POST",
            json={
                "client_id": client_id,
                "client_secret": client_secret,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        if 200 <= _response.status_code < 300:
            _data = typing.cast(
                AuthGetTokenResponse,
                parse_obj_as(
                    type_=AuthGetTokenResponse,  # type: ignore
                    object_=_response_json,
                ),
            )
            return AsyncHttpResponse(response=_response, data=_data)
        if "errorName" in _response_json:
            if _response_json["errorName"] == "TooManyRequestsError":
                raise TooManyRequestsError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        TooManyRequestsErrorType,
                        parse_obj_as(
                            type_=TooManyRequestsErrorType,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    ),
                )
            if _response_json["errorName"] == "InvalidContentTypeError":
                raise InvalidContentTypeError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        InvalidContentTypeErrorType,
                        parse_obj_as(
                            type_=InvalidContentTypeErrorType,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    ),
                )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
