"""
Cortex Agent API.

OpenAPI 3.0 specification for the Cortex Agent API  # noqa: E501

The version of the OpenAPI document: 0.1.0
Contact: support@snowflake.com
Generated by: https://openapi-generator.tech

Do not edit this file manually.
"""

from __future__ import annotations

import json
import pprint
import re  # noqa: F401

from typing import Any, Dict, List, Optional

from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr, field_validator
from typing_extensions import Annotated

from snowflake.core.cortex.lite_agent_service._generated.models.agent_instructions import (
    AgentInstructions,
    AgentInstructionsModel,
)
from snowflake.core.cortex.lite_agent_service._generated.models.agent_models import AgentModels, AgentModelsModel
from snowflake.core.cortex.lite_agent_service._generated.models.agent_orchestration import (
    AgentOrchestration,
    AgentOrchestrationModel,
)
from snowflake.core.cortex.lite_agent_service._generated.models.mcp_server_wrapper import (
    McpServerWrapper,
    McpServerWrapperModel,
)
from snowflake.core.cortex.lite_agent_service._generated.models.message import Message, MessageModel
from snowflake.core.cortex.lite_agent_service._generated.models.tool import Tool, ToolModel
from snowflake.core.cortex.lite_agent_service._generated.models.tool_choice import ToolChoice, ToolChoiceModel


