# 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]:
        """
        Register a new user account with email verification.

        Creates a new user account, sends a 4-digit verification code via email,
        and creates an EmailVerification record. User must verify their email
        using the /verify endpoint to complete registration.

        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]:
        """
        Authenticate user credentials and initiate two-factor authentication (2FA) via email verification.

        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]:
        """
        Verify email verification code and return JWT tokens.

        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]:
        """
        Refresh an expired access token using a valid refresh token.

        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]:
        """
        Logout the current user and invalidate their authentication tokens.

        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]:
        """
        Request a password reset for a user account.

        Sends a 4-digit verification code to the user's email if the account exists.
        For security, always returns success regardless of whether the email exists.

        **Security Features:**
        - Generic response (prevents email enumeration)
        - Rate limiting (1 request per minute per email)
        - Time-limited codes (5 minutes expiry)
        - Automatic cleanup of expired codes

        **Flow:**
        1. User requests password reset with email
        2. If account exists, receives 4-digit code via email
        3. User submits code + new password to /password/reset/verify
        4. All existing sessions are revoked on successful reset

        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]:
        """
        Verify password reset code and set new password.

        Validates the 4-digit code and updates the user's password.
        All existing refresh tokens are revoked, forcing re-authentication.

        **Security Features:**
        - Code expires after 5 minutes
        - One-time use codes (marked as used after verification)
        - Password strength validation
        - All sessions revoked on success

        **Errors:**
        - 404: User not found
        - 422: Invalid/expired code or weak password

        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]:
        """
        Update password for authenticated user.

        Requires current password verification and enforces password strength requirements.
        All other device sessions are revoked while keeping the current session active.

        **Security Features:**
        - Requires authentication (Bearer token)
        - Verifies current password before allowing change
        - Password strength validation
        - Keeps current session active
        - Revokes all other device sessions
        - Logs password change for audit

        **Password Requirements:**
        - Minimum 8 characters
        - At least one special character
        - Not in common weak passwords list

        **Errors:**
        - 401: Current password is incorrect
        - 404: User not found
        - 422: Passwords don't match or new password is weak

        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]:
        """
        Validate email for registration.

        Checks if email is:
        - Valid format
        - Not already registered
        - Associated with an organization domain

        This endpoint is used during registration to provide real-time feedback
        about email validity and availability.

        **Returns:**
        - valid: Whether email format is valid
        - available: Whether email is available for registration
        - organization_id: Organization ID if email domain matches (optional)
        - organization_name: Organization name if email domain matches (optional)

        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]:
        """
        Resend verification code.

        Generates and sends a new 4-digit verification code to the user's email.
        Works for login, registration, and password reset verifications.

        **Security Features:**
        - Validates verification record exists
        - Checks if verification already used
        - Generates new random code
        - Updates expiry time

        **Errors:**
        - 404: Verification record not found
        - 422: Verification already used
        - 500: Email sending failed

        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 forgot_password(
        self, *, email: str, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[PasswordResetResponse]:
        """
        Request a password reset (alias for /password/reset).

        Sends a 4-digit verification code to the user's email if the account exists.
        For security, always returns success regardless of whether the email exists.

        **Security Features:**
        - Generic response (prevents email enumeration)
        - Rate limiting (1 request per minute per email)
        - Time-limited codes (5 minutes expiry)
        - Automatic cleanup of expired codes

        **Flow:**
        1. User requests password reset with email
        2. If account exists, receives 4-digit code via email
        3. User submits code + new password to /password/reset
        4. All existing sessions are revoked on successful reset

        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/forgot",
            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 validate_token(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[TokenValidationResponse]:
        """
        Validate current authentication token.

        Used by frontend to check if the session is still valid.
        If the request reaches this endpoint (passes AuthContext dependency),
        the token is valid.

        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]:
        """
        Development login (bypass email verification).

        **WARNING:** This endpoint is only available in non-production environments
        or when explicitly enabled via configuration.

        It validates credentials and immediately returns authentication tokens
        without sending a verification code.

        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]:
        """
        Generate Google OAuth authorization URL for Sign-In.

        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]:
        """
        Handle Google OAuth callback and show success/error page.

        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]:
        """
        Register a new user account with email verification.

        Creates a new user account, sends a 4-digit verification code via email,
        and creates an EmailVerification record. User must verify their email
        using the /verify endpoint to complete registration.

        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]:
        """
        Authenticate user credentials and initiate two-factor authentication (2FA) via email verification.

        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]:
        """
        Verify email verification code and return JWT tokens.

        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]:
        """
        Refresh an expired access token using a valid refresh token.

        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]:
        """
        Logout the current user and invalidate their authentication tokens.

        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]:
        """
        Request a password reset for a user account.

        Sends a 4-digit verification code to the user's email if the account exists.
        For security, always returns success regardless of whether the email exists.

        **Security Features:**
        - Generic response (prevents email enumeration)
        - Rate limiting (1 request per minute per email)
        - Time-limited codes (5 minutes expiry)
        - Automatic cleanup of expired codes

        **Flow:**
        1. User requests password reset with email
        2. If account exists, receives 4-digit code via email
        3. User submits code + new password to /password/reset/verify
        4. All existing sessions are revoked on successful reset

        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]:
        """
        Verify password reset code and set new password.

        Validates the 4-digit code and updates the user's password.
        All existing refresh tokens are revoked, forcing re-authentication.

        **Security Features:**
        - Code expires after 5 minutes
        - One-time use codes (marked as used after verification)
        - Password strength validation
        - All sessions revoked on success

        **Errors:**
        - 404: User not found
        - 422: Invalid/expired code or weak password

        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]:
        """
        Update password for authenticated user.

        Requires current password verification and enforces password strength requirements.
        All other device sessions are revoked while keeping the current session active.

        **Security Features:**
        - Requires authentication (Bearer token)
        - Verifies current password before allowing change
        - Password strength validation
        - Keeps current session active
        - Revokes all other device sessions
        - Logs password change for audit

        **Password Requirements:**
        - Minimum 8 characters
        - At least one special character
        - Not in common weak passwords list

        **Errors:**
        - 401: Current password is incorrect
        - 404: User not found
        - 422: Passwords don't match or new password is weak

        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]:
        """
        Validate email for registration.

        Checks if email is:
        - Valid format
        - Not already registered
        - Associated with an organization domain

        This endpoint is used during registration to provide real-time feedback
        about email validity and availability.

        **Returns:**
        - valid: Whether email format is valid
        - available: Whether email is available for registration
        - organization_id: Organization ID if email domain matches (optional)
        - organization_name: Organization name if email domain matches (optional)

        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]:
        """
        Resend verification code.

        Generates and sends a new 4-digit verification code to the user's email.
        Works for login, registration, and password reset verifications.

        **Security Features:**
        - Validates verification record exists
        - Checks if verification already used
        - Generates new random code
        - Updates expiry time

        **Errors:**
        - 404: Verification record not found
        - 422: Verification already used
        - 500: Email sending failed

        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 forgot_password(
        self, *, email: str, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[PasswordResetResponse]:
        """
        Request a password reset (alias for /password/reset).

        Sends a 4-digit verification code to the user's email if the account exists.
        For security, always returns success regardless of whether the email exists.

        **Security Features:**
        - Generic response (prevents email enumeration)
        - Rate limiting (1 request per minute per email)
        - Time-limited codes (5 minutes expiry)
        - Automatic cleanup of expired codes

        **Flow:**
        1. User requests password reset with email
        2. If account exists, receives 4-digit code via email
        3. User submits code + new password to /password/reset
        4. All existing sessions are revoked on successful reset

        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/forgot",
            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 validate_token(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[TokenValidationResponse]:
        """
        Validate current authentication token.

        Used by frontend to check if the session is still valid.
        If the request reaches this endpoint (passes AuthContext dependency),
        the token is valid.

        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]:
        """
        Development login (bypass email verification).

        **WARNING:** This endpoint is only available in non-production environments
        or when explicitly enabled via configuration.

        It validates credentials and immediately returns authentication tokens
        without sending a verification code.

        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]:
        """
        Generate Google OAuth authorization URL for Sign-In.

        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]:
        """
        Handle Google OAuth callback and show success/error page.

        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)
