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

import typing
from ...core.client_wrapper import SyncClientWrapper
from ...entity_group_types.types.entity_group_id import EntityGroupId
from ...entity_types.types.entity_user_id import EntityUserId
from ...core.request_options import RequestOptions
from ...entity_group_types.types.find_entity_group_user_response import FindEntityGroupUserResponse
from ...core.jsonable_encoder import jsonable_encoder
from json.decoder import JSONDecodeError
from ...core.api_error import ApiError
from ...core.pydantic_utilities import parse_obj_as
from ...commons.errors.bad_request import BadRequest
from ...commons.errors.unauthorized import Unauthorized
from ...commons.errors.forbidden import Forbidden
from ...commons.errors.not_found import NotFound
from ...commons.errors.conflict import Conflict
from ...commons.errors.internal_server_error import InternalServerError
from ...commons.errors.unimplemented import Unimplemented
from ...entity_group_types.types.entity_group_user_request import EntityGroupUserRequest
from ...entity_group_types.types.entity_group_user_response import EntityGroupUserResponse
from ...entity_types.types.token_generation_options import TokenGenerationOptions
from ...core.client_wrapper import AsyncClientWrapper

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


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

    def find(
        self,
        entity_group_id: EntityGroupId,
        *,
        foreign_id: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        role: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        name: typing.Optional[str] = None,
        email: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        starting_after: typing.Optional[EntityUserId] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> FindEntityGroupUserResponse:
        """
        Search entity group users

        Parameters
        ----------
        entity_group_id : EntityGroupId
            Entity Group ID or Entity Group ForeignID

        foreign_id : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            ID used to identify user in your system

        role : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            Filter users by role. If multiple roles are provided, users with any of the roles will be returned.

        name : typing.Optional[str]
            Filter users by name. Partial matches are supported.

        email : typing.Optional[str]
            Filter users by email. Partial matches are supported.

        limit : typing.Optional[int]
            Number of entities to return. Limit can range between 1 and 100, and the default is 10.

        starting_after : typing.Optional[EntityUserId]
            The ID of the user to start after. If not provided, the first page of entities will be returned.

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

        Returns
        -------
        FindEntityGroupUserResponse

        Examples
        --------
        from mercoa import Mercoa

        client = Mercoa(
            token="YOUR_TOKEN",
        )
        client.entity_group.user.find(
            entity_group_id="entg_8545a84e-a45f-41bf-bdf1-33b42a55812c",
            name="John",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"entityGroup/{jsonable_encoder(entity_group_id)}/users",
            method="GET",
            params={
                "foreignId": foreign_id,
                "role": role,
                "name": name,
                "email": email,
                "limit": limit,
                "startingAfter": starting_after,
            },
            request_options=request_options,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return typing.cast(
                FindEntityGroupUserResponse,
                parse_obj_as(
                    type_=FindEntityGroupUserResponse,  # type: ignore
                    object_=_response_json,
                ),
            )
        if "errorName" in _response_json:
            if _response_json["errorName"] == "BadRequest":
                raise BadRequest(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unauthorized":
                raise Unauthorized(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Forbidden":
                raise Forbidden(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "NotFound":
                raise NotFound(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Conflict":
                raise Conflict(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "InternalServerError":
                raise InternalServerError(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unimplemented":
                raise Unimplemented(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def create(
        self,
        entity_group_id: EntityGroupId,
        *,
        request: EntityGroupUserRequest,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> EntityGroupUserResponse:
        """
        Create entity user that will be added to all entities in the group.

        Parameters
        ----------
        entity_group_id : EntityGroupId
            Entity Group ID or Entity Group ForeignID

        request : EntityGroupUserRequest

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

        Returns
        -------
        EntityGroupUserResponse

        Examples
        --------
        from mercoa import Mercoa
        from mercoa.entity_group_types import (
            EntityGroupUserEntityRequest,
            EntityGroupUserRequest,
        )

        client = Mercoa(
            token="YOUR_TOKEN",
        )
        client.entity_group.user.create(
            entity_group_id="entg_8545a84e-a45f-41bf-bdf1-33b42a55812c",
            request=EntityGroupUserRequest(
                foreign_id="MY-DB-ID-12345",
                email="john.doe@acme.com",
                name="John Doe",
                entities=[
                    EntityGroupUserEntityRequest(
                        roles=["admin", "approver"],
                        entity_id="ent_21661ac1-a2a8-4465-a6c0-64474ba8181d",
                    ),
                    EntityGroupUserEntityRequest(
                        roles=["viewer"],
                        entity_id="ent_9e02a20e-7749-47de-8d8a-f8ff2859fa90",
                    ),
                ],
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"entityGroup/{jsonable_encoder(entity_group_id)}/user",
            method="POST",
            json=request,
            request_options=request_options,
            omit=OMIT,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return typing.cast(
                EntityGroupUserResponse,
                parse_obj_as(
                    type_=EntityGroupUserResponse,  # type: ignore
                    object_=_response_json,
                ),
            )
        if "errorName" in _response_json:
            if _response_json["errorName"] == "BadRequest":
                raise BadRequest(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unauthorized":
                raise Unauthorized(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Forbidden":
                raise Forbidden(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "NotFound":
                raise NotFound(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Conflict":
                raise Conflict(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "InternalServerError":
                raise InternalServerError(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unimplemented":
                raise Unimplemented(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def get(
        self,
        entity_group_id: EntityGroupId,
        foreign_id: str,
        *,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> EntityGroupUserResponse:
        """
        Get entity user from a group

        Parameters
        ----------
        entity_group_id : EntityGroupId
            Entity Group ID or Entity Group ForeignID

        foreign_id : str
            ID used to identify user in your system

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

        Returns
        -------
        EntityGroupUserResponse

        Examples
        --------
        from mercoa import Mercoa

        client = Mercoa(
            token="YOUR_TOKEN",
        )
        client.entity_group.user.get(
            entity_group_id="entg_8545a84e-a45f-41bf-bdf1-33b42a55812c",
            foreign_id="MY-DB-ID-12345",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"entityGroup/{jsonable_encoder(entity_group_id)}/user/{jsonable_encoder(foreign_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return typing.cast(
                EntityGroupUserResponse,
                parse_obj_as(
                    type_=EntityGroupUserResponse,  # type: ignore
                    object_=_response_json,
                ),
            )
        if "errorName" in _response_json:
            if _response_json["errorName"] == "BadRequest":
                raise BadRequest(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unauthorized":
                raise Unauthorized(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Forbidden":
                raise Forbidden(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "NotFound":
                raise NotFound(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Conflict":
                raise Conflict(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "InternalServerError":
                raise InternalServerError(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unimplemented":
                raise Unimplemented(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def update(
        self,
        entity_group_id: EntityGroupId,
        foreign_id: str,
        *,
        request: EntityGroupUserRequest,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> EntityGroupUserResponse:
        """
        Update entity user for all entities in the group.

        Parameters
        ----------
        entity_group_id : EntityGroupId
            Entity Group ID or Entity Group ForeignID

        foreign_id : str
            ID used to identify user in your system

        request : EntityGroupUserRequest

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

        Returns
        -------
        EntityGroupUserResponse

        Examples
        --------
        from mercoa import Mercoa
        from mercoa.entity_group_types import (
            EntityGroupUserEntityRequest,
            EntityGroupUserRequest,
        )

        client = Mercoa(
            token="YOUR_TOKEN",
        )
        client.entity_group.user.update(
            entity_group_id="entg_8545a84e-a45f-41bf-bdf1-33b42a55812c",
            foreign_id="MY-DB-ID-12345",
            request=EntityGroupUserRequest(
                foreign_id="MY-DB-ID-12345",
                email="john.doe@acme.com",
                name="John Doe",
                entities=[
                    EntityGroupUserEntityRequest(
                        roles=["admin", "approver"],
                        entity_id="ent_21661ac1-a2a8-4465-a6c0-64474ba8181d",
                    ),
                    EntityGroupUserEntityRequest(
                        roles=["viewer"],
                        entity_id="ent_9e02a20e-7749-47de-8d8a-f8ff2859fa90",
                    ),
                ],
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"entityGroup/{jsonable_encoder(entity_group_id)}/user/{jsonable_encoder(foreign_id)}",
            method="POST",
            json=request,
            request_options=request_options,
            omit=OMIT,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return typing.cast(
                EntityGroupUserResponse,
                parse_obj_as(
                    type_=EntityGroupUserResponse,  # type: ignore
                    object_=_response_json,
                ),
            )
        if "errorName" in _response_json:
            if _response_json["errorName"] == "BadRequest":
                raise BadRequest(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unauthorized":
                raise Unauthorized(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Forbidden":
                raise Forbidden(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "NotFound":
                raise NotFound(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Conflict":
                raise Conflict(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "InternalServerError":
                raise InternalServerError(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unimplemented":
                raise Unimplemented(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def delete(
        self,
        entity_group_id: EntityGroupId,
        foreign_id: str,
        *,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Delete entity user from all entities in the group. This will also remove the user from all approval policies. If an approval policy will break as a result of this operation, this request will fail.

        Parameters
        ----------
        entity_group_id : EntityGroupId
            Entity Group ID or Entity Group ForeignID

        foreign_id : str
            ID used to identify user in your system

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

        Returns
        -------
        None

        Examples
        --------
        from mercoa import Mercoa

        client = Mercoa(
            token="YOUR_TOKEN",
        )
        client.entity_group.user.delete(
            entity_group_id="string",
            foreign_id="string",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"entityGroup/{jsonable_encoder(entity_group_id)}/user/{jsonable_encoder(foreign_id)}",
            method="DELETE",
            request_options=request_options,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if "errorName" in _response_json:
            if _response_json["errorName"] == "BadRequest":
                raise BadRequest(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unauthorized":
                raise Unauthorized(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Forbidden":
                raise Forbidden(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "NotFound":
                raise NotFound(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Conflict":
                raise Conflict(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "InternalServerError":
                raise InternalServerError(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unimplemented":
                raise Unimplemented(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def get_token(
        self,
        entity_group_id: EntityGroupId,
        foreign_id: str,
        *,
        request: TokenGenerationOptions,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> str:
        """
        Generate a JWT token for an entity group with the given options. This token can be used to authenticate to any entity in the entity group as the user in the Mercoa API and iFrame.

        Parameters
        ----------
        entity_group_id : EntityGroupId
            Entity Group ID or Entity Group ForeignID

        foreign_id : str
            ID used to identify user in your system

        request : TokenGenerationOptions

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

        Returns
        -------
        str

        Examples
        --------
        from mercoa import Mercoa
        from mercoa.entity_types import TokenGenerationOptions

        client = Mercoa(
            token="YOUR_TOKEN",
        )
        client.entity_group.user.get_token(
            entity_group_id="entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced",
            foreign_id="MY-DB-ID-12345",
            request=TokenGenerationOptions(
                expires_in="1h",
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"entityGroup/{jsonable_encoder(entity_group_id)}/user/{jsonable_encoder(foreign_id)}/token",
            method="POST",
            json=request,
            request_options=request_options,
            omit=OMIT,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return typing.cast(
                str,
                parse_obj_as(
                    type_=str,  # type: ignore
                    object_=_response_json,
                ),
            )
        if "errorName" in _response_json:
            if _response_json["errorName"] == "BadRequest":
                raise BadRequest(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unauthorized":
                raise Unauthorized(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Forbidden":
                raise Forbidden(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "NotFound":
                raise NotFound(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Conflict":
                raise Conflict(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "InternalServerError":
                raise InternalServerError(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unimplemented":
                raise Unimplemented(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)


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

    async def find(
        self,
        entity_group_id: EntityGroupId,
        *,
        foreign_id: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        role: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        name: typing.Optional[str] = None,
        email: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        starting_after: typing.Optional[EntityUserId] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> FindEntityGroupUserResponse:
        """
        Search entity group users

        Parameters
        ----------
        entity_group_id : EntityGroupId
            Entity Group ID or Entity Group ForeignID

        foreign_id : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            ID used to identify user in your system

        role : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            Filter users by role. If multiple roles are provided, users with any of the roles will be returned.

        name : typing.Optional[str]
            Filter users by name. Partial matches are supported.

        email : typing.Optional[str]
            Filter users by email. Partial matches are supported.

        limit : typing.Optional[int]
            Number of entities to return. Limit can range between 1 and 100, and the default is 10.

        starting_after : typing.Optional[EntityUserId]
            The ID of the user to start after. If not provided, the first page of entities will be returned.

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

        Returns
        -------
        FindEntityGroupUserResponse

        Examples
        --------
        import asyncio

        from mercoa import AsyncMercoa

        client = AsyncMercoa(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.entity_group.user.find(
                entity_group_id="entg_8545a84e-a45f-41bf-bdf1-33b42a55812c",
                name="John",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"entityGroup/{jsonable_encoder(entity_group_id)}/users",
            method="GET",
            params={
                "foreignId": foreign_id,
                "role": role,
                "name": name,
                "email": email,
                "limit": limit,
                "startingAfter": starting_after,
            },
            request_options=request_options,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return typing.cast(
                FindEntityGroupUserResponse,
                parse_obj_as(
                    type_=FindEntityGroupUserResponse,  # type: ignore
                    object_=_response_json,
                ),
            )
        if "errorName" in _response_json:
            if _response_json["errorName"] == "BadRequest":
                raise BadRequest(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unauthorized":
                raise Unauthorized(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Forbidden":
                raise Forbidden(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "NotFound":
                raise NotFound(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Conflict":
                raise Conflict(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "InternalServerError":
                raise InternalServerError(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unimplemented":
                raise Unimplemented(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def create(
        self,
        entity_group_id: EntityGroupId,
        *,
        request: EntityGroupUserRequest,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> EntityGroupUserResponse:
        """
        Create entity user that will be added to all entities in the group.

        Parameters
        ----------
        entity_group_id : EntityGroupId
            Entity Group ID or Entity Group ForeignID

        request : EntityGroupUserRequest

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

        Returns
        -------
        EntityGroupUserResponse

        Examples
        --------
        import asyncio

        from mercoa import AsyncMercoa
        from mercoa.entity_group_types import (
            EntityGroupUserEntityRequest,
            EntityGroupUserRequest,
        )

        client = AsyncMercoa(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.entity_group.user.create(
                entity_group_id="entg_8545a84e-a45f-41bf-bdf1-33b42a55812c",
                request=EntityGroupUserRequest(
                    foreign_id="MY-DB-ID-12345",
                    email="john.doe@acme.com",
                    name="John Doe",
                    entities=[
                        EntityGroupUserEntityRequest(
                            roles=["admin", "approver"],
                            entity_id="ent_21661ac1-a2a8-4465-a6c0-64474ba8181d",
                        ),
                        EntityGroupUserEntityRequest(
                            roles=["viewer"],
                            entity_id="ent_9e02a20e-7749-47de-8d8a-f8ff2859fa90",
                        ),
                    ],
                ),
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"entityGroup/{jsonable_encoder(entity_group_id)}/user",
            method="POST",
            json=request,
            request_options=request_options,
            omit=OMIT,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return typing.cast(
                EntityGroupUserResponse,
                parse_obj_as(
                    type_=EntityGroupUserResponse,  # type: ignore
                    object_=_response_json,
                ),
            )
        if "errorName" in _response_json:
            if _response_json["errorName"] == "BadRequest":
                raise BadRequest(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unauthorized":
                raise Unauthorized(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Forbidden":
                raise Forbidden(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "NotFound":
                raise NotFound(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Conflict":
                raise Conflict(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "InternalServerError":
                raise InternalServerError(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unimplemented":
                raise Unimplemented(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def get(
        self,
        entity_group_id: EntityGroupId,
        foreign_id: str,
        *,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> EntityGroupUserResponse:
        """
        Get entity user from a group

        Parameters
        ----------
        entity_group_id : EntityGroupId
            Entity Group ID or Entity Group ForeignID

        foreign_id : str
            ID used to identify user in your system

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

        Returns
        -------
        EntityGroupUserResponse

        Examples
        --------
        import asyncio

        from mercoa import AsyncMercoa

        client = AsyncMercoa(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.entity_group.user.get(
                entity_group_id="entg_8545a84e-a45f-41bf-bdf1-33b42a55812c",
                foreign_id="MY-DB-ID-12345",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"entityGroup/{jsonable_encoder(entity_group_id)}/user/{jsonable_encoder(foreign_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return typing.cast(
                EntityGroupUserResponse,
                parse_obj_as(
                    type_=EntityGroupUserResponse,  # type: ignore
                    object_=_response_json,
                ),
            )
        if "errorName" in _response_json:
            if _response_json["errorName"] == "BadRequest":
                raise BadRequest(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unauthorized":
                raise Unauthorized(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Forbidden":
                raise Forbidden(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "NotFound":
                raise NotFound(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Conflict":
                raise Conflict(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "InternalServerError":
                raise InternalServerError(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unimplemented":
                raise Unimplemented(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def update(
        self,
        entity_group_id: EntityGroupId,
        foreign_id: str,
        *,
        request: EntityGroupUserRequest,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> EntityGroupUserResponse:
        """
        Update entity user for all entities in the group.

        Parameters
        ----------
        entity_group_id : EntityGroupId
            Entity Group ID or Entity Group ForeignID

        foreign_id : str
            ID used to identify user in your system

        request : EntityGroupUserRequest

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

        Returns
        -------
        EntityGroupUserResponse

        Examples
        --------
        import asyncio

        from mercoa import AsyncMercoa
        from mercoa.entity_group_types import (
            EntityGroupUserEntityRequest,
            EntityGroupUserRequest,
        )

        client = AsyncMercoa(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.entity_group.user.update(
                entity_group_id="entg_8545a84e-a45f-41bf-bdf1-33b42a55812c",
                foreign_id="MY-DB-ID-12345",
                request=EntityGroupUserRequest(
                    foreign_id="MY-DB-ID-12345",
                    email="john.doe@acme.com",
                    name="John Doe",
                    entities=[
                        EntityGroupUserEntityRequest(
                            roles=["admin", "approver"],
                            entity_id="ent_21661ac1-a2a8-4465-a6c0-64474ba8181d",
                        ),
                        EntityGroupUserEntityRequest(
                            roles=["viewer"],
                            entity_id="ent_9e02a20e-7749-47de-8d8a-f8ff2859fa90",
                        ),
                    ],
                ),
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"entityGroup/{jsonable_encoder(entity_group_id)}/user/{jsonable_encoder(foreign_id)}",
            method="POST",
            json=request,
            request_options=request_options,
            omit=OMIT,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return typing.cast(
                EntityGroupUserResponse,
                parse_obj_as(
                    type_=EntityGroupUserResponse,  # type: ignore
                    object_=_response_json,
                ),
            )
        if "errorName" in _response_json:
            if _response_json["errorName"] == "BadRequest":
                raise BadRequest(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unauthorized":
                raise Unauthorized(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Forbidden":
                raise Forbidden(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "NotFound":
                raise NotFound(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Conflict":
                raise Conflict(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "InternalServerError":
                raise InternalServerError(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unimplemented":
                raise Unimplemented(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def delete(
        self,
        entity_group_id: EntityGroupId,
        foreign_id: str,
        *,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Delete entity user from all entities in the group. This will also remove the user from all approval policies. If an approval policy will break as a result of this operation, this request will fail.

        Parameters
        ----------
        entity_group_id : EntityGroupId
            Entity Group ID or Entity Group ForeignID

        foreign_id : str
            ID used to identify user in your system

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

        Returns
        -------
        None

        Examples
        --------
        import asyncio

        from mercoa import AsyncMercoa

        client = AsyncMercoa(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.entity_group.user.delete(
                entity_group_id="string",
                foreign_id="string",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"entityGroup/{jsonable_encoder(entity_group_id)}/user/{jsonable_encoder(foreign_id)}",
            method="DELETE",
            request_options=request_options,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if "errorName" in _response_json:
            if _response_json["errorName"] == "BadRequest":
                raise BadRequest(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unauthorized":
                raise Unauthorized(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Forbidden":
                raise Forbidden(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "NotFound":
                raise NotFound(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Conflict":
                raise Conflict(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "InternalServerError":
                raise InternalServerError(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unimplemented":
                raise Unimplemented(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def get_token(
        self,
        entity_group_id: EntityGroupId,
        foreign_id: str,
        *,
        request: TokenGenerationOptions,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> str:
        """
        Generate a JWT token for an entity group with the given options. This token can be used to authenticate to any entity in the entity group as the user in the Mercoa API and iFrame.

        Parameters
        ----------
        entity_group_id : EntityGroupId
            Entity Group ID or Entity Group ForeignID

        foreign_id : str
            ID used to identify user in your system

        request : TokenGenerationOptions

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

        Returns
        -------
        str

        Examples
        --------
        import asyncio

        from mercoa import AsyncMercoa
        from mercoa.entity_types import TokenGenerationOptions

        client = AsyncMercoa(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.entity_group.user.get_token(
                entity_group_id="entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced",
                foreign_id="MY-DB-ID-12345",
                request=TokenGenerationOptions(
                    expires_in="1h",
                ),
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"entityGroup/{jsonable_encoder(entity_group_id)}/user/{jsonable_encoder(foreign_id)}/token",
            method="POST",
            json=request,
            request_options=request_options,
            omit=OMIT,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return typing.cast(
                str,
                parse_obj_as(
                    type_=str,  # type: ignore
                    object_=_response_json,
                ),
            )
        if "errorName" in _response_json:
            if _response_json["errorName"] == "BadRequest":
                raise BadRequest(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unauthorized":
                raise Unauthorized(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Forbidden":
                raise Forbidden(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "NotFound":
                raise NotFound(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Conflict":
                raise Conflict(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "InternalServerError":
                raise InternalServerError(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
            if _response_json["errorName"] == "Unimplemented":
                raise Unimplemented(
                    typing.cast(
                        str,
                        parse_obj_as(
                            type_=str,  # type: ignore
                            object_=_response_json["content"],
                        ),
                    )
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)