class AgentRunRequest(BaseModel):
    """A model object representing the AgentRunRequest resource.

    Constructs an object of type AgentRunRequest with the provided properties.

    Parameters
    __________
    messages : list[Message]
        The conversation history and current message.
        Contains both user queries and assistant responses in chronological order.
    models : AgentModels, optional

    orchestration : AgentOrchestration, optional

    instructions : AgentInstructions, optional

    model : str, optional
        The identifier of the LLM to use for processing.
    response_instruction : str, optional
        Optional instructions to guide the model's response style and behavior.
        Can be used to set the tone, format, or specific requirements for responses.
    experimental : object, optional
        reserved
    tools : list[Tool], optional
        List of tools available for the agent to use.
        Tools may have a corresponding configuration in tool_resources.
    tool_resources : Dict[str, object], optional
        Configuration for each tool referenced in the tools array.
        Keys must match the name field of tools.
    tool_choice : ToolChoice, optional

    thread_id : int, optional
        The id of the thread.
    parent_message_id : int, optional
        The id of the message from which this run should begin.
    variables : object, optional
        Dictionary of variables with metadata.
        Each variable can include value, type information, and flags indicating whether it's a session or prompt variable.
    query_tags : list[object], optional
        Query tags to be attached to the Snowflake session. These will be applied for all queries executed by the agent.
    tool_bindings : object, optional
        Maps tools to their variable bindings. For each tool, specifies which input parameters
        should be automatically injected with variable definitions.
    origin_application : str,  default 'external'
        The application that initiated this agent run request.
        Used for tracking and analytics.
    internal_metadata : object, optional
        Internal metadata for the request. This field is reserved for internal use.
    client_metadata : object, optional
        Client-provided metadata for the request. Can be used by clients
        to pass additional context or configuration.
    mcp_servers : list[McpServerWrapper], optional
        List of MCP (Model Context Protocol) servers to use for this request.
        Each server is specified with a server_spec containing its fully qualified name.
    """

    models: Optional[AgentModels] = None

    orchestration: Optional[AgentOrchestration] = None

    instructions: Optional[AgentInstructions] = None

    model: Optional[StrictStr] = None

    response_instruction: Optional[StrictStr] = None

    experimental: Optional[Dict[str, Any]] = None

    messages: Annotated[List[Message], Field(min_length=1)]

    tools: Optional[List[Tool]] = None

    tool_resources: Optional[Dict[str, Dict[str, Any]]] = None

    tool_choice: Optional[ToolChoice] = None

    thread_id: Optional[StrictInt] = None

    parent_message_id: Optional[StrictInt] = None

    variables: Optional[Dict[str, Any]] = None

    query_tags: Optional[List[Any]] = None

    tool_bindings: Optional[Dict[str, Any]] = None

    origin_application: Optional[StrictStr] = "external"

    internal_metadata: Optional[Dict[str, Any]] = None

    client_metadata: Optional[Dict[str, Any]] = None

    mcp_servers: Optional[List[McpServerWrapper]] = None

    __properties = [
        "models",
        "orchestration",
        "instructions",
        "model",
        "response_instruction",
        "experimental",
        "messages",
        "tools",
        "tool_resources",
        "tool_choice",
        "thread_id",
        "parent_message_id",
        "variables",
        "query_tags",
        "tool_bindings",
        "origin_application",
        "internal_metadata",
        "client_metadata",
        "mcp_servers",
    ]

    @field_validator("origin_application")
    def origin_application_validate_enum(cls, v):
        if v is None:
            return v
        if v not in ("inline_copilot", "data_science_agent", "microsoft_teams", "coding_agent", "external"):
            raise ValueError(
                "must validate the enum values ('inline_copilot','data_science_agent','microsoft_teams','coding_agent','external')"
            )
        return v

    model_config = ConfigDict(
        validate_by_name=True,
        validate_assignment=True,
    )

    def to_str(self) -> str:
        """Returns the string representation of the model using alias."""
        return pprint.pformat(self.dict(by_alias=True))

    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias."""
        return json.dumps(self.to_dict())

    @classmethod
    def from_json(cls, json_str: str) -> AgentRunRequest:
        """Create an instance of AgentRunRequest from a JSON string."""
        return cls.from_dict(json.loads(json_str))

    def to_dict(
        self,
        hide_readonly_properties: bool = False,
    ) -> dict[str, Any]:
        """Returns the dictionary representation of the model using alias."""
        exclude_properties = set()

        if hide_readonly_properties:
            exclude_properties.update({})

        _dict = self.model_dump(serialize_as_any=True, by_alias=True, exclude=exclude_properties, exclude_none=True)

        # override the default output from pydantic by calling `to_dict()` of models
        if self.models:
            _dict["models"] = self.models.to_dict()

        # override the default output from pydantic by calling `to_dict()` of orchestration
        if self.orchestration:
            _dict["orchestration"] = self.orchestration.to_dict()

        # override the default output from pydantic by calling `to_dict()` of instructions
        if self.instructions:
            _dict["instructions"] = self.instructions.to_dict()

        # override the default output from pydantic by calling `to_dict()` of each item in messages (list)
        _items = []
        if self.messages:
            for _item in self.messages:
                if _item:
                    _items.append(_item.to_dict())
            _dict["messages"] = _items

        # override the default output from pydantic by calling `to_dict()` of each item in tools (list)
        _items = []
        if self.tools:
            for _item in self.tools:
                if _item:
                    _items.append(_item.to_dict())
            _dict["tools"] = _items

        # override the default output from pydantic by calling `to_dict()` of tool_choice
        if self.tool_choice:
            _dict["tool_choice"] = self.tool_choice.to_dict()

        # override the default output from pydantic by calling `to_dict()` of each item in mcp_servers (list)
        _items = []
        if self.mcp_servers:
            for _item in self.mcp_servers:
                if _item:
                    _items.append(_item.to_dict())
            _dict["mcp_servers"] = _items

        # set to None if tool_choice (nullable) is None
        if self.tool_choice is None:
            _dict["tool_choice"] = None

        return _dict

    def to_dict_without_readonly_properties(self) -> dict[str, Any]:
        """Return the dictionary representation of the model without readonly properties."""
        return self.to_dict(hide_readonly_properties=True)

    @classmethod
    def from_dict(cls, obj: dict) -> AgentRunRequest:
        """Create an instance of AgentRunRequest from a dict."""
        if obj is None:
            return None

        if type(obj) is not dict:
            return AgentRunRequest.model_validate(obj)

        _obj = AgentRunRequest.model_validate(
            {
                "models": AgentModels.from_dict(obj.get("models")) if obj.get("models") is not None else None,
                "orchestration": AgentOrchestration.from_dict(obj.get("orchestration"))
                if obj.get("orchestration") is not None
                else None,
                "instructions": AgentInstructions.from_dict(obj.get("instructions"))
                if obj.get("instructions") is not None
                else None,
                "model": obj.get("model"),
                "response_instruction": obj.get("response_instruction"),
                "experimental": obj.get("experimental"),
                "messages": [Message.from_dict(_item) for _item in obj.get("messages")]
                if obj.get("messages") is not None
                else None,
                "tools": [Tool.from_dict(_item) for _item in obj.get("tools")]
                if obj.get("tools") is not None
                else None,
                "tool_resources": obj.get("tool_resources"),
                "tool_choice": ToolChoice.from_dict(obj.get("tool_choice"))
                if obj.get("tool_choice") is not None
                else None,
                "thread_id": obj.get("thread_id"),
                "parent_message_id": obj.get("parent_message_id"),
                "variables": obj.get("variables"),
                "query_tags": obj.get("query_tags"),
                "tool_bindings": obj.get("tool_bindings"),
                "origin_application": obj.get("origin_application")
                if obj.get("origin_application") is not None
                else "external",
                "internal_metadata": obj.get("internal_metadata"),
                "client_metadata": obj.get("client_metadata"),
                "mcp_servers": [McpServerWrapper.from_dict(_item) for _item in obj.get("mcp_servers")]
                if obj.get("mcp_servers") is not None
                else None,
            }
        )

        return _obj


class AgentRunRequestModel:
    def __init__(
        self,
        messages: list[Message],
        # optional properties
        models: Optional[AgentModels] = None,
        orchestration: Optional[AgentOrchestration] = None,
        instructions: Optional[AgentInstructions] = None,
        model: Optional[str] = None,
        response_instruction: Optional[str] = None,
        experimental: Optional[object] = None,
        tools: Optional[list[Tool]] = None,
        tool_resources: Optional[Dict[str, object]] = None,
        tool_choice: Optional[ToolChoice] = None,
        thread_id: Optional[int] = None,
        parent_message_id: Optional[int] = None,
        variables: Optional[object] = None,
        query_tags: Optional[list[object]] = None,
        tool_bindings: Optional[object] = None,
        origin_application: Optional[str] = "external",
        internal_metadata: Optional[object] = None,
        client_metadata: Optional[object] = None,
        mcp_servers: Optional[list[McpServerWrapper]] = None,
    ):
        """A model object representing the AgentRunRequest resource.

                Constructs an object of type AgentRunRequest with the provided properties.

                Parameters
                __________
                messages : list[Message]
                    The conversation history and current message.
        Contains both user queries and assistant responses in chronological order.

                models : AgentModels, optional

                orchestration : AgentOrchestration, optional

                instructions : AgentInstructions, optional

                model : str, optional
                    The identifier of the LLM to use for processing.
                response_instruction : str, optional
                    Optional instructions to guide the model's response style and behavior.
        Can be used to set the tone, format, or specific requirements for responses.

                experimental : object, optional
                    reserved
                tools : list[Tool], optional
                    List of tools available for the agent to use.
        Tools may have a corresponding configuration in tool_resources.

                tool_resources : Dict[str, object], optional
                    Configuration for each tool referenced in the tools array.
        Keys must match the name field of tools.

                tool_choice : ToolChoice, optional

                thread_id : int, optional
                    The id of the thread.

                parent_message_id : int, optional
                    The id of the message from which this run should begin.

                variables : object, optional
                    Dictionary of variables with metadata.
        Each variable can include value, type information, and flags indicating whether it's a session or prompt variable.

                query_tags : list[object], optional
                    Query tags to be attached to the Snowflake session. These will be applied for all queries executed by the agent.

                tool_bindings : object, optional
                    Maps tools to their variable bindings. For each tool, specifies which input parameters
        should be automatically injected with variable definitions.

                origin_application : str,  default 'external'
                    The application that initiated this agent run request.
        Used for tracking and analytics.

                internal_metadata : object, optional
                    Internal metadata for the request. This field is reserved for internal use.

                client_metadata : object, optional
                    Client-provided metadata for the request. Can be used by clients
        to pass additional context or configuration.

                mcp_servers : list[McpServerWrapper], optional
                    List of MCP (Model Context Protocol) servers to use for this request.
        Each server is specified with a server_spec containing its fully qualified name.
        """
        self.models = models
        self.orchestration = orchestration
        self.instructions = instructions
        self.model = model
        self.response_instruction = response_instruction
        self.experimental = experimental
        self.messages = messages
        self.tools = tools
        self.tool_resources = tool_resources
        self.tool_choice = tool_choice
        self.thread_id = thread_id
        self.parent_message_id = parent_message_id
        self.variables = variables
        self.query_tags = query_tags
        self.tool_bindings = tool_bindings
        self.origin_application = origin_application
        self.internal_metadata = internal_metadata
        self.client_metadata = client_metadata
        self.mcp_servers = mcp_servers

    __properties = [
        "models",
        "orchestration",
        "instructions",
        "model",
        "response_instruction",
        "experimental",
        "messages",
        "tools",
        "tool_resources",
        "tool_choice",
        "thread_id",
        "parent_message_id",
        "variables",
        "query_tags",
        "tool_bindings",
        "origin_application",
        "internal_metadata",
        "client_metadata",
        "mcp_servers",
    ]

    def __repr__(self) -> str:
        return repr(self._to_model())

    def _to_model(self):
        return AgentRunRequest(
            models=self.models._to_model() if self.models is not None else None,
            orchestration=self.orchestration._to_model() if self.orchestration is not None else None,
            instructions=self.instructions._to_model() if self.instructions is not None else None,
            model=self.model,
            response_instruction=self.response_instruction,
            experimental=self.experimental,
            messages=[x._to_model() for x in self.messages] if self.messages is not None else None,
            tools=[x._to_model() for x in self.tools] if self.tools is not None else None,
            tool_resources=self.tool_resources,
            tool_choice=self.tool_choice._to_model() if self.tool_choice is not None else None,
            thread_id=self.thread_id,
            parent_message_id=self.parent_message_id,
            variables=self.variables,
            query_tags=self.query_tags,
            tool_bindings=self.tool_bindings,
            origin_application=self.origin_application,
            internal_metadata=self.internal_metadata,
            client_metadata=self.client_metadata,
            mcp_servers=[x._to_model() for x in self.mcp_servers] if self.mcp_servers is not None else None,
        )

    @classmethod
    def _from_model(cls, model) -> AgentRunRequestModel:
        return AgentRunRequestModel(
            models=AgentModelsModel._from_model(model.models) if model.models else None,
            orchestration=AgentOrchestrationModel._from_model(model.orchestration) if model.orchestration else None,
            instructions=AgentInstructionsModel._from_model(model.instructions) if model.instructions else None,
            model=model.model,
            response_instruction=model.response_instruction,
            experimental=model.experimental,
            messages=[MessageModel._from_model(x) for x in model.messages] if model.messages else None,
            tools=[ToolModel._from_model(x) for x in model.tools] if model.tools else None,
            tool_resources=model.tool_resources,
            tool_choice=ToolChoiceModel._from_model(model.tool_choice) if model.tool_choice else None,
            thread_id=model.thread_id,
            parent_message_id=model.parent_message_id,
            variables=model.variables,
            query_tags=model.query_tags,
            tool_bindings=model.tool_bindings,
            origin_application=model.origin_application,
            internal_metadata=model.internal_metadata,
            client_metadata=model.client_metadata,
            mcp_servers=[McpServerWrapperModel._from_model(x) for x in model.mcp_servers]
            if model.mcp_servers
            else None,
        )

    def to_dict(self):
        """Create a dictionary of the properties from a AgentRunRequest.

        This method constructs a dictionary with the key-value entries corresponding to the properties of the AgentRunRequest object.

        Returns
        _______
        dict
            A dictionary object created using the input model.
        """
        return self._to_model().to_dict()

    @classmethod
    def from_dict(cls, obj: dict) -> AgentRunRequestModel:
        """Create an instance of AgentRunRequest from a dict.

        This method constructs a AgentRunRequest object from a dictionary with the key-value pairs of its properties.

        Parameters
        ----------
        obj : dict
            A dictionary whose keys and values correspond to the properties of the resource object.

        Returns
        _______
        AgentRunRequest
            A AgentRunRequest object created using the input dictionary; this will fail if the required properties are missing.
        """
        return cls._from_model(AgentRunRequest.from_dict(obj))


AgentRunRequest._model_class = AgentRunRequestModel
