"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""

from __future__ import annotations
from .chatstreamoptions import ChatStreamOptions, ChatStreamOptionsTypedDict
from .message import Message, MessageTypedDict
from .reasoningsummaryverbosity import ReasoningSummaryVerbosity
from .responseformatjsonschema import (
    ResponseFormatJSONSchema,
    ResponseFormatJSONSchemaTypedDict,
)
from .responseformattextgrammar import (
    ResponseFormatTextGrammar,
    ResponseFormatTextGrammarTypedDict,
)
from .tooldefinitionjson import ToolDefinitionJSON, ToolDefinitionJSONTypedDict
from openrouter.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
    UnrecognizedStr,
)
from openrouter.utils import validate_const, validate_open_enum
import pydantic
from pydantic import model_serializer
from pydantic.functional_validators import AfterValidator, PlainValidator
from typing import Any, Dict, List, Literal, Optional, Union
from typing_extensions import Annotated, NotRequired, TypeAliasType, TypedDict


Effort = Union[
    Literal[
        "minimal",
        "low",
        "medium",
        "high",
    ],
    UnrecognizedStr,
]


class ReasoningTypedDict(TypedDict):
    effort: NotRequired[Nullable[Effort]]
    summary: NotRequired[Nullable[ReasoningSummaryVerbosity]]


class Reasoning(BaseModel):
    effort: Annotated[
        OptionalNullable[Effort], PlainValidator(validate_open_enum(False))
    ] = UNSET

    summary: Annotated[
        OptionalNullable[ReasoningSummaryVerbosity],
        PlainValidator(validate_open_enum(False)),
    ] = UNSET

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["effort", "summary"]
        nullable_fields = ["effort", "summary"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


class ChatGenerationParamsResponseFormatPythonTypedDict(TypedDict):
    type: Literal["python"]


class ChatGenerationParamsResponseFormatPython(BaseModel):
    TYPE: Annotated[
        Annotated[Literal["python"], AfterValidator(validate_const("python"))],
        pydantic.Field(alias="type"),
    ] = "python"


class ChatGenerationParamsResponseFormatJSONObjectTypedDict(TypedDict):
    type: Literal["json_object"]


class ChatGenerationParamsResponseFormatJSONObject(BaseModel):
    TYPE: Annotated[
        Annotated[
            Literal["json_object"], AfterValidator(validate_const("json_object"))
        ],
        pydantic.Field(alias="type"),
    ] = "json_object"


class ChatGenerationParamsResponseFormatTextTypedDict(TypedDict):
    type: Literal["text"]


class ChatGenerationParamsResponseFormatText(BaseModel):
    TYPE: Annotated[
        Annotated[Literal["text"], AfterValidator(validate_const("text"))],
        pydantic.Field(alias="type"),
    ] = "text"


ChatGenerationParamsResponseFormatUnionTypedDict = TypeAliasType(
    "ChatGenerationParamsResponseFormatUnionTypedDict",
    Union[
        ChatGenerationParamsResponseFormatTextTypedDict,
        ChatGenerationParamsResponseFormatJSONObjectTypedDict,
        ChatGenerationParamsResponseFormatPythonTypedDict,
        ResponseFormatJSONSchemaTypedDict,
        ResponseFormatTextGrammarTypedDict,
    ],
)


ChatGenerationParamsResponseFormatUnion = TypeAliasType(
    "ChatGenerationParamsResponseFormatUnion",
    Union[
        ChatGenerationParamsResponseFormatText,
        ChatGenerationParamsResponseFormatJSONObject,
        ChatGenerationParamsResponseFormatPython,
        ResponseFormatJSONSchema,
        ResponseFormatTextGrammar,
    ],
)


ChatGenerationParamsStopTypedDict = TypeAliasType(
    "ChatGenerationParamsStopTypedDict", Union[str, List[str]]
)


ChatGenerationParamsStop = TypeAliasType(
    "ChatGenerationParamsStop", Union[str, List[str]]
)


class ChatGenerationParamsTypedDict(TypedDict):
    messages: List[MessageTypedDict]
    model: NotRequired[str]
    models: NotRequired[List[str]]
    frequency_penalty: NotRequired[Nullable[float]]
    logit_bias: NotRequired[Nullable[Dict[str, float]]]
    logprobs: NotRequired[Nullable[bool]]
    top_logprobs: NotRequired[Nullable[float]]
    max_completion_tokens: NotRequired[Nullable[float]]
    max_tokens: NotRequired[Nullable[float]]
    metadata: NotRequired[Dict[str, str]]
    presence_penalty: NotRequired[Nullable[float]]
    reasoning: NotRequired[ReasoningTypedDict]
    response_format: NotRequired[ChatGenerationParamsResponseFormatUnionTypedDict]
    seed: NotRequired[Nullable[int]]
    stop: NotRequired[Nullable[ChatGenerationParamsStopTypedDict]]
    stream: NotRequired[bool]
    stream_options: NotRequired[Nullable[ChatStreamOptionsTypedDict]]
    temperature: NotRequired[Nullable[float]]
    tool_choice: NotRequired[Any]
    tools: NotRequired[List[ToolDefinitionJSONTypedDict]]
    top_p: NotRequired[Nullable[float]]
    user: NotRequired[str]


class ChatGenerationParams(BaseModel):
    messages: List[Message]

    model: Optional[str] = None

    models: Optional[List[str]] = None

    frequency_penalty: OptionalNullable[float] = UNSET

    logit_bias: OptionalNullable[Dict[str, float]] = UNSET

    logprobs: OptionalNullable[bool] = UNSET

    top_logprobs: OptionalNullable[float] = UNSET

    max_completion_tokens: OptionalNullable[float] = UNSET

    max_tokens: OptionalNullable[float] = UNSET

    metadata: Optional[Dict[str, str]] = None

    presence_penalty: OptionalNullable[float] = UNSET

    reasoning: Optional[Reasoning] = None

    response_format: Optional[ChatGenerationParamsResponseFormatUnion] = None

    seed: OptionalNullable[int] = UNSET

    stop: OptionalNullable[ChatGenerationParamsStop] = UNSET

    stream: Optional[bool] = False

    stream_options: OptionalNullable[ChatStreamOptions] = UNSET

    temperature: OptionalNullable[float] = UNSET

    tool_choice: Optional[Any] = None

    tools: Optional[List[ToolDefinitionJSON]] = None

    top_p: OptionalNullable[float] = UNSET

    user: Optional[str] = None

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "model",
            "models",
            "frequency_penalty",
            "logit_bias",
            "logprobs",
            "top_logprobs",
            "max_completion_tokens",
            "max_tokens",
            "metadata",
            "presence_penalty",
            "reasoning",
            "response_format",
            "seed",
            "stop",
            "stream",
            "stream_options",
            "temperature",
            "tool_choice",
            "tools",
            "top_p",
            "user",
        ]
        nullable_fields = [
            "frequency_penalty",
            "logit_bias",
            "logprobs",
            "top_logprobs",
            "max_completion_tokens",
            "max_tokens",
            "presence_penalty",
            "seed",
            "stop",
            "stream_options",
            "temperature",
            "top_p",
        ]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m
