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

import typing
from json.decoder import JSONDecodeError

from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.jsonable_encoder import encode_path_param
from ..core.pagination import AsyncPager, SyncPager
from ..core.parse_error import ParsingError
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..errors.bad_request_error import BadRequestError
from ..errors.conflict_error import ConflictError
from ..errors.forbidden_error import ForbiddenError
from ..errors.not_found_error import NotFoundError
from ..errors.service_unavailable_error import ServiceUnavailableError
from ..errors.too_many_requests_error import TooManyRequestsError
from ..errors.unauthorized_error import UnauthorizedError
from ..types.app_metadata import AppMetadata
from ..types.create_user_response_content import CreateUserResponseContent
from ..types.get_user_response_content import GetUserResponseContent
from ..types.list_users_offset_paginated_response_content import ListUsersOffsetPaginatedResponseContent
from ..types.regenerate_users_recovery_code_response_content import RegenerateUsersRecoveryCodeResponseContent
from ..types.search_engine_versions_enum import SearchEngineVersionsEnum
from ..types.update_user_response_content import UpdateUserResponseContent
from ..types.user_metadata import UserMetadata
from ..types.user_response_schema import UserResponseSchema
from pydantic import ValidationError

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


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

    def list(
        self,
        *,
        page: typing.Optional[int] = 0,
        per_page: typing.Optional[int] = 50,
        include_totals: typing.Optional[bool] = True,
        sort: typing.Optional[str] = None,
        connection: typing.Optional[str] = None,
        fields: typing.Optional[str] = None,
        include_fields: typing.Optional[bool] = None,
        q: typing.Optional[str] = None,
        search_engine: typing.Optional[SearchEngineVersionsEnum] = None,
        primary_order: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SyncPager[UserResponseSchema, ListUsersOffsetPaginatedResponseContent]:
        """
        Retrieve details of users. It is possible to:

        - Specify a search criteria for users
        - Sort the users to be returned
        - Select the fields to be returned
        - Specify the number of users to retrieve per page and the page index



        The `q` query parameter can be used to get users that match the specified criteria [using query string syntax.](https://auth0.com/docs/users/search/v3/query-syntax)

        [Learn more about searching for users.](https://auth0.com/docs/users/search/v3)

        Read about [best practices](https://auth0.com/docs/users/search/best-practices) when working with the API endpoints for retrieving users.



        Auth0 limits the number of users you can return. If you exceed this threshold, please redefine your search, use the [export job](https://auth0.com/docs/api/management/v2#!/Jobs/post_users_exports), or the [User Import / Export](https://auth0.com/docs/extensions/user-import-export) extension.

        Parameters
        ----------
        page : typing.Optional[int]
            Page index of the results to return. First page is 0.

        per_page : typing.Optional[int]
            Number of results per page.

        include_totals : typing.Optional[bool]
            Return results inside an object that contains the total result count (true) or as a direct array of results (false, default).

        sort : typing.Optional[str]
            Field to sort by. Use <code>field:order</code> where order is <code>1</code> for ascending and <code>-1</code> for descending. e.g. <code>created_at:1</code>

        connection : typing.Optional[str]
            Connection filter. Only applies when using <code>search_engine=v1</code>. To filter by connection with <code>search_engine=v2|v3</code>, use <code>q=identities.connection:"connection_name"</code>

        fields : typing.Optional[str]
            Comma-separated list of fields to include or exclude (based on value provided for include_fields) in the result. Leave empty to retrieve all fields.

        include_fields : typing.Optional[bool]
            Whether specified fields are to be included (true) or excluded (false).

        q : typing.Optional[str]
            Query in <a target='_new' href ='https://lucene.apache.org/core/2_9_4/queryparsersyntax.html'>Lucene query string syntax</a>. Some query types cannot be used on metadata fields, for details see <a href='https://auth0.com/docs/users/search/v3/query-syntax#searchable-fields'>Searchable Fields</a>.

        search_engine : typing.Optional[SearchEngineVersionsEnum]
            The version of the search engine

        primary_order : typing.Optional[bool]
            If true (default), results are returned in a deterministic order. If false, results may be returned in a non-deterministic order, which can enhance performance for complex queries targeting a small number of users. Set to false only when consistent ordering and pagination is not required.

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

        Returns
        -------
        SyncPager[UserResponseSchema, ListUsersOffsetPaginatedResponseContent]
            Users successfully retrieved.
        """
        page = page if page is not None else 0

        _response = self._client_wrapper.httpx_client.request(
            "users",
            method="GET",
            params={
                "page": page,
                "per_page": per_page,
                "include_totals": include_totals,
                "sort": sort,
                "connection": connection,
                "fields": fields,
                "include_fields": include_fields,
                "q": q,
                "search_engine": search_engine,
                "primary_order": primary_order,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    ListUsersOffsetPaginatedResponseContent,
                    parse_obj_as(
                        type_=ListUsersOffsetPaginatedResponseContent,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.users
                _has_next = len(_items or []) > 0
                _get_next = lambda: self.list(
                    page=page + 1,
                    per_page=per_page,
                    include_totals=include_totals,
                    sort=sort,
                    connection=connection,
                    fields=fields,
                    include_fields=include_fields,
                    q=q,
                    search_engine=search_engine,
                    primary_order=primary_order,
                    request_options=request_options,
                )
                return SyncPager(has_next=_has_next, items=_items, get_next=_get_next, response=_parsed_response)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=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)
        except ValidationError as e:
            raise ParsingError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
            )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def create(
        self,
        *,
        connection: str,
        email: typing.Optional[str] = OMIT,
        phone_number: typing.Optional[str] = OMIT,
        user_metadata: typing.Optional[UserMetadata] = OMIT,
        blocked: typing.Optional[bool] = OMIT,
        email_verified: typing.Optional[bool] = OMIT,
        phone_verified: typing.Optional[bool] = OMIT,
        app_metadata: typing.Optional[AppMetadata] = OMIT,
        given_name: typing.Optional[str] = OMIT,
        family_name: typing.Optional[str] = OMIT,
        name: typing.Optional[str] = OMIT,
        nickname: typing.Optional[str] = OMIT,
        picture: typing.Optional[str] = OMIT,
        user_id: typing.Optional[str] = OMIT,
        password: typing.Optional[str] = OMIT,
        verify_email: typing.Optional[bool] = OMIT,
        username: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[CreateUserResponseContent]:
        """
        Create a new user for a given [database](https://auth0.com/docs/connections/database) or [passwordless](https://auth0.com/docs/connections/passwordless) connection.

        Note: `connection` is required but other parameters such as `email` and `password` are dependent upon the type of connection.

        Parameters
        ----------
        connection : str
            Name of the connection this user should be created in.

        email : typing.Optional[str]
            The user's email.

        phone_number : typing.Optional[str]
            The user's phone number (following the E.164 recommendation).

        user_metadata : typing.Optional[UserMetadata]

        blocked : typing.Optional[bool]
            Whether this user was blocked by an administrator (true) or not (false).

        email_verified : typing.Optional[bool]
            Whether this email address is verified (true) or unverified (false). User will receive a verification email after creation if `email_verified` is false or not specified

        phone_verified : typing.Optional[bool]
            Whether this phone number has been verified (true) or not (false).

        app_metadata : typing.Optional[AppMetadata]

        given_name : typing.Optional[str]
            The user's given name(s).

        family_name : typing.Optional[str]
            The user's family name(s).

        name : typing.Optional[str]
            The user's full name.

        nickname : typing.Optional[str]
            The user's nickname.

        picture : typing.Optional[str]
            A URI pointing to the user's picture.

        user_id : typing.Optional[str]
            The external user's id provided by the identity provider.

        password : typing.Optional[str]
            Initial password for this user. Only valid for auth0 connection strategy.

        verify_email : typing.Optional[bool]
            Whether the user will receive a verification email after creation (true) or no email (false). Overrides behavior of `email_verified` parameter.

        username : typing.Optional[str]
            The user's username. Only valid if the connection requires a username.

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

        Returns
        -------
        HttpResponse[CreateUserResponseContent]
            User successfully created.
        """
        _response = self._client_wrapper.httpx_client.request(
            "users",
            method="POST",
            json={
                "email": email,
                "phone_number": phone_number,
                "user_metadata": user_metadata,
                "blocked": blocked,
                "email_verified": email_verified,
                "phone_verified": phone_verified,
                "app_metadata": app_metadata,
                "given_name": given_name,
                "family_name": family_name,
                "name": name,
                "nickname": nickname,
                "picture": picture,
                "user_id": user_id,
                "connection": connection,
                "password": password,
                "verify_email": verify_email,
                "username": username,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CreateUserResponseContent,
                    parse_obj_as(
                        type_=CreateUserResponseContent,  # 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.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 409:
                raise ConflictError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=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)
        except ValidationError as e:
            raise ParsingError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
            )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def list_users_by_email(
        self,
        *,
        email: str,
        fields: typing.Optional[str] = None,
        include_fields: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[typing.List[UserResponseSchema]]:
        """
        Find users by email. If Auth0 is the identity provider (idP), the email address associated with a user is saved in lower case, regardless of how you initially provided it.

        For example, if you register a user as JohnSmith@example.com, Auth0 saves the user's email as johnsmith@example.com.

        Therefore, when using this endpoint, make sure that you are searching for users via email addresses using the correct case.

        Parameters
        ----------
        email : str
            Email address to search for (case-sensitive).

        fields : typing.Optional[str]
            Comma-separated list of fields to include or exclude (based on value provided for include_fields) in the result. Leave empty to retrieve all fields.

        include_fields : typing.Optional[bool]
            Whether specified fields are to be included (true) or excluded (false). Defaults to true.

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

        Returns
        -------
        HttpResponse[typing.List[UserResponseSchema]]
            Users successfully searched.
        """
        _response = self._client_wrapper.httpx_client.request(
            "users-by-email",
            method="GET",
            params={
                "fields": fields,
                "include_fields": include_fields,
                "email": email,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.List[UserResponseSchema],
                    parse_obj_as(
                        type_=typing.List[UserResponseSchema],  # 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.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=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)
        except ValidationError as e:
            raise ParsingError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
            )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get(
        self,
        id: str,
        *,
        fields: typing.Optional[str] = None,
        include_fields: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[GetUserResponseContent]:
        """
        Retrieve user details. A list of fields to include or exclude may also be specified. For more information, see [Retrieve Users with the Get Users Endpoint](https://auth0.com/docs/manage-users/user-search/retrieve-users-with-get-users-endpoint).

        Parameters
        ----------
        id : str
            ID of the user to retrieve.

        fields : typing.Optional[str]
            Comma-separated list of fields to include or exclude (based on value provided for include_fields) in the result. Leave empty to retrieve all fields.

        include_fields : typing.Optional[bool]
            Whether specified fields are to be included (true) or excluded (false).

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

        Returns
        -------
        HttpResponse[GetUserResponseContent]
            User successfully retrieved.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"users/{encode_path_param(id)}",
            method="GET",
            params={
                "fields": fields,
                "include_fields": include_fields,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetUserResponseContent,
                    parse_obj_as(
                        type_=GetUserResponseContent,  # 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.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=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)
        except ValidationError as e:
            raise ParsingError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
            )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[None]:
        """
        Delete a user by user ID. This action cannot be undone. For Auth0 Dashboard instructions, see [Delete Users](https://auth0.com/docs/manage-users/user-accounts/delete-users).

        Parameters
        ----------
        id : str
            ID of the user to delete.

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"users/{encode_path_param(id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=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)
        except ValidationError as e:
            raise ParsingError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
            )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def update(
        self,
        id: str,
        *,
        blocked: typing.Optional[bool] = OMIT,
        email_verified: typing.Optional[bool] = OMIT,
        email: typing.Optional[str] = OMIT,
        phone_number: typing.Optional[str] = OMIT,
        phone_verified: typing.Optional[bool] = OMIT,
        user_metadata: typing.Optional[UserMetadata] = OMIT,
        app_metadata: typing.Optional[AppMetadata] = OMIT,
        given_name: typing.Optional[str] = OMIT,
        family_name: typing.Optional[str] = OMIT,
        name: typing.Optional[str] = OMIT,
        nickname: typing.Optional[str] = OMIT,
        picture: typing.Optional[str] = OMIT,
        verify_email: typing.Optional[bool] = OMIT,
        verify_phone_number: typing.Optional[bool] = OMIT,
        password: typing.Optional[str] = OMIT,
        connection: typing.Optional[str] = OMIT,
        client_id: typing.Optional[str] = OMIT,
        username: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[UpdateUserResponseContent]:
        """
        Update a user.

        These are the attributes that can be updated at the root level:

        - app_metadata
        - blocked
        - email
        - email_verified
        - family_name
        - given_name
        - name
        - nickname
        - password
        - phone_number
        - phone_verified
        - picture
        - username
        - user_metadata
        - verify_email

        Some considerations:

        - The properties of the new object will replace the old ones.
        - The metadata fields are an exception to this rule (`user_metadata` and `app_metadata`). These properties are merged instead of being replaced but be careful, the merge only occurs on the first level.
        - If you are updating `email`, `email_verified`, `phone_number`, `phone_verified`, `username` or `password` of a secondary identity, you need to specify the `connection` property too.
        - If you are updating `email` or `phone_number` you can specify, optionally, the `client_id` property.
        - Updating `email_verified` is not supported for enterprise and passwordless sms connections.
        - Updating the `blocked` to `false` does not affect the user's blocked state from an excessive amount of incorrectly provided credentials. Use the "Unblock a user" endpoint from the "User Blocks" API to change the user's state.
        - Supported attributes can be unset by supplying `null` as the value.

        **Updating a field (non-metadata property)**

        To mark the email address of a user as verified, the body to send should be:

        ```json
        { "email_verified": true }
        ```

        **Updating a user metadata root property**

        Let's assume that our test user has the following `user_metadata`:

        ```json
        { "user_metadata" : { "profileCode": 1479 } }
        ```

        To add the field `addresses` the body to send should be:

        ```json
        { "user_metadata" : { "addresses": {"work_address": "100 Industrial Way"} }}
        ```

        The modified object ends up with the following `user_metadata` property:

        ```json
        {
          "user_metadata": {
            "profileCode": 1479,
            "addresses": { "work_address": "100 Industrial Way" }
          }
        }
        ```

        **Updating an inner user metadata property**

        If there's existing user metadata to which we want to add  `"home_address": "742 Evergreen Terrace"` (using the `addresses` property) we should send the whole `addresses` object. Since this is a first-level object, the object will be merged in, but its own properties will not be. The body to send should be:

        ```json
        {
          "user_metadata": {
            "addresses": {
              "work_address": "100 Industrial Way",
              "home_address": "742 Evergreen Terrace"
            }
          }
        }
        ```

        The modified object ends up with the following `user_metadata` property:

        ```json
        {
          "user_metadata": {
            "profileCode": 1479,
            "addresses": {
              "work_address": "100 Industrial Way",
              "home_address": "742 Evergreen Terrace"
            }
          }
        }
        ```

        Parameters
        ----------
        id : str
            ID of the user to update.

        blocked : typing.Optional[bool]
            Whether this user was blocked by an administrator (true) or not (false).

        email_verified : typing.Optional[bool]
            Whether this email address is verified (true) or unverified (false). If set to false the user will not receive a verification email unless `verify_email` is set to true.

        email : typing.Optional[str]
            Email address of this user.

        phone_number : typing.Optional[str]
            The user's phone number (following the E.164 recommendation).

        phone_verified : typing.Optional[bool]
            Whether this phone number has been verified (true) or not (false).

        user_metadata : typing.Optional[UserMetadata]
            User metadata to which this user has read/write access.

        app_metadata : typing.Optional[AppMetadata]
            User metadata to which this user has read-only access.

        given_name : typing.Optional[str]
            Given name/first name/forename of this user.

        family_name : typing.Optional[str]
            Family name/last name/surname of this user.

        name : typing.Optional[str]
            Name of this user.

        nickname : typing.Optional[str]
            Preferred nickname or alias of this user.

        picture : typing.Optional[str]
            URL to picture, photo, or avatar of this user.

        verify_email : typing.Optional[bool]
            Whether this user will receive a verification email after creation (true) or no email (false). Overrides behavior of `email_verified` parameter.

        verify_phone_number : typing.Optional[bool]
            Whether this user will receive a text after changing the phone number (true) or no text (false). Only valid when changing phone number for SMS connections.

        password : typing.Optional[str]
            New password for this user. Only valid for database connections.

        connection : typing.Optional[str]
            Name of the connection to target for this user update.

        client_id : typing.Optional[str]
            Auth0 client ID. Only valid when updating email address.

        username : typing.Optional[str]
            The user's username. Only valid if the connection requires a username.

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

        Returns
        -------
        HttpResponse[UpdateUserResponseContent]
            User successfully updated.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"users/{encode_path_param(id)}",
            method="PATCH",
            json={
                "blocked": blocked,
                "email_verified": email_verified,
                "email": email,
                "phone_number": phone_number,
                "phone_verified": phone_verified,
                "user_metadata": user_metadata,
                "app_metadata": app_metadata,
                "given_name": given_name,
                "family_name": family_name,
                "name": name,
                "nickname": nickname,
                "picture": picture,
                "verify_email": verify_email,
                "verify_phone_number": verify_phone_number,
                "password": password,
                "connection": connection,
                "client_id": client_id,
                "username": username,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UpdateUserResponseContent,
                    parse_obj_as(
                        type_=UpdateUserResponseContent,  # 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.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=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)
        except ValidationError as e:
            raise ParsingError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
            )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def regenerate_recovery_code(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[RegenerateUsersRecoveryCodeResponseContent]:
        """
        Remove an existing multi-factor authentication (MFA) [recovery code](https://auth0.com/docs/secure/multi-factor-authentication/reset-user-mfa) and generate a new one. If a user cannot access the original device or account used for MFA enrollment, they can use a recovery code to authenticate.

        Parameters
        ----------
        id : str
            ID of the user to regenerate a multi-factor authentication recovery code for.

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

        Returns
        -------
        HttpResponse[RegenerateUsersRecoveryCodeResponseContent]
            New recovery code successfully generated.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"users/{encode_path_param(id)}/recovery-code-regeneration",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    RegenerateUsersRecoveryCodeResponseContent,
                    parse_obj_as(
                        type_=RegenerateUsersRecoveryCodeResponseContent,  # 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.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=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)
        except ValidationError as e:
            raise ParsingError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
            )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def revoke_access(
        self,
        id: str,
        *,
        session_id: typing.Optional[str] = OMIT,
        preserve_refresh_tokens: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[None]:
        """
        Revokes selected resources related to a user (sessions, refresh tokens, ...).

        Parameters
        ----------
        id : str
            ID of the user.

        session_id : typing.Optional[str]
            ID of the session to revoke.

        preserve_refresh_tokens : typing.Optional[bool]
            Whether to preserve the refresh tokens associated with the session.

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"users/{encode_path_param(id)}/revoke-access",
            method="POST",
            json={
                "session_id": session_id,
                "preserve_refresh_tokens": preserve_refresh_tokens,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=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)
        except ValidationError as e:
            raise ParsingError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
            )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)


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

    async def list(
        self,
        *,
        page: typing.Optional[int] = 0,
        per_page: typing.Optional[int] = 50,
        include_totals: typing.Optional[bool] = True,
        sort: typing.Optional[str] = None,
        connection: typing.Optional[str] = None,
        fields: typing.Optional[str] = None,
        include_fields: typing.Optional[bool] = None,
        q: typing.Optional[str] = None,
        search_engine: typing.Optional[SearchEngineVersionsEnum] = None,
        primary_order: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncPager[UserResponseSchema, ListUsersOffsetPaginatedResponseContent]:
        """
        Retrieve details of users. It is possible to:

        - Specify a search criteria for users
        - Sort the users to be returned
        - Select the fields to be returned
        - Specify the number of users to retrieve per page and the page index



        The `q` query parameter can be used to get users that match the specified criteria [using query string syntax.](https://auth0.com/docs/users/search/v3/query-syntax)

        [Learn more about searching for users.](https://auth0.com/docs/users/search/v3)

        Read about [best practices](https://auth0.com/docs/users/search/best-practices) when working with the API endpoints for retrieving users.



        Auth0 limits the number of users you can return. If you exceed this threshold, please redefine your search, use the [export job](https://auth0.com/docs/api/management/v2#!/Jobs/post_users_exports), or the [User Import / Export](https://auth0.com/docs/extensions/user-import-export) extension.

        Parameters
        ----------
        page : typing.Optional[int]
            Page index of the results to return. First page is 0.

        per_page : typing.Optional[int]
            Number of results per page.

        include_totals : typing.Optional[bool]
            Return results inside an object that contains the total result count (true) or as a direct array of results (false, default).

        sort : typing.Optional[str]
            Field to sort by. Use <code>field:order</code> where order is <code>1</code> for ascending and <code>-1</code> for descending. e.g. <code>created_at:1</code>

        connection : typing.Optional[str]
            Connection filter. Only applies when using <code>search_engine=v1</code>. To filter by connection with <code>search_engine=v2|v3</code>, use <code>q=identities.connection:"connection_name"</code>

        fields : typing.Optional[str]
            Comma-separated list of fields to include or exclude (based on value provided for include_fields) in the result. Leave empty to retrieve all fields.

        include_fields : typing.Optional[bool]
            Whether specified fields are to be included (true) or excluded (false).

        q : typing.Optional[str]
            Query in <a target='_new' href ='https://lucene.apache.org/core/2_9_4/queryparsersyntax.html'>Lucene query string syntax</a>. Some query types cannot be used on metadata fields, for details see <a href='https://auth0.com/docs/users/search/v3/query-syntax#searchable-fields'>Searchable Fields</a>.

        search_engine : typing.Optional[SearchEngineVersionsEnum]
            The version of the search engine

        primary_order : typing.Optional[bool]
            If true (default), results are returned in a deterministic order. If false, results may be returned in a non-deterministic order, which can enhance performance for complex queries targeting a small number of users. Set to false only when consistent ordering and pagination is not required.

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

        Returns
        -------
        AsyncPager[UserResponseSchema, ListUsersOffsetPaginatedResponseContent]
            Users successfully retrieved.
        """
        page = page if page is not None else 0

        _response = await self._client_wrapper.httpx_client.request(
            "users",
            method="GET",
            params={
                "page": page,
                "per_page": per_page,
                "include_totals": include_totals,
                "sort": sort,
                "connection": connection,
                "fields": fields,
                "include_fields": include_fields,
                "q": q,
                "search_engine": search_engine,
                "primary_order": primary_order,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    ListUsersOffsetPaginatedResponseContent,
                    parse_obj_as(
                        type_=ListUsersOffsetPaginatedResponseContent,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.users
                _has_next = len(_items or []) > 0

                async def _get_next():
                    return await self.list(
                        page=page + 1,
                        per_page=per_page,
                        include_totals=include_totals,
                        sort=sort,
                        connection=connection,
                        fields=fields,
                        include_fields=include_fields,
                        q=q,
                        search_engine=search_engine,
                        primary_order=primary_order,
                        request_options=request_options,
                    )

                return AsyncPager(has_next=_has_next, items=_items, get_next=_get_next, response=_parsed_response)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=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)
        except ValidationError as e:
            raise ParsingError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
            )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def create(
        self,
        *,
        connection: str,
        email: typing.Optional[str] = OMIT,
        phone_number: typing.Optional[str] = OMIT,
        user_metadata: typing.Optional[UserMetadata] = OMIT,
        blocked: typing.Optional[bool] = OMIT,
        email_verified: typing.Optional[bool] = OMIT,
        phone_verified: typing.Optional[bool] = OMIT,
        app_metadata: typing.Optional[AppMetadata] = OMIT,
        given_name: typing.Optional[str] = OMIT,
        family_name: typing.Optional[str] = OMIT,
        name: typing.Optional[str] = OMIT,
        nickname: typing.Optional[str] = OMIT,
        picture: typing.Optional[str] = OMIT,
        user_id: typing.Optional[str] = OMIT,
        password: typing.Optional[str] = OMIT,
        verify_email: typing.Optional[bool] = OMIT,
        username: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[CreateUserResponseContent]:
        """
        Create a new user for a given [database](https://auth0.com/docs/connections/database) or [passwordless](https://auth0.com/docs/connections/passwordless) connection.

        Note: `connection` is required but other parameters such as `email` and `password` are dependent upon the type of connection.

        Parameters
        ----------
        connection : str
            Name of the connection this user should be created in.

        email : typing.Optional[str]
            The user's email.

        phone_number : typing.Optional[str]
            The user's phone number (following the E.164 recommendation).

        user_metadata : typing.Optional[UserMetadata]

        blocked : typing.Optional[bool]
            Whether this user was blocked by an administrator (true) or not (false).

        email_verified : typing.Optional[bool]
            Whether this email address is verified (true) or unverified (false). User will receive a verification email after creation if `email_verified` is false or not specified

        phone_verified : typing.Optional[bool]
            Whether this phone number has been verified (true) or not (false).

        app_metadata : typing.Optional[AppMetadata]

        given_name : typing.Optional[str]
            The user's given name(s).

        family_name : typing.Optional[str]
            The user's family name(s).

        name : typing.Optional[str]
            The user's full name.

        nickname : typing.Optional[str]
            The user's nickname.

        picture : typing.Optional[str]
            A URI pointing to the user's picture.

        user_id : typing.Optional[str]
            The external user's id provided by the identity provider.

        password : typing.Optional[str]
            Initial password for this user. Only valid for auth0 connection strategy.

        verify_email : typing.Optional[bool]
            Whether the user will receive a verification email after creation (true) or no email (false). Overrides behavior of `email_verified` parameter.

        username : typing.Optional[str]
            The user's username. Only valid if the connection requires a username.

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

        Returns
        -------
        AsyncHttpResponse[CreateUserResponseContent]
            User successfully created.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "users",
            method="POST",
            json={
                "email": email,
                "phone_number": phone_number,
                "user_metadata": user_metadata,
                "blocked": blocked,
                "email_verified": email_verified,
                "phone_verified": phone_verified,
                "app_metadata": app_metadata,
                "given_name": given_name,
                "family_name": family_name,
                "name": name,
                "nickname": nickname,
                "picture": picture,
                "user_id": user_id,
                "connection": connection,
                "password": password,
                "verify_email": verify_email,
                "username": username,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CreateUserResponseContent,
                    parse_obj_as(
                        type_=CreateUserResponseContent,  # 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.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 409:
                raise ConflictError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=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)
        except ValidationError as e:
            raise ParsingError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
            )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def list_users_by_email(
        self,
        *,
        email: str,
        fields: typing.Optional[str] = None,
        include_fields: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[typing.List[UserResponseSchema]]:
        """
        Find users by email. If Auth0 is the identity provider (idP), the email address associated with a user is saved in lower case, regardless of how you initially provided it.

        For example, if you register a user as JohnSmith@example.com, Auth0 saves the user's email as johnsmith@example.com.

        Therefore, when using this endpoint, make sure that you are searching for users via email addresses using the correct case.

        Parameters
        ----------
        email : str
            Email address to search for (case-sensitive).

        fields : typing.Optional[str]
            Comma-separated list of fields to include or exclude (based on value provided for include_fields) in the result. Leave empty to retrieve all fields.

        include_fields : typing.Optional[bool]
            Whether specified fields are to be included (true) or excluded (false). Defaults to true.

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

        Returns
        -------
        AsyncHttpResponse[typing.List[UserResponseSchema]]
            Users successfully searched.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "users-by-email",
            method="GET",
            params={
                "fields": fields,
                "include_fields": include_fields,
                "email": email,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.List[UserResponseSchema],
                    parse_obj_as(
                        type_=typing.List[UserResponseSchema],  # 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.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=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)
        except ValidationError as e:
            raise ParsingError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
            )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get(
        self,
        id: str,
        *,
        fields: typing.Optional[str] = None,
        include_fields: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[GetUserResponseContent]:
        """
        Retrieve user details. A list of fields to include or exclude may also be specified. For more information, see [Retrieve Users with the Get Users Endpoint](https://auth0.com/docs/manage-users/user-search/retrieve-users-with-get-users-endpoint).

        Parameters
        ----------
        id : str
            ID of the user to retrieve.

        fields : typing.Optional[str]
            Comma-separated list of fields to include or exclude (based on value provided for include_fields) in the result. Leave empty to retrieve all fields.

        include_fields : typing.Optional[bool]
            Whether specified fields are to be included (true) or excluded (false).

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

        Returns
        -------
        AsyncHttpResponse[GetUserResponseContent]
            User successfully retrieved.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"users/{encode_path_param(id)}",
            method="GET",
            params={
                "fields": fields,
                "include_fields": include_fields,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetUserResponseContent,
                    parse_obj_as(
                        type_=GetUserResponseContent,  # 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.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=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)
        except ValidationError as e:
            raise ParsingError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
            )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def delete(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[None]:
        """
        Delete a user by user ID. This action cannot be undone. For Auth0 Dashboard instructions, see [Delete Users](https://auth0.com/docs/manage-users/user-accounts/delete-users).

        Parameters
        ----------
        id : str
            ID of the user to delete.

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"users/{encode_path_param(id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=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)
        except ValidationError as e:
            raise ParsingError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
            )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def update(
        self,
        id: str,
        *,
        blocked: typing.Optional[bool] = OMIT,
        email_verified: typing.Optional[bool] = OMIT,
        email: typing.Optional[str] = OMIT,
        phone_number: typing.Optional[str] = OMIT,
        phone_verified: typing.Optional[bool] = OMIT,
        user_metadata: typing.Optional[UserMetadata] = OMIT,
        app_metadata: typing.Optional[AppMetadata] = OMIT,
        given_name: typing.Optional[str] = OMIT,
        family_name: typing.Optional[str] = OMIT,
        name: typing.Optional[str] = OMIT,
        nickname: typing.Optional[str] = OMIT,
        picture: typing.Optional[str] = OMIT,
        verify_email: typing.Optional[bool] = OMIT,
        verify_phone_number: typing.Optional[bool] = OMIT,
        password: typing.Optional[str] = OMIT,
        connection: typing.Optional[str] = OMIT,
        client_id: typing.Optional[str] = OMIT,
        username: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[UpdateUserResponseContent]:
        """
        Update a user.

        These are the attributes that can be updated at the root level:

        - app_metadata
        - blocked
        - email
        - email_verified
        - family_name
        - given_name
        - name
        - nickname
        - password
        - phone_number
        - phone_verified
        - picture
        - username
        - user_metadata
        - verify_email

        Some considerations:

        - The properties of the new object will replace the old ones.
        - The metadata fields are an exception to this rule (`user_metadata` and `app_metadata`). These properties are merged instead of being replaced but be careful, the merge only occurs on the first level.
        - If you are updating `email`, `email_verified`, `phone_number`, `phone_verified`, `username` or `password` of a secondary identity, you need to specify the `connection` property too.
        - If you are updating `email` or `phone_number` you can specify, optionally, the `client_id` property.
        - Updating `email_verified` is not supported for enterprise and passwordless sms connections.
        - Updating the `blocked` to `false` does not affect the user's blocked state from an excessive amount of incorrectly provided credentials. Use the "Unblock a user" endpoint from the "User Blocks" API to change the user's state.
        - Supported attributes can be unset by supplying `null` as the value.

        **Updating a field (non-metadata property)**

        To mark the email address of a user as verified, the body to send should be:

        ```json
        { "email_verified": true }
        ```

        **Updating a user metadata root property**

        Let's assume that our test user has the following `user_metadata`:

        ```json
        { "user_metadata" : { "profileCode": 1479 } }
        ```

        To add the field `addresses` the body to send should be:

        ```json
        { "user_metadata" : { "addresses": {"work_address": "100 Industrial Way"} }}
        ```

        The modified object ends up with the following `user_metadata` property:

        ```json
        {
          "user_metadata": {
            "profileCode": 1479,
            "addresses": { "work_address": "100 Industrial Way" }
          }
        }
        ```

        **Updating an inner user metadata property**

        If there's existing user metadata to which we want to add  `"home_address": "742 Evergreen Terrace"` (using the `addresses` property) we should send the whole `addresses` object. Since this is a first-level object, the object will be merged in, but its own properties will not be. The body to send should be:

        ```json
        {
          "user_metadata": {
            "addresses": {
              "work_address": "100 Industrial Way",
              "home_address": "742 Evergreen Terrace"
            }
          }
        }
        ```

        The modified object ends up with the following `user_metadata` property:

        ```json
        {
          "user_metadata": {
            "profileCode": 1479,
            "addresses": {
              "work_address": "100 Industrial Way",
              "home_address": "742 Evergreen Terrace"
            }
          }
        }
        ```

        Parameters
        ----------
        id : str
            ID of the user to update.

        blocked : typing.Optional[bool]
            Whether this user was blocked by an administrator (true) or not (false).

        email_verified : typing.Optional[bool]
            Whether this email address is verified (true) or unverified (false). If set to false the user will not receive a verification email unless `verify_email` is set to true.

        email : typing.Optional[str]
            Email address of this user.

        phone_number : typing.Optional[str]
            The user's phone number (following the E.164 recommendation).

        phone_verified : typing.Optional[bool]
            Whether this phone number has been verified (true) or not (false).

        user_metadata : typing.Optional[UserMetadata]
            User metadata to which this user has read/write access.

        app_metadata : typing.Optional[AppMetadata]
            User metadata to which this user has read-only access.

        given_name : typing.Optional[str]
            Given name/first name/forename of this user.

        family_name : typing.Optional[str]
            Family name/last name/surname of this user.

        name : typing.Optional[str]
            Name of this user.

        nickname : typing.Optional[str]
            Preferred nickname or alias of this user.

        picture : typing.Optional[str]
            URL to picture, photo, or avatar of this user.

        verify_email : typing.Optional[bool]
            Whether this user will receive a verification email after creation (true) or no email (false). Overrides behavior of `email_verified` parameter.

        verify_phone_number : typing.Optional[bool]
            Whether this user will receive a text after changing the phone number (true) or no text (false). Only valid when changing phone number for SMS connections.

        password : typing.Optional[str]
            New password for this user. Only valid for database connections.

        connection : typing.Optional[str]
            Name of the connection to target for this user update.

        client_id : typing.Optional[str]
            Auth0 client ID. Only valid when updating email address.

        username : typing.Optional[str]
            The user's username. Only valid if the connection requires a username.

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

        Returns
        -------
        AsyncHttpResponse[UpdateUserResponseContent]
            User successfully updated.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"users/{encode_path_param(id)}",
            method="PATCH",
            json={
                "blocked": blocked,
                "email_verified": email_verified,
                "email": email,
                "phone_number": phone_number,
                "phone_verified": phone_verified,
                "user_metadata": user_metadata,
                "app_metadata": app_metadata,
                "given_name": given_name,
                "family_name": family_name,
                "name": name,
                "nickname": nickname,
                "picture": picture,
                "verify_email": verify_email,
                "verify_phone_number": verify_phone_number,
                "password": password,
                "connection": connection,
                "client_id": client_id,
                "username": username,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UpdateUserResponseContent,
                    parse_obj_as(
                        type_=UpdateUserResponseContent,  # 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.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=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)
        except ValidationError as e:
            raise ParsingError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
            )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def regenerate_recovery_code(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[RegenerateUsersRecoveryCodeResponseContent]:
        """
        Remove an existing multi-factor authentication (MFA) [recovery code](https://auth0.com/docs/secure/multi-factor-authentication/reset-user-mfa) and generate a new one. If a user cannot access the original device or account used for MFA enrollment, they can use a recovery code to authenticate.

        Parameters
        ----------
        id : str
            ID of the user to regenerate a multi-factor authentication recovery code for.

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

        Returns
        -------
        AsyncHttpResponse[RegenerateUsersRecoveryCodeResponseContent]
            New recovery code successfully generated.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"users/{encode_path_param(id)}/recovery-code-regeneration",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    RegenerateUsersRecoveryCodeResponseContent,
                    parse_obj_as(
                        type_=RegenerateUsersRecoveryCodeResponseContent,  # 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.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=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)
        except ValidationError as e:
            raise ParsingError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
            )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def revoke_access(
        self,
        id: str,
        *,
        session_id: typing.Optional[str] = OMIT,
        preserve_refresh_tokens: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[None]:
        """
        Revokes selected resources related to a user (sessions, refresh tokens, ...).

        Parameters
        ----------
        id : str
            ID of the user.

        session_id : typing.Optional[str]
            ID of the session to revoke.

        preserve_refresh_tokens : typing.Optional[bool]
            Whether to preserve the refresh tokens associated with the session.

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"users/{encode_path_param(id)}/revoke-access",
            method="POST",
            json={
                "session_id": session_id,
                "preserve_refresh_tokens": preserve_refresh_tokens,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=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)
        except ValidationError as e:
            raise ParsingError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
            )
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
