"""
Cortex Inference API.

OpenAPI 3.0 specification for the Cortex REST 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, List, Optional, Union

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

from snowflake.core.cortex.inference_service._generated.models.complete_request_anthropic import (
    CompleteRequestAnthropic,
    CompleteRequestAnthropicModel,
)
from snowflake.core.cortex.inference_service._generated.models.complete_request_messages_inner import (
    CompleteRequestMessagesInner,
    CompleteRequestMessagesInnerModel,
)
from snowflake.core.cortex.inference_service._generated.models.complete_request_openai import (
    CompleteRequestOpenai,
    CompleteRequestOpenaiModel,
)
from snowflake.core.cortex.inference_service._generated.models.complete_request_response_format import (
    CompleteRequestResponseFormat,
    CompleteRequestResponseFormatModel,
)
from snowflake.core.cortex.inference_service._generated.models.guardrails_config import (
    GuardrailsConfig,
    GuardrailsConfigModel,
)
from snowflake.core.cortex.inference_service._generated.models.tool import Tool, ToolModel
from snowflake.core.cortex.inference_service._generated.models.tool_choice import ToolChoice, ToolChoiceModel


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

    Constructs an object of type CompleteRequest with the provided properties.

    Parameters
    __________
    model : str
        The model name. See documentation for possible values.
    messages : list[CompleteRequestMessagesInner]

    anthropic : CompleteRequestAnthropic, optional

    openai : CompleteRequestOpenai, optional

    temperature : float, optional
        Temperature controls the amount of randomness used in response generation. A higher temperature corresponds to more randomness.
    top_p : float,  default 1.0
        Threshold probability for nucleus sampling. A higher top-p value increases the diversity of tokens that the model considers, while a lower value results in more predictable output.
    max_tokens : int,  default 4096
        The maximum number of output tokens to produce. The default value is model-dependent.
    max_output_tokens : int, optional
        Deprecated in favor of "max_tokens", which has identical behavior.
    response_format : CompleteRequestResponseFormat, optional

    guardrails : GuardrailsConfig, optional

    tools : list[Tool], optional
        List of tools to be used during tool calling
    tool_choice : ToolChoice, optional

    provisioned_throughput_id : str, optional
        The provisioned throughput ID to be used with the request.
    sf_ml_xp_inflight_prompt_action : str, optional
        Reserved
    sf_ml_xp_inflight_prompt_client_id : str, optional
        Reserved
    sf_ml_xp_inflight_prompt_public_key : str, optional
        Reserved
    stream : bool,  default True
        Reserved
    """

    model: StrictStr

    anthropic: Optional[CompleteRequestAnthropic] = None

    openai: Optional[CompleteRequestOpenai] = None

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

    temperature: Optional[
        Union[Annotated[float, Field(strict=True, ge=0.0)], Annotated[int, Field(strict=True, ge=0)]]
    ] = None

    top_p: Optional[
        Union[Annotated[float, Field(le=1.0, strict=True, ge=0.0)], Annotated[int, Field(le=1, strict=True, ge=0)]]
    ] = 1.0

    max_tokens: Optional[Annotated[int, Field(strict=True, ge=0)]] = 4096

    max_output_tokens: Optional[StrictInt] = None

    response_format: Optional[CompleteRequestResponseFormat] = None

    guardrails: Optional[GuardrailsConfig] = None

    tools: Optional[List[Tool]] = None

    tool_choice: Optional[ToolChoice] = None

    provisioned_throughput_id: Optional[StrictStr] = None

    sf_ml_xp_inflight_prompt_action: Optional[StrictStr] = Field(default=None, alias="sf-ml-xp-inflight-prompt-action")

    sf_ml_xp_inflight_prompt_client_id: Optional[StrictStr] = Field(
        default=None, alias="sf-ml-xp-inflight-prompt-client-id"
    )

    sf_ml_xp_inflight_prompt_public_key: Optional[StrictStr] = Field(
        default=None, alias="sf-ml-xp-inflight-prompt-public-key"
    )

    stream: Optional[StrictBool] = True

    __properties = [
        "model",
        "anthropic",
        "openai",
        "messages",
        "temperature",
        "top_p",
        "max_tokens",
        "max_output_tokens",
        "response_format",
        "guardrails",
        "tools",
        "tool_choice",
        "provisioned_throughput_id",
        "sf-ml-xp-inflight-prompt-action",
        "sf-ml-xp-inflight-prompt-client-id",
        "sf-ml-xp-inflight-prompt-public-key",
        "stream",
    ]

    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) -> CompleteRequest:
        """Create an instance of CompleteRequest 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 anthropic
        if self.anthropic:
            _dict["anthropic"] = self.anthropic.to_dict()

        # override the default output from pydantic by calling `to_dict()` of openai
        if self.openai:
            _dict["openai"] = self.openai.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 response_format
        if self.response_format:
            _dict["response_format"] = self.response_format.to_dict()

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

        # 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()

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

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

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

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

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

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

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

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

        # set to None if stream (nullable) is None
        if self.stream is None:
            _dict["stream"] = 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) -> CompleteRequest:
        """Create an instance of CompleteRequest from a dict."""
        if obj is None:
            return None

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

        _obj = CompleteRequest.model_validate(
            {
                "model": obj.get("model"),
                "anthropic": CompleteRequestAnthropic.from_dict(obj.get("anthropic"))
                if obj.get("anthropic") is not None
                else None,
                "openai": CompleteRequestOpenai.from_dict(obj.get("openai")) if obj.get("openai") is not None else None,
                "messages": [CompleteRequestMessagesInner.from_dict(_item) for _item in obj.get("messages")]
                if obj.get("messages") is not None
                else None,
                "temperature": obj.get("temperature"),
                "top_p": obj.get("top_p") if obj.get("top_p") is not None else 1.0,
                "max_tokens": obj.get("max_tokens") if obj.get("max_tokens") is not None else 4096,
                "max_output_tokens": obj.get("max_output_tokens"),
                "response_format": CompleteRequestResponseFormat.from_dict(obj.get("response_format"))
                if obj.get("response_format") is not None
                else None,
                "guardrails": GuardrailsConfig.from_dict(obj.get("guardrails"))
                if obj.get("guardrails") 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_choice": ToolChoice.from_dict(obj.get("tool_choice"))
                if obj.get("tool_choice") is not None
                else None,
                "provisioned_throughput_id": obj.get("provisioned_throughput_id"),
                "sf_ml_xp_inflight_prompt_action": obj.get("sf-ml-xp-inflight-prompt-action"),
                "sf_ml_xp_inflight_prompt_client_id": obj.get("sf-ml-xp-inflight-prompt-client-id"),
                "sf_ml_xp_inflight_prompt_public_key": obj.get("sf-ml-xp-inflight-prompt-public-key"),
                "stream": obj.get("stream") if obj.get("stream") is not None else True,
            }
        )

        return _obj


class CompleteRequestModel:
    def __init__(
        self,
        model: str,
        messages: list[CompleteRequestMessagesInner],
        # optional properties
        anthropic: Optional[CompleteRequestAnthropic] = None,
        openai: Optional[CompleteRequestOpenai] = None,
        temperature: Optional[float] = None,
        top_p: Optional[float] = 1.0,
        max_tokens: Optional[int] = 4096,
        max_output_tokens: Optional[int] = None,
        response_format: Optional[CompleteRequestResponseFormat] = None,
        guardrails: Optional[GuardrailsConfig] = None,
        tools: Optional[list[Tool]] = None,
        tool_choice: Optional[ToolChoice] = None,
        provisioned_throughput_id: Optional[str] = None,
        sf_ml_xp_inflight_prompt_action: Optional[str] = None,
        sf_ml_xp_inflight_prompt_client_id: Optional[str] = None,
        sf_ml_xp_inflight_prompt_public_key: Optional[str] = None,
        stream: Optional[bool] = True,
    ):
        """A model object representing the CompleteRequest resource.

        Constructs an object of type CompleteRequest with the provided properties.

        Parameters
        __________
        model : str
            The model name. See documentation for possible values.
        messages : list[CompleteRequestMessagesInner]

        anthropic : CompleteRequestAnthropic, optional

        openai : CompleteRequestOpenai, optional

        temperature : float, optional
            Temperature controls the amount of randomness used in response generation. A higher temperature corresponds to more randomness.
        top_p : float,  default 1.0
            Threshold probability for nucleus sampling. A higher top-p value increases the diversity of tokens that the model considers, while a lower value results in more predictable output.
        max_tokens : int,  default 4096
            The maximum number of output tokens to produce. The default value is model-dependent.
        max_output_tokens : int, optional
            Deprecated in favor of "max_tokens", which has identical behavior.
        response_format : CompleteRequestResponseFormat, optional

        guardrails : GuardrailsConfig, optional

        tools : list[Tool], optional
            List of tools to be used during tool calling
        tool_choice : ToolChoice, optional

        provisioned_throughput_id : str, optional
            The provisioned throughput ID to be used with the request.
        sf_ml_xp_inflight_prompt_action : str, optional
            Reserved
        sf_ml_xp_inflight_prompt_client_id : str, optional
            Reserved
        sf_ml_xp_inflight_prompt_public_key : str, optional
            Reserved
        stream : bool,  default True
            Reserved
        """
        self.model = model
        self.anthropic = anthropic
        self.openai = openai
        self.messages = messages
        self.temperature = temperature
        self.top_p = top_p
        self.max_tokens = max_tokens
        self.max_output_tokens = max_output_tokens
        self.response_format = response_format
        self.guardrails = guardrails
        self.tools = tools
        self.tool_choice = tool_choice
        self.provisioned_throughput_id = provisioned_throughput_id
        self.sf_ml_xp_inflight_prompt_action = sf_ml_xp_inflight_prompt_action
        self.sf_ml_xp_inflight_prompt_client_id = sf_ml_xp_inflight_prompt_client_id
        self.sf_ml_xp_inflight_prompt_public_key = sf_ml_xp_inflight_prompt_public_key
        self.stream = stream

    __properties = [
        "model",
        "anthropic",
        "openai",
        "messages",
        "temperature",
        "top_p",
        "max_tokens",
        "max_output_tokens",
        "response_format",
        "guardrails",
        "tools",
        "tool_choice",
        "provisioned_throughput_id",
        "sf-ml-xp-inflight-prompt-action",
        "sf-ml-xp-inflight-prompt-client-id",
        "sf-ml-xp-inflight-prompt-public-key",
        "stream",
    ]

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

    def _to_model(self):
        return CompleteRequest(
            model=self.model,
            anthropic=self.anthropic._to_model() if self.anthropic is not None else None,
            openai=self.openai._to_model() if self.openai is not None else None,
            messages=[x._to_model() for x in self.messages] if self.messages is not None else None,
            temperature=self.temperature,
            top_p=self.top_p,
            max_tokens=self.max_tokens,
            max_output_tokens=self.max_output_tokens,
            response_format=self.response_format._to_model() if self.response_format is not None else None,
            guardrails=self.guardrails._to_model() if self.guardrails is not None else None,
            tools=[x._to_model() for x in self.tools] if self.tools is not None else None,
            tool_choice=self.tool_choice._to_model() if self.tool_choice is not None else None,
            provisioned_throughput_id=self.provisioned_throughput_id,
            sf_ml_xp_inflight_prompt_action=self.sf_ml_xp_inflight_prompt_action,
            sf_ml_xp_inflight_prompt_client_id=self.sf_ml_xp_inflight_prompt_client_id,
            sf_ml_xp_inflight_prompt_public_key=self.sf_ml_xp_inflight_prompt_public_key,
            stream=self.stream,
        )

    @classmethod
    def _from_model(cls, model) -> CompleteRequestModel:
        return CompleteRequestModel(
            model=model.model,
            anthropic=CompleteRequestAnthropicModel._from_model(model.anthropic) if model.anthropic else None,
            openai=CompleteRequestOpenaiModel._from_model(model.openai) if model.openai else None,
            messages=[CompleteRequestMessagesInnerModel._from_model(x) for x in model.messages]
            if model.messages
            else None,
            temperature=model.temperature,
            top_p=model.top_p,
            max_tokens=model.max_tokens,
            max_output_tokens=model.max_output_tokens,
            response_format=CompleteRequestResponseFormatModel._from_model(model.response_format)
            if model.response_format
            else None,
            guardrails=GuardrailsConfigModel._from_model(model.guardrails) if model.guardrails else None,
            tools=[ToolModel._from_model(x) for x in model.tools] if model.tools else None,
            tool_choice=ToolChoiceModel._from_model(model.tool_choice) if model.tool_choice else None,
            provisioned_throughput_id=model.provisioned_throughput_id,
            sf_ml_xp_inflight_prompt_action=model.sf_ml_xp_inflight_prompt_action,
            sf_ml_xp_inflight_prompt_client_id=model.sf_ml_xp_inflight_prompt_client_id,
            sf_ml_xp_inflight_prompt_public_key=model.sf_ml_xp_inflight_prompt_public_key,
            stream=model.stream,
        )

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

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

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

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

        This method constructs a CompleteRequest 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
        _______
        CompleteRequest
            A CompleteRequest object created using the input dictionary; this will fail if the required properties are missing.
        """
        return cls._from_model(CompleteRequest.from_dict(obj))


CompleteRequest._model_class = CompleteRequestModel
