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

import typing
from json.decoder import JSONDecodeError

from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from ..errors.unprocessable_entity_error import UnprocessableEntityError
from ..types.device_information import DeviceInformation
from ..types.email_validation_response import EmailValidationResponse
from ..types.google_authorize_response import GoogleAuthorizeResponse
from ..types.login_response import LoginResponse
from ..types.login_verification_response import LoginVerificationResponse
from ..types.logout_response import LogoutResponse
from ..types.password_reset_response import PasswordResetResponse
from ..types.password_reset_verify_response import PasswordResetVerifyResponse
from ..types.password_update_response import PasswordUpdateResponse
from ..types.refresh_token_response import RefreshTokenResponse
from ..types.register_response import RegisterResponse
from ..types.resend_code_response import ResendCodeResponse
from ..types.token_validation_response import TokenValidationResponse

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


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

    def register(
        self,
        *,
        email: str,
        password: str,
        full_name: str,
        user_name: typing.Optional[str] = OMIT,
        organization_id: typing.Optional[str] = OMIT,
        device_information: typing.Optional[DeviceInformation] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[RegisterResponse]:
        """
        Creates a new user account and sends a 4-digit verification code to the provided email. The user must verify their email using the /verify endpoint to complete registration and receive tokens.

        Parameters
        ----------
        email : str
            User email address (primary identifier)

        password : str
            Password (min 8 chars with complexity, max 72 chars due to bcrypt limit)

        full_name : str
            User's full name

        user_name : typing.Optional[str]
            Preferred username (defaults to email prefix if omitted, min 3 chars)

        organization_id : typing.Optional[str]
            Organization UID to associate the user with

        device_information : typing.Optional[DeviceInformation]
            Device tracking information

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

        Returns
        -------
        HttpResponse[RegisterResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/auth/register",
            method="POST",
            json={
                "email": email,
                "password": password,
                "full_name": full_name,
                "user_name": user_name,
                "organization_id": organization_id,
                "device_information": convert_and_respect_annotation_metadata(
                    object_=device_information, annotation=typing.Optional[DeviceInformation], direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    RegisterResponse,
                    parse_obj_as(
                        type_=RegisterResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def login(
        self,
        *,
        email_or_username: str,
        password: str,
        device_information: typing.Optional[DeviceInformation] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[LoginResponse]:
        """
        Validates the user's email/username and password, then initiates two-factor authentication (2FA) by sending a 4-digit verification code via email. Returns user info and an email_key for use with the /verify endpoint. Does not return tokens directly — the user must complete 2FA first.

        Parameters
        ----------
        email_or_username : str
            Email address or username

        password : str
            User password

        device_information : typing.Optional[DeviceInformation]
            Device tracking information

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

        Returns
        -------
        HttpResponse[LoginResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/auth/login",
            method="POST",
            json={
                "email_or_username": email_or_username,
                "password": password,
                "device_information": convert_and_respect_annotation_metadata(
                    object_=device_information, annotation=typing.Optional[DeviceInformation], direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    LoginResponse,
                    parse_obj_as(
                        type_=LoginResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def verify_email(
        self,
        *,
        email_key: str,
        verification_code: int,
        device_information: typing.Optional[DeviceInformation] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[LoginVerificationResponse]:
        """
        Validates the 4-digit verification code sent during login or registration. On success, returns JWT access and refresh tokens along with user details. The email_key from the login/register response and the code from the user's email are both required.

        Parameters
        ----------
        email_key : str
            Email verification key

        verification_code : int
            4-digit verification code

        device_information : typing.Optional[DeviceInformation]
            Device tracking information

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

        Returns
        -------
        HttpResponse[LoginVerificationResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/auth/verify",
            method="POST",
            json={
                "email_key": email_key,
                "verification_code": verification_code,
                "device_information": convert_and_respect_annotation_metadata(
                    object_=device_information, annotation=typing.Optional[DeviceInformation], direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    LoginVerificationResponse,
                    parse_obj_as(
                        type_=LoginVerificationResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def refresh_token(
        self, *, refresh_token: str, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[RefreshTokenResponse]:
        """
        Exchanges a valid refresh token for a new access token and refresh token pair. Implements token rotation — the old refresh token is invalidated and a new one is issued. Use this to maintain sessions without requiring the user to re-authenticate.

        Parameters
        ----------
        refresh_token : str
            Refresh token

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

        Returns
        -------
        HttpResponse[RefreshTokenResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/auth/refresh",
            method="POST",
            json={
                "refresh_token": refresh_token,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    RefreshTokenResponse,
                    parse_obj_as(
                        type_=RefreshTokenResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def logout(
        self, *, refresh_token: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[LogoutResponse]:
        """
        Logs out the current user by revoking their refresh token and invalidating the associated device session. Requires a valid Bearer token. The refresh token provided in the body is permanently revoked and cannot be reused.

        Parameters
        ----------
        refresh_token : typing.Optional[str]
            Refresh token to invalidate

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

        Returns
        -------
        HttpResponse[LogoutResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/auth/logout",
            method="POST",
            json={
                "refresh_token": refresh_token,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    LogoutResponse,
                    parse_obj_as(
                        type_=LogoutResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def request_password_reset(
        self, *, email: str, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[PasswordResetResponse]:
        """
        Sends a 4-digit verification code to the user's email if the account exists. For security, always returns a success response regardless of whether the email is registered (prevents email enumeration). Codes expire after 5 minutes. Rate-limited to 1 request per minute per email. After receiving the code, submit it with the new password to /password/reset/verify.

        Parameters
        ----------
        email : str
            User email address

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

        Returns
        -------
        HttpResponse[PasswordResetResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/auth/password/reset",
            method="POST",
            json={
                "email": email,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PasswordResetResponse,
                    parse_obj_as(
                        type_=PasswordResetResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def verify_password_reset(
        self,
        *,
        email: str,
        verification_code: int,
        new_password: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[PasswordResetVerifyResponse]:
        """
        Validates the 4-digit verification code sent to the user's email and sets the new password. Codes are one-time use and expire after 5 minutes. On success, all existing refresh tokens are revoked, forcing re-authentication on all devices. Password strength requirements are enforced.

        Parameters
        ----------
        email : str
            User email address

        verification_code : int
            4-digit verification code

        new_password : str
            New password (min 8 chars with complexity, max 72 chars due to bcrypt limit)

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

        Returns
        -------
        HttpResponse[PasswordResetVerifyResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/auth/password/reset/verify",
            method="POST",
            json={
                "email": email,
                "verification_code": verification_code,
                "new_password": new_password,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PasswordResetVerifyResponse,
                    parse_obj_as(
                        type_=PasswordResetVerifyResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def update_password(
        self,
        *,
        current_password: str,
        new_password: str,
        confirm_password: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[PasswordUpdateResponse]:
        """
        Changes the password for the currently authenticated user. Requires the current password for verification and enforces password strength requirements (minimum 8 characters, at least one special character). On success, all other device sessions are revoked while keeping the current session active. Requires Bearer token authentication.

        Parameters
        ----------
        current_password : str
            Current password for verification

        new_password : str
            New password (min 8 chars with complexity, max 72 chars due to bcrypt limit)

        confirm_password : str
            Confirmation of new password (must match new_password)

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

        Returns
        -------
        HttpResponse[PasswordUpdateResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/auth/password/update",
            method="PUT",
            json={
                "current_password": current_password,
                "new_password": new_password,
                "confirm_password": confirm_password,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PasswordUpdateResponse,
                    parse_obj_as(
                        type_=PasswordUpdateResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def validate_email(
        self, *, email: str, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[EmailValidationResponse]:
        """
        Checks whether an email address is eligible for registration. Validates format, checks availability (not already registered), and detects organization domain matches. Use this during registration to provide real-time feedback. Returns validity, availability, and optional organization details if the email domain matches an existing organization.

        Parameters
        ----------
        email : str
            Email address to validate for signup eligibility

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

        Returns
        -------
        HttpResponse[EmailValidationResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/auth/validate-email",
            method="POST",
            json={
                "email": email,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    EmailValidationResponse,
                    parse_obj_as(
                        type_=EmailValidationResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def resend_verification_code(
        self, *, email_key: str, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[ResendCodeResponse]:
        """
        Generates and sends a new 4-digit verification code to the user's email. Works for login, registration, and password reset verification flows. The previous code is invalidated and a new one is generated with a fresh expiry window. Requires the email_key from the original login/register response.

        Parameters
        ----------
        email_key : str
            Email verification key

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

        Returns
        -------
        HttpResponse[ResendCodeResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/auth/resend-code",
            method="POST",
            json={
                "email_key": email_key,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ResendCodeResponse,
                    parse_obj_as(
                        type_=ResendCodeResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def validate_token(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[TokenValidationResponse]:
        """
        Checks whether the current authentication token (Bearer or API key) is still valid. If the request passes authentication, the token is valid and the endpoint returns success. Used by frontends to verify session state without making a data request.

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

        Returns
        -------
        HttpResponse[TokenValidationResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/auth/validate",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TokenValidationResponse,
                    parse_obj_as(
                        type_=TokenValidationResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def dev_login(
        self,
        *,
        email_or_username: str,
        password: str,
        device_information: typing.Optional[DeviceInformation] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[LoginVerificationResponse]:
        """
        Authenticates credentials and immediately returns JWT tokens without sending a verification code. Only available in local, develop, and test environments — returns 403 in production and staging. Useful for automated testing and local development workflows.

        Parameters
        ----------
        email_or_username : str
            Email address or username

        password : str
            User password

        device_information : typing.Optional[DeviceInformation]
            Device tracking information

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

        Returns
        -------
        HttpResponse[LoginVerificationResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/auth/dev-login",
            method="POST",
            json={
                "email_or_username": email_or_username,
                "password": password,
                "device_information": convert_and_respect_annotation_metadata(
                    object_=device_information, annotation=typing.Optional[DeviceInformation], direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    LoginVerificationResponse,
                    parse_obj_as(
                        type_=LoginVerificationResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def google_authorize(
        self,
        *,
        redirect_uri: str,
        organization_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[GoogleAuthorizeResponse]:
        """
        Generates a Google OAuth 2.0 authorization URL for Sign-In with Google. Returns a URL containing a CSRF state token that the client should redirect the user to. The state token is stored server-side and validated during the callback to prevent CSRF attacks. Optionally accepts an organization_id to pre-associate the user with an organization.

        Parameters
        ----------
        redirect_uri : str
            Frontend URL to redirect to after authentication

        organization_id : typing.Optional[str]
            Optional organization ID to associate user with

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

        Returns
        -------
        HttpResponse[GoogleAuthorizeResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/auth/google/authorize",
            method="POST",
            json={
                "redirect_uri": redirect_uri,
                "organization_id": organization_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GoogleAuthorizeResponse,
                    parse_obj_as(
                        type_=GoogleAuthorizeResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def google_callback(
        self,
        *,
        code: str,
        state: str,
        error: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[None]:
        """
        Handles the OAuth 2.0 callback from Google after user authorization. Exchanges the authorization code for tokens, creates or links the user account, and returns an HTML page that passes the JWT tokens to the frontend via postMessage. Validates the CSRF state token to prevent cross-site request forgery.

        Parameters
        ----------
        code : str
            Authorization code from Google

        state : str
            CSRF state token

        error : typing.Optional[str]
            Error from Google

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/auth/google/callback",
            method="GET",
            params={
                "code": code,
                "state": state,
                "error": error,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)


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

    async def register(
        self,
        *,
        email: str,
        password: str,
        full_name: str,
        user_name: typing.Optional[str] = OMIT,
        organization_id: typing.Optional[str] = OMIT,
        device_information: typing.Optional[DeviceInformation] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[RegisterResponse]:
        """
        Creates a new user account and sends a 4-digit verification code to the provided email. The user must verify their email using the /verify endpoint to complete registration and receive tokens.

        Parameters
        ----------
        email : str
            User email address (primary identifier)

        password : str
            Password (min 8 chars with complexity, max 72 chars due to bcrypt limit)

        full_name : str
            User's full name

        user_name : typing.Optional[str]
            Preferred username (defaults to email prefix if omitted, min 3 chars)

        organization_id : typing.Optional[str]
            Organization UID to associate the user with

        device_information : typing.Optional[DeviceInformation]
            Device tracking information

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

        Returns
        -------
        AsyncHttpResponse[RegisterResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/auth/register",
            method="POST",
            json={
                "email": email,
                "password": password,
                "full_name": full_name,
                "user_name": user_name,
                "organization_id": organization_id,
                "device_information": convert_and_respect_annotation_metadata(
                    object_=device_information, annotation=typing.Optional[DeviceInformation], direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    RegisterResponse,
                    parse_obj_as(
                        type_=RegisterResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def login(
        self,
        *,
        email_or_username: str,
        password: str,
        device_information: typing.Optional[DeviceInformation] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[LoginResponse]:
        """
        Validates the user's email/username and password, then initiates two-factor authentication (2FA) by sending a 4-digit verification code via email. Returns user info and an email_key for use with the /verify endpoint. Does not return tokens directly — the user must complete 2FA first.

        Parameters
        ----------
        email_or_username : str
            Email address or username

        password : str
            User password

        device_information : typing.Optional[DeviceInformation]
            Device tracking information

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

        Returns
        -------
        AsyncHttpResponse[LoginResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/auth/login",
            method="POST",
            json={
                "email_or_username": email_or_username,
                "password": password,
                "device_information": convert_and_respect_annotation_metadata(
                    object_=device_information, annotation=typing.Optional[DeviceInformation], direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    LoginResponse,
                    parse_obj_as(
                        type_=LoginResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def verify_email(
        self,
        *,
        email_key: str,
        verification_code: int,
        device_information: typing.Optional[DeviceInformation] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[LoginVerificationResponse]:
        """
        Validates the 4-digit verification code sent during login or registration. On success, returns JWT access and refresh tokens along with user details. The email_key from the login/register response and the code from the user's email are both required.

        Parameters
        ----------
        email_key : str
            Email verification key

        verification_code : int
            4-digit verification code

        device_information : typing.Optional[DeviceInformation]
            Device tracking information

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

        Returns
        -------
        AsyncHttpResponse[LoginVerificationResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/auth/verify",
            method="POST",
            json={
                "email_key": email_key,
                "verification_code": verification_code,
                "device_information": convert_and_respect_annotation_metadata(
                    object_=device_information, annotation=typing.Optional[DeviceInformation], direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    LoginVerificationResponse,
                    parse_obj_as(
                        type_=LoginVerificationResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def refresh_token(
        self, *, refresh_token: str, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[RefreshTokenResponse]:
        """
        Exchanges a valid refresh token for a new access token and refresh token pair. Implements token rotation — the old refresh token is invalidated and a new one is issued. Use this to maintain sessions without requiring the user to re-authenticate.

        Parameters
        ----------
        refresh_token : str
            Refresh token

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

        Returns
        -------
        AsyncHttpResponse[RefreshTokenResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/auth/refresh",
            method="POST",
            json={
                "refresh_token": refresh_token,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    RefreshTokenResponse,
                    parse_obj_as(
                        type_=RefreshTokenResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def logout(
        self, *, refresh_token: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[LogoutResponse]:
        """
        Logs out the current user by revoking their refresh token and invalidating the associated device session. Requires a valid Bearer token. The refresh token provided in the body is permanently revoked and cannot be reused.

        Parameters
        ----------
        refresh_token : typing.Optional[str]
            Refresh token to invalidate

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

        Returns
        -------
        AsyncHttpResponse[LogoutResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/auth/logout",
            method="POST",
            json={
                "refresh_token": refresh_token,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    LogoutResponse,
                    parse_obj_as(
                        type_=LogoutResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def request_password_reset(
        self, *, email: str, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[PasswordResetResponse]:
        """
        Sends a 4-digit verification code to the user's email if the account exists. For security, always returns a success response regardless of whether the email is registered (prevents email enumeration). Codes expire after 5 minutes. Rate-limited to 1 request per minute per email. After receiving the code, submit it with the new password to /password/reset/verify.

        Parameters
        ----------
        email : str
            User email address

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

        Returns
        -------
        AsyncHttpResponse[PasswordResetResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/auth/password/reset",
            method="POST",
            json={
                "email": email,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PasswordResetResponse,
                    parse_obj_as(
                        type_=PasswordResetResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def verify_password_reset(
        self,
        *,
        email: str,
        verification_code: int,
        new_password: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[PasswordResetVerifyResponse]:
        """
        Validates the 4-digit verification code sent to the user's email and sets the new password. Codes are one-time use and expire after 5 minutes. On success, all existing refresh tokens are revoked, forcing re-authentication on all devices. Password strength requirements are enforced.

        Parameters
        ----------
        email : str
            User email address

        verification_code : int
            4-digit verification code

        new_password : str
            New password (min 8 chars with complexity, max 72 chars due to bcrypt limit)

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

        Returns
        -------
        AsyncHttpResponse[PasswordResetVerifyResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/auth/password/reset/verify",
            method="POST",
            json={
                "email": email,
                "verification_code": verification_code,
                "new_password": new_password,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PasswordResetVerifyResponse,
                    parse_obj_as(
                        type_=PasswordResetVerifyResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def update_password(
        self,
        *,
        current_password: str,
        new_password: str,
        confirm_password: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[PasswordUpdateResponse]:
        """
        Changes the password for the currently authenticated user. Requires the current password for verification and enforces password strength requirements (minimum 8 characters, at least one special character). On success, all other device sessions are revoked while keeping the current session active. Requires Bearer token authentication.

        Parameters
        ----------
        current_password : str
            Current password for verification

        new_password : str
            New password (min 8 chars with complexity, max 72 chars due to bcrypt limit)

        confirm_password : str
            Confirmation of new password (must match new_password)

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

        Returns
        -------
        AsyncHttpResponse[PasswordUpdateResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/auth/password/update",
            method="PUT",
            json={
                "current_password": current_password,
                "new_password": new_password,
                "confirm_password": confirm_password,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PasswordUpdateResponse,
                    parse_obj_as(
                        type_=PasswordUpdateResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def validate_email(
        self, *, email: str, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[EmailValidationResponse]:
        """
        Checks whether an email address is eligible for registration. Validates format, checks availability (not already registered), and detects organization domain matches. Use this during registration to provide real-time feedback. Returns validity, availability, and optional organization details if the email domain matches an existing organization.

        Parameters
        ----------
        email : str
            Email address to validate for signup eligibility

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

        Returns
        -------
        AsyncHttpResponse[EmailValidationResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/auth/validate-email",
            method="POST",
            json={
                "email": email,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    EmailValidationResponse,
                    parse_obj_as(
                        type_=EmailValidationResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def resend_verification_code(
        self, *, email_key: str, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[ResendCodeResponse]:
        """
        Generates and sends a new 4-digit verification code to the user's email. Works for login, registration, and password reset verification flows. The previous code is invalidated and a new one is generated with a fresh expiry window. Requires the email_key from the original login/register response.

        Parameters
        ----------
        email_key : str
            Email verification key

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

        Returns
        -------
        AsyncHttpResponse[ResendCodeResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/auth/resend-code",
            method="POST",
            json={
                "email_key": email_key,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ResendCodeResponse,
                    parse_obj_as(
                        type_=ResendCodeResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def validate_token(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[TokenValidationResponse]:
        """
        Checks whether the current authentication token (Bearer or API key) is still valid. If the request passes authentication, the token is valid and the endpoint returns success. Used by frontends to verify session state without making a data request.

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

        Returns
        -------
        AsyncHttpResponse[TokenValidationResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/auth/validate",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TokenValidationResponse,
                    parse_obj_as(
                        type_=TokenValidationResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def dev_login(
        self,
        *,
        email_or_username: str,
        password: str,
        device_information: typing.Optional[DeviceInformation] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[LoginVerificationResponse]:
        """
        Authenticates credentials and immediately returns JWT tokens without sending a verification code. Only available in local, develop, and test environments — returns 403 in production and staging. Useful for automated testing and local development workflows.

        Parameters
        ----------
        email_or_username : str
            Email address or username

        password : str
            User password

        device_information : typing.Optional[DeviceInformation]
            Device tracking information

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

        Returns
        -------
        AsyncHttpResponse[LoginVerificationResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/auth/dev-login",
            method="POST",
            json={
                "email_or_username": email_or_username,
                "password": password,
                "device_information": convert_and_respect_annotation_metadata(
                    object_=device_information, annotation=typing.Optional[DeviceInformation], direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    LoginVerificationResponse,
                    parse_obj_as(
                        type_=LoginVerificationResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def google_authorize(
        self,
        *,
        redirect_uri: str,
        organization_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[GoogleAuthorizeResponse]:
        """
        Generates a Google OAuth 2.0 authorization URL for Sign-In with Google. Returns a URL containing a CSRF state token that the client should redirect the user to. The state token is stored server-side and validated during the callback to prevent CSRF attacks. Optionally accepts an organization_id to pre-associate the user with an organization.

        Parameters
        ----------
        redirect_uri : str
            Frontend URL to redirect to after authentication

        organization_id : typing.Optional[str]
            Optional organization ID to associate user with

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

        Returns
        -------
        AsyncHttpResponse[GoogleAuthorizeResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/auth/google/authorize",
            method="POST",
            json={
                "redirect_uri": redirect_uri,
                "organization_id": organization_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GoogleAuthorizeResponse,
                    parse_obj_as(
                        type_=GoogleAuthorizeResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def google_callback(
        self,
        *,
        code: str,
        state: str,
        error: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[None]:
        """
        Handles the OAuth 2.0 callback from Google after user authorization. Exchanges the authorization code for tokens, creates or links the user account, and returns an HTML page that passes the JWT tokens to the frontend via postMessage. Validates the CSRF state token to prevent cross-site request forgery.

        Parameters
        ----------
        code : str
            Authorization code from Google

        state : str
            CSRF state token

        error : typing.Optional[str]
            Error from Google

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/auth/google/callback",
            method="GET",
            params={
                "code": code,
                "state": state,
                "error": error,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    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)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
