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

from __future__ import annotations
from .caseexpression import CaseExpression, CaseExpressionTypedDict
from .celexpression import CelExpression, CelExpressionTypedDict
from .contexttaskmetadata import ContextTaskMetadata, ContextTaskMetadataTypedDict
from .contexttoolinfo import ContextToolInfo, ContextToolInfoTypedDict
from .expressiontaskevents import ExpressionTaskEvents, ExpressionTaskEventsTypedDict
from .inputparameter import InputParameter, InputParameterTypedDict
from .jmespathexpression import JMESPathExpression, JMESPathExpressionTypedDict
from .variable import Variable, VariableTypedDict
import pydantic
from pydantic import Discriminator, Tag, model_serializer
from pydantic.functional_validators import AfterValidator
from syllable_sdk.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
)
from syllable_sdk.utils import get_discriminator, validate_const
from typing import Any, Dict, List, Literal, Optional, Union
from typing_extensions import Annotated, NotRequired, TypeAliasType, TypedDict


Expression1TypedDict = TypeAliasType(
    "Expression1TypedDict", Union[CelExpressionTypedDict, JMESPathExpressionTypedDict]
)


Expression1 = Annotated[
    Union[
        Annotated[CelExpression, Tag("cel")],
        Annotated[JMESPathExpression, Tag("jmespath")],
        Annotated[JMESPathExpression, Tag("jp")],
    ],
    Discriminator(lambda m: get_discriminator(m, "type", "type")),
]


Expression2TypedDict = TypeAliasType(
    "Expression2TypedDict", Union[CaseExpressionTypedDict, Expression1TypedDict, str]
)


Expression2 = TypeAliasType("Expression2", Union[CaseExpression, Expression1, str])


class ExpressionTaskTypedDict(TypedDict):
    id: NotRequired[Nullable[str]]
    r"""A unique identifier for the task."""
    config: NotRequired[Nullable[Dict[str, Any]]]
    variables: NotRequired[Nullable[List[VariableTypedDict]]]
    metadata: NotRequired[Nullable[ContextTaskMetadataTypedDict]]
    tool: NotRequired[Nullable[ContextToolInfoTypedDict]]
    type: Literal["expression"]
    version: Literal["v1alpha"]
    inputs: NotRequired[List[InputParameterTypedDict]]
    expression: NotRequired[Nullable[Expression2TypedDict]]
    output: NotRequired[Nullable[Any]]
    on: NotRequired[ExpressionTaskEventsTypedDict]
    r"""Actions to perform when events occur (start, submit)."""


class ExpressionTask(BaseModel):
    id: OptionalNullable[str] = UNSET
    r"""A unique identifier for the task."""

    config: OptionalNullable[Dict[str, Any]] = UNSET

    variables: OptionalNullable[List[Variable]] = UNSET

    metadata: OptionalNullable[ContextTaskMetadata] = UNSET

    tool: OptionalNullable[ContextToolInfo] = UNSET

    TYPE: Annotated[
        Annotated[
            Optional[Literal["expression"]],
            AfterValidator(validate_const("expression")),
        ],
        pydantic.Field(alias="type"),
    ] = "expression"

    VERSION: Annotated[
        Annotated[
            Optional[Literal["v1alpha"]], AfterValidator(validate_const("v1alpha"))
        ],
        pydantic.Field(alias="version"),
    ] = "v1alpha"

    inputs: Optional[List[InputParameter]] = None

    expression: OptionalNullable[Expression2] = UNSET

    output: OptionalNullable[Any] = UNSET

    on: Optional[ExpressionTaskEvents] = None
    r"""Actions to perform when events occur (start, submit)."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(
            [
                "id",
                "config",
                "variables",
                "metadata",
                "tool",
                "type",
                "version",
                "inputs",
                "expression",
                "output",
                "on",
            ]
        )
        nullable_fields = set(
            ["id", "config", "variables", "metadata", "tool", "expression", "output"]
        )
        serialized = handler(self)
        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            is_nullable_and_explicitly_set = (
                k in nullable_fields
                and (self.__pydantic_fields_set__.intersection({n}))  # pylint: disable=no-member
            )

            if val != UNSET_SENTINEL:
                if (
                    val is not None
                    or k not in optional_fields
                    or is_nullable_and_explicitly_set
                ):
                    m[k] = val

        return m
