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

import datetime as dt
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.jsonable_encoder import jsonable_encoder
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from .errors.bad_request_error import BadRequestError
from .errors.forbidden_error import ForbiddenError
from .errors.internal_server_error import InternalServerError
from .errors.not_found_error import NotFoundError
from .errors.unauthorized_error import UnauthorizedError
from .types.auth_method import AuthMethod
from .types.fhir_provider_delete_response import FhirProviderDeleteResponse
from .types.fhir_provider_list_response import FhirProviderListResponse
from .types.fhir_provider_remove_auth_config_response import FhirProviderRemoveAuthConfigResponse
from .types.fhir_provider_response import FhirProviderResponse
from .types.provider import Provider
from .types.role import Role
from .types.service_account_key import ServiceAccountKey

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


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

    def create(
        self,
        *,
        name: str,
        provider: Provider,
        auth_method: AuthMethod,
        base_url: str,
        description: typing.Optional[str] = OMIT,
        client_id: typing.Optional[str] = OMIT,
        client_secret: typing.Optional[str] = OMIT,
        service_account_key: typing.Optional[ServiceAccountKey] = OMIT,
        role: typing.Optional[Role] = OMIT,
        scopes: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[FhirProviderResponse]:
        """
        Creates a new FHIR provider configuration with authentication credentials.

        Note: The "sandbox" provider type cannot be created via this API - it is managed internally.

        Parameters
        ----------
        name : str
            Display name for the FHIR provider

        provider : Provider

        auth_method : AuthMethod

        base_url : str
            Base URL of the FHIR server

        description : typing.Optional[str]
            Optional description of the FHIR provider

        client_id : typing.Optional[str]
            OAuth client ID (required for most auth methods)

        client_secret : typing.Optional[str]
            OAuth client secret (required for client_secret and on_behalf_of auth methods)

        service_account_key : typing.Optional[ServiceAccountKey]

        role : typing.Optional[Role]

        scopes : typing.Optional[str]
            OAuth scopes to request. Cannot be specified with role. If neither role nor scopes are specified, the provider-specific default role will be used. You are solely responsible for ensuring the scopes are valid options for the provider being created or updated.

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

        Returns
        -------
        HttpResponse[FhirProviderResponse]
            FHIR provider created successfully
        """
        _response = self._client_wrapper.httpx_client.request(
            "fhir-provider",
            method="POST",
            json={
                "name": name,
                "description": description,
                "provider": provider,
                "auth_method": auth_method,
                "base_url": base_url,
                "client_id": client_id,
                "client_secret": client_secret,
                "service_account_key": convert_and_respect_annotation_metadata(
                    object_=service_account_key, annotation=ServiceAccountKey, direction="write"
                ),
                "role": role,
                "scopes": scopes,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    FhirProviderResponse,
                    parse_obj_as(
                        type_=FhirProviderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def list(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[FhirProviderListResponse]:
        """
        Retrieves a list of all active FHIR providers for the authenticated user.

        On shared instances, only sandbox providers are returned.
        Sandbox providers return FhirProviderSandboxInfo.

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

        Returns
        -------
        HttpResponse[FhirProviderListResponse]
            FHIR providers retrieved successfully
        """
        _response = self._client_wrapper.httpx_client.request(
            "fhir-provider/list",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    FhirProviderListResponse,
                    parse_obj_as(
                        type_=FhirProviderListResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get(
        self, fhir_provider_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[FhirProviderResponse]:
        """
        Retrieves a specific FHIR provider configuration by its ID.

        Sandbox providers return FhirProviderSandboxInfo.
        On shared instances, only sandbox providers can be accessed.

        Parameters
        ----------
        fhir_provider_id : str
            ID of the FHIR provider to retrieve

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

        Returns
        -------
        HttpResponse[FhirProviderResponse]
            FHIR provider retrieved successfully
        """
        _response = self._client_wrapper.httpx_client.request(
            f"fhir-provider/{jsonable_encoder(fhir_provider_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    FhirProviderResponse,
                    parse_obj_as(
                        type_=FhirProviderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def delete(
        self, fhir_provider_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[FhirProviderDeleteResponse]:
        """
        Soft deletes a FHIR provider by setting is_active to false.

        Note: Sandbox providers cannot be deleted.

        Parameters
        ----------
        fhir_provider_id : str
            ID of the FHIR provider to delete

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

        Returns
        -------
        HttpResponse[FhirProviderDeleteResponse]
            FHIR provider deleted successfully
        """
        _response = self._client_wrapper.httpx_client.request(
            f"fhir-provider/{jsonable_encoder(fhir_provider_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    FhirProviderDeleteResponse,
                    parse_obj_as(
                        type_=FhirProviderDeleteResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def add_auth_config(
        self,
        fhir_provider_id: str,
        *,
        auth_method: AuthMethod,
        client_secret: typing.Optional[str] = OMIT,
        service_account_key: typing.Optional[ServiceAccountKey] = OMIT,
        credential_expiry: typing.Optional[dt.datetime] = OMIT,
        role: typing.Optional[Role] = OMIT,
        scopes: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[FhirProviderResponse]:
        """
        Adds a new authentication configuration to an existing FHIR provider.
        This enables key rotation and multiple auth configurations per provider.

        Note: Sandbox providers cannot be modified.

        Parameters
        ----------
        fhir_provider_id : str
            ID of the FHIR provider to add auth config to

        auth_method : AuthMethod

        client_secret : typing.Optional[str]
            OAuth client secret (required for client_secret and on_behalf_of auth methods)

        service_account_key : typing.Optional[ServiceAccountKey]

        credential_expiry : typing.Optional[dt.datetime]
            Expiry time for JWT credentials (only applicable for JWT auth method)

        role : typing.Optional[Role]

        scopes : typing.Optional[str]
            OAuth scopes to request. Cannot be specified with role. If neither role nor scopes are specified, the provider-specific default role will be used. You are solely responsible for ensuring the scopes are valid options for the provider being created or updated.

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

        Returns
        -------
        HttpResponse[FhirProviderResponse]
            Auth configuration added successfully
        """
        _response = self._client_wrapper.httpx_client.request(
            f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/add-auth-config",
            method="PATCH",
            json={
                "auth_method": auth_method,
                "client_secret": client_secret,
                "service_account_key": convert_and_respect_annotation_metadata(
                    object_=service_account_key, annotation=ServiceAccountKey, direction="write"
                ),
                "credential_expiry": credential_expiry,
                "role": role,
                "scopes": scopes,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    FhirProviderResponse,
                    parse_obj_as(
                        type_=FhirProviderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def set_active_auth_config(
        self, fhir_provider_id: str, *, auth_config_id: str, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[FhirProviderResponse]:
        """
        Sets which authentication configuration should be active for a FHIR provider.
        Only one auth config can be active at a time.

        If the specified auth config is already active, the request succeeds without
        making any changes and returns a message indicating the config is already active.

        Note: Sandbox providers cannot be modified.

        Parameters
        ----------
        fhir_provider_id : str
            ID of the FHIR provider

        auth_config_id : str
            ID of the auth configuration to set as active

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

        Returns
        -------
        HttpResponse[FhirProviderResponse]
            Active auth configuration set successfully, or the config was already active.
            Check the message field to determine which case occurred.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/set-active-auth-config",
            method="PATCH",
            json={
                "auth_config_id": auth_config_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    FhirProviderResponse,
                    parse_obj_as(
                        type_=FhirProviderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def remove_auth_config(
        self, fhir_provider_id: str, *, auth_config_id: str, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[FhirProviderRemoveAuthConfigResponse]:
        """
        Removes an authentication configuration from a FHIR provider.
        Cannot remove the currently active auth configuration.

        Note: Sandbox providers cannot be modified.

        Parameters
        ----------
        fhir_provider_id : str
            ID of the FHIR provider

        auth_config_id : str
            ID of the auth configuration to remove

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

        Returns
        -------
        HttpResponse[FhirProviderRemoveAuthConfigResponse]
            Auth configuration removed successfully
        """
        _response = self._client_wrapper.httpx_client.request(
            f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/remove-auth-config",
            method="PATCH",
            json={
                "auth_config_id": auth_config_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    FhirProviderRemoveAuthConfigResponse,
                    parse_obj_as(
                        type_=FhirProviderRemoveAuthConfigResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)


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

    async def create(
        self,
        *,
        name: str,
        provider: Provider,
        auth_method: AuthMethod,
        base_url: str,
        description: typing.Optional[str] = OMIT,
        client_id: typing.Optional[str] = OMIT,
        client_secret: typing.Optional[str] = OMIT,
        service_account_key: typing.Optional[ServiceAccountKey] = OMIT,
        role: typing.Optional[Role] = OMIT,
        scopes: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[FhirProviderResponse]:
        """
        Creates a new FHIR provider configuration with authentication credentials.

        Note: The "sandbox" provider type cannot be created via this API - it is managed internally.

        Parameters
        ----------
        name : str
            Display name for the FHIR provider

        provider : Provider

        auth_method : AuthMethod

        base_url : str
            Base URL of the FHIR server

        description : typing.Optional[str]
            Optional description of the FHIR provider

        client_id : typing.Optional[str]
            OAuth client ID (required for most auth methods)

        client_secret : typing.Optional[str]
            OAuth client secret (required for client_secret and on_behalf_of auth methods)

        service_account_key : typing.Optional[ServiceAccountKey]

        role : typing.Optional[Role]

        scopes : typing.Optional[str]
            OAuth scopes to request. Cannot be specified with role. If neither role nor scopes are specified, the provider-specific default role will be used. You are solely responsible for ensuring the scopes are valid options for the provider being created or updated.

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

        Returns
        -------
        AsyncHttpResponse[FhirProviderResponse]
            FHIR provider created successfully
        """
        _response = await self._client_wrapper.httpx_client.request(
            "fhir-provider",
            method="POST",
            json={
                "name": name,
                "description": description,
                "provider": provider,
                "auth_method": auth_method,
                "base_url": base_url,
                "client_id": client_id,
                "client_secret": client_secret,
                "service_account_key": convert_and_respect_annotation_metadata(
                    object_=service_account_key, annotation=ServiceAccountKey, direction="write"
                ),
                "role": role,
                "scopes": scopes,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    FhirProviderResponse,
                    parse_obj_as(
                        type_=FhirProviderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def list(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[FhirProviderListResponse]:
        """
        Retrieves a list of all active FHIR providers for the authenticated user.

        On shared instances, only sandbox providers are returned.
        Sandbox providers return FhirProviderSandboxInfo.

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

        Returns
        -------
        AsyncHttpResponse[FhirProviderListResponse]
            FHIR providers retrieved successfully
        """
        _response = await self._client_wrapper.httpx_client.request(
            "fhir-provider/list",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    FhirProviderListResponse,
                    parse_obj_as(
                        type_=FhirProviderListResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get(
        self, fhir_provider_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[FhirProviderResponse]:
        """
        Retrieves a specific FHIR provider configuration by its ID.

        Sandbox providers return FhirProviderSandboxInfo.
        On shared instances, only sandbox providers can be accessed.

        Parameters
        ----------
        fhir_provider_id : str
            ID of the FHIR provider to retrieve

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

        Returns
        -------
        AsyncHttpResponse[FhirProviderResponse]
            FHIR provider retrieved successfully
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"fhir-provider/{jsonable_encoder(fhir_provider_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    FhirProviderResponse,
                    parse_obj_as(
                        type_=FhirProviderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def delete(
        self, fhir_provider_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[FhirProviderDeleteResponse]:
        """
        Soft deletes a FHIR provider by setting is_active to false.

        Note: Sandbox providers cannot be deleted.

        Parameters
        ----------
        fhir_provider_id : str
            ID of the FHIR provider to delete

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

        Returns
        -------
        AsyncHttpResponse[FhirProviderDeleteResponse]
            FHIR provider deleted successfully
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"fhir-provider/{jsonable_encoder(fhir_provider_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    FhirProviderDeleteResponse,
                    parse_obj_as(
                        type_=FhirProviderDeleteResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def add_auth_config(
        self,
        fhir_provider_id: str,
        *,
        auth_method: AuthMethod,
        client_secret: typing.Optional[str] = OMIT,
        service_account_key: typing.Optional[ServiceAccountKey] = OMIT,
        credential_expiry: typing.Optional[dt.datetime] = OMIT,
        role: typing.Optional[Role] = OMIT,
        scopes: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[FhirProviderResponse]:
        """
        Adds a new authentication configuration to an existing FHIR provider.
        This enables key rotation and multiple auth configurations per provider.

        Note: Sandbox providers cannot be modified.

        Parameters
        ----------
        fhir_provider_id : str
            ID of the FHIR provider to add auth config to

        auth_method : AuthMethod

        client_secret : typing.Optional[str]
            OAuth client secret (required for client_secret and on_behalf_of auth methods)

        service_account_key : typing.Optional[ServiceAccountKey]

        credential_expiry : typing.Optional[dt.datetime]
            Expiry time for JWT credentials (only applicable for JWT auth method)

        role : typing.Optional[Role]

        scopes : typing.Optional[str]
            OAuth scopes to request. Cannot be specified with role. If neither role nor scopes are specified, the provider-specific default role will be used. You are solely responsible for ensuring the scopes are valid options for the provider being created or updated.

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

        Returns
        -------
        AsyncHttpResponse[FhirProviderResponse]
            Auth configuration added successfully
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/add-auth-config",
            method="PATCH",
            json={
                "auth_method": auth_method,
                "client_secret": client_secret,
                "service_account_key": convert_and_respect_annotation_metadata(
                    object_=service_account_key, annotation=ServiceAccountKey, direction="write"
                ),
                "credential_expiry": credential_expiry,
                "role": role,
                "scopes": scopes,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    FhirProviderResponse,
                    parse_obj_as(
                        type_=FhirProviderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def set_active_auth_config(
        self, fhir_provider_id: str, *, auth_config_id: str, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[FhirProviderResponse]:
        """
        Sets which authentication configuration should be active for a FHIR provider.
        Only one auth config can be active at a time.

        If the specified auth config is already active, the request succeeds without
        making any changes and returns a message indicating the config is already active.

        Note: Sandbox providers cannot be modified.

        Parameters
        ----------
        fhir_provider_id : str
            ID of the FHIR provider

        auth_config_id : str
            ID of the auth configuration to set as active

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

        Returns
        -------
        AsyncHttpResponse[FhirProviderResponse]
            Active auth configuration set successfully, or the config was already active.
            Check the message field to determine which case occurred.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/set-active-auth-config",
            method="PATCH",
            json={
                "auth_config_id": auth_config_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    FhirProviderResponse,
                    parse_obj_as(
                        type_=FhirProviderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def remove_auth_config(
        self, fhir_provider_id: str, *, auth_config_id: str, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[FhirProviderRemoveAuthConfigResponse]:
        """
        Removes an authentication configuration from a FHIR provider.
        Cannot remove the currently active auth configuration.

        Note: Sandbox providers cannot be modified.

        Parameters
        ----------
        fhir_provider_id : str
            ID of the FHIR provider

        auth_config_id : str
            ID of the auth configuration to remove

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

        Returns
        -------
        AsyncHttpResponse[FhirProviderRemoveAuthConfigResponse]
            Auth configuration removed successfully
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/remove-auth-config",
            method="PATCH",
            json={
                "auth_config_id": auth_config_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    FhirProviderRemoveAuthConfigResponse,
                    parse_obj_as(
                        type_=FhirProviderRemoveAuthConfigResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
