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

import typing
from ..core.client_wrapper import SyncClientWrapper
from ..commons.types.entity_id_base import EntityIdBase
from ..commons.types.action_parameter import ActionParameter
from ..commons.types.precondition import Precondition
from ..core.request_options import RequestOptions
from ..commons.types.action_response import ActionResponse
from ..core.serialization import convert_and_respect_annotation_metadata
from ..core.pydantic_utilities import parse_obj_as
from ..commons.errors.not_found_error import NotFoundError
from ..commons.types.error_message import ErrorMessage
from ..commons.errors.bad_request_error import BadRequestError
from ..commons.errors.server_error import ServerError
from json.decoder import JSONDecodeError
from ..core.api_error import ApiError
from ..core.jsonable_encoder import jsonable_encoder
from ..core.client_wrapper import AsyncClientWrapper

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


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

    def create_or_update(
        self,
        *,
        action_id: EntityIdBase,
        name: str,
        description: str,
        user_interaction_required: bool,
        user_form_parameters: typing.Sequence[ActionParameter],
        button_name: typing.Optional[str] = OMIT,
        precondition: typing.Optional[Precondition] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ActionResponse:
        """
        Update an action or create it if it doesn't exist

        Parameters
        ----------
        action_id : EntityIdBase
            ID that uniquely identifies this action

        name : str
            The name of the action. This is displayed to the end user as part of forms when user interaction is required. It is also used to help Maven decide if the action is relevant to a conversation.

        description : str
            The description of the action. Must be less than 1024 characters. This helps Maven decide if the action is relevant to a conversation and is not displayed directly to the end user. Descriptions are used by the LLM.

        user_interaction_required : bool
            Whether the action requires user interaction to execute. If false, and all of the required action parameters are known, the LLM may call the action automatically. If true, an conversations ask call will return a BotActionFormResponse which must be submitted by an API caller. API callers must display a button with the buttonName label to confirm the user's intent.

        user_form_parameters : typing.Sequence[ActionParameter]
            The parameters that the action uses as input. An action will only be executed when all of the required parameters are provided. During execution, actions all have access to the full Conversation and User objects. Parameter values may be inferred from the user's conversation by the LLM.

        button_name : typing.Optional[str]
            When user interaction is required, the name of the button that is shown to the end user to confirm execution of the action

        precondition : typing.Optional[Precondition]
            The preconditions that must be met for an action to be relevant to a conversation. Can be used to restrict actions to certain types of users.

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

        Returns
        -------
        ActionResponse

        Examples
        --------
        from mavenagi import MavenAGI
        from mavenagi.commons import EntityIdBase, Precondition_Group, Precondition_User

        client = MavenAGI(
            organization_id="YOUR_ORGANIZATION_ID",
            agent_id="YOUR_AGENT_ID",
            app_id="YOUR_APP_ID",
            app_secret="YOUR_APP_SECRET",
        )
        client.actions.create_or_update(
            action_id=EntityIdBase(
                reference_id="get-balance",
            ),
            name="Get the user's balance",
            description="This action calls an API to get the user's current balance.",
            user_interaction_required=False,
            user_form_parameters=[],
            precondition=Precondition_Group(
                operator="AND",
                preconditions=[
                    Precondition_User(
                        key="userKey",
                    ),
                    Precondition_User(
                        key="userKey2",
                    ),
                ],
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/actions",
            method="PUT",
            json={
                "actionId": convert_and_respect_annotation_metadata(
                    object_=action_id, annotation=EntityIdBase, direction="write"
                ),
                "name": name,
                "description": description,
                "userInteractionRequired": user_interaction_required,
                "buttonName": button_name,
                "precondition": convert_and_respect_annotation_metadata(
                    object_=precondition, annotation=Precondition, direction="write"
                ),
                "userFormParameters": convert_and_respect_annotation_metadata(
                    object_=user_form_parameters, annotation=typing.Sequence[ActionParameter], direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ActionResponse,
                    parse_obj_as(
                        type_=ActionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise ServerError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def get(
        self, action_reference_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> ActionResponse:
        """
        Get an action by its supplied ID

        Parameters
        ----------
        action_reference_id : str
            The reference ID of the action to get. All other entity ID fields are inferred from the request.

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

        Returns
        -------
        ActionResponse

        Examples
        --------
        from mavenagi import MavenAGI

        client = MavenAGI(
            organization_id="YOUR_ORGANIZATION_ID",
            agent_id="YOUR_AGENT_ID",
            app_id="YOUR_APP_ID",
            app_secret="YOUR_APP_SECRET",
        )
        client.actions.get(
            action_reference_id="get-balance",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/actions/{jsonable_encoder(action_reference_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ActionResponse,
                    parse_obj_as(
                        type_=ActionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise ServerError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def delete(self, action_reference_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
        """
        Delete an action

        Parameters
        ----------
        action_reference_id : str
            The reference ID of the action to unregister. All other entity ID fields are inferred from the request.

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

        Returns
        -------
        None

        Examples
        --------
        from mavenagi import MavenAGI

        client = MavenAGI(
            organization_id="YOUR_ORGANIZATION_ID",
            agent_id="YOUR_AGENT_ID",
            app_id="YOUR_APP_ID",
            app_secret="YOUR_APP_SECRET",
        )
        client.actions.delete(
            action_reference_id="get-balance",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/actions/{jsonable_encoder(action_reference_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise ServerError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)


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

    async def create_or_update(
        self,
        *,
        action_id: EntityIdBase,
        name: str,
        description: str,
        user_interaction_required: bool,
        user_form_parameters: typing.Sequence[ActionParameter],
        button_name: typing.Optional[str] = OMIT,
        precondition: typing.Optional[Precondition] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ActionResponse:
        """
        Update an action or create it if it doesn't exist

        Parameters
        ----------
        action_id : EntityIdBase
            ID that uniquely identifies this action

        name : str
            The name of the action. This is displayed to the end user as part of forms when user interaction is required. It is also used to help Maven decide if the action is relevant to a conversation.

        description : str
            The description of the action. Must be less than 1024 characters. This helps Maven decide if the action is relevant to a conversation and is not displayed directly to the end user. Descriptions are used by the LLM.

        user_interaction_required : bool
            Whether the action requires user interaction to execute. If false, and all of the required action parameters are known, the LLM may call the action automatically. If true, an conversations ask call will return a BotActionFormResponse which must be submitted by an API caller. API callers must display a button with the buttonName label to confirm the user's intent.

        user_form_parameters : typing.Sequence[ActionParameter]
            The parameters that the action uses as input. An action will only be executed when all of the required parameters are provided. During execution, actions all have access to the full Conversation and User objects. Parameter values may be inferred from the user's conversation by the LLM.

        button_name : typing.Optional[str]
            When user interaction is required, the name of the button that is shown to the end user to confirm execution of the action

        precondition : typing.Optional[Precondition]
            The preconditions that must be met for an action to be relevant to a conversation. Can be used to restrict actions to certain types of users.

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

        Returns
        -------
        ActionResponse

        Examples
        --------
        import asyncio

        from mavenagi import AsyncMavenAGI
        from mavenagi.commons import EntityIdBase, Precondition_Group, Precondition_User

        client = AsyncMavenAGI(
            organization_id="YOUR_ORGANIZATION_ID",
            agent_id="YOUR_AGENT_ID",
            app_id="YOUR_APP_ID",
            app_secret="YOUR_APP_SECRET",
        )


        async def main() -> None:
            await client.actions.create_or_update(
                action_id=EntityIdBase(
                    reference_id="get-balance",
                ),
                name="Get the user's balance",
                description="This action calls an API to get the user's current balance.",
                user_interaction_required=False,
                user_form_parameters=[],
                precondition=Precondition_Group(
                    operator="AND",
                    preconditions=[
                        Precondition_User(
                            key="userKey",
                        ),
                        Precondition_User(
                            key="userKey2",
                        ),
                    ],
                ),
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/actions",
            method="PUT",
            json={
                "actionId": convert_and_respect_annotation_metadata(
                    object_=action_id, annotation=EntityIdBase, direction="write"
                ),
                "name": name,
                "description": description,
                "userInteractionRequired": user_interaction_required,
                "buttonName": button_name,
                "precondition": convert_and_respect_annotation_metadata(
                    object_=precondition, annotation=Precondition, direction="write"
                ),
                "userFormParameters": convert_and_respect_annotation_metadata(
                    object_=user_form_parameters, annotation=typing.Sequence[ActionParameter], direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ActionResponse,
                    parse_obj_as(
                        type_=ActionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise ServerError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def get(
        self, action_reference_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> ActionResponse:
        """
        Get an action by its supplied ID

        Parameters
        ----------
        action_reference_id : str
            The reference ID of the action to get. All other entity ID fields are inferred from the request.

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

        Returns
        -------
        ActionResponse

        Examples
        --------
        import asyncio

        from mavenagi import AsyncMavenAGI

        client = AsyncMavenAGI(
            organization_id="YOUR_ORGANIZATION_ID",
            agent_id="YOUR_AGENT_ID",
            app_id="YOUR_APP_ID",
            app_secret="YOUR_APP_SECRET",
        )


        async def main() -> None:
            await client.actions.get(
                action_reference_id="get-balance",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/actions/{jsonable_encoder(action_reference_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ActionResponse,
                    parse_obj_as(
                        type_=ActionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise ServerError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def delete(
        self, action_reference_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> None:
        """
        Delete an action

        Parameters
        ----------
        action_reference_id : str
            The reference ID of the action to unregister. All other entity ID fields are inferred from the request.

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

        Returns
        -------
        None

        Examples
        --------
        import asyncio

        from mavenagi import AsyncMavenAGI

        client = AsyncMavenAGI(
            organization_id="YOUR_ORGANIZATION_ID",
            agent_id="YOUR_AGENT_ID",
            app_id="YOUR_APP_ID",
            app_secret="YOUR_APP_SECRET",
        )


        async def main() -> None:
            await client.actions.delete(
                action_reference_id="get-balance",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/actions/{jsonable_encoder(action_reference_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise ServerError(
                    typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)
