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

from __future__ import annotations
from .diffactionenum import DiffActionEnum
from .resourcetypeenum import ResourceTypeEnum
from datetime import datetime
from novu_py.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL
import pydantic
from pydantic import model_serializer
from typing import Any, Dict, Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class ResourceDiffDtoUpdatedByTypedDict(TypedDict):
    r"""User who last updated the resource"""

    id: str
    r"""User ID"""
    first_name: str
    r"""User first name"""
    last_name: NotRequired[Nullable[str]]
    r"""User last name"""
    external_id: NotRequired[str]
    r"""User external ID"""


class ResourceDiffDtoUpdatedBy(BaseModel):
    r"""User who last updated the resource"""

    id: Annotated[str, pydantic.Field(alias="_id")]
    r"""User ID"""

    first_name: Annotated[str, pydantic.Field(alias="firstName")]
    r"""User first name"""

    last_name: Annotated[OptionalNullable[str], pydantic.Field(alias="lastName")] = (
        UNSET
    )
    r"""User last name"""

    external_id: Annotated[Optional[str], pydantic.Field(alias="externalId")] = None
    r"""User external ID"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["lastName", "externalId"])
        nullable_fields = set(["lastName"])
        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


class ResourceDiffDtoSourceResourceTypedDict(TypedDict):
    r"""Source resource information"""

    id: NotRequired[Nullable[str]]
    r"""Resource ID (workflow ID or step ID)"""
    name: NotRequired[Nullable[str]]
    r"""Resource name (workflow name or step name)"""
    updated_by: NotRequired[Nullable[ResourceDiffDtoUpdatedByTypedDict]]
    r"""User who last updated the resource"""
    updated_at: NotRequired[Nullable[datetime]]
    r"""When the resource was last updated"""


class ResourceDiffDtoSourceResource(BaseModel):
    r"""Source resource information"""

    id: OptionalNullable[str] = UNSET
    r"""Resource ID (workflow ID or step ID)"""

    name: OptionalNullable[str] = UNSET
    r"""Resource name (workflow name or step name)"""

    updated_by: Annotated[
        OptionalNullable[ResourceDiffDtoUpdatedBy], pydantic.Field(alias="updatedBy")
    ] = UNSET
    r"""User who last updated the resource"""

    updated_at: Annotated[
        OptionalNullable[datetime], pydantic.Field(alias="updatedAt")
    ] = UNSET
    r"""When the resource was last updated"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["id", "name", "updatedBy", "updatedAt"])
        nullable_fields = set(["id", "name", "updatedBy", "updatedAt"])
        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


class ResourceDiffDtoTargetResourceUpdatedByTypedDict(TypedDict):
    r"""User who last updated the resource"""

    id: str
    r"""User ID"""
    first_name: str
    r"""User first name"""
    last_name: NotRequired[Nullable[str]]
    r"""User last name"""
    external_id: NotRequired[str]
    r"""User external ID"""


class ResourceDiffDtoTargetResourceUpdatedBy(BaseModel):
    r"""User who last updated the resource"""

    id: Annotated[str, pydantic.Field(alias="_id")]
    r"""User ID"""

    first_name: Annotated[str, pydantic.Field(alias="firstName")]
    r"""User first name"""

    last_name: Annotated[OptionalNullable[str], pydantic.Field(alias="lastName")] = (
        UNSET
    )
    r"""User last name"""

    external_id: Annotated[Optional[str], pydantic.Field(alias="externalId")] = None
    r"""User external ID"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["lastName", "externalId"])
        nullable_fields = set(["lastName"])
        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


class ResourceDiffDtoTargetResourceTypedDict(TypedDict):
    r"""Target resource information"""

    id: NotRequired[Nullable[str]]
    r"""Resource ID (workflow ID or step ID)"""
    name: NotRequired[Nullable[str]]
    r"""Resource name (workflow name or step name)"""
    updated_by: NotRequired[Nullable[ResourceDiffDtoTargetResourceUpdatedByTypedDict]]
    r"""User who last updated the resource"""
    updated_at: NotRequired[Nullable[datetime]]
    r"""When the resource was last updated"""


class ResourceDiffDtoTargetResource(BaseModel):
    r"""Target resource information"""

    id: OptionalNullable[str] = UNSET
    r"""Resource ID (workflow ID or step ID)"""

    name: OptionalNullable[str] = UNSET
    r"""Resource name (workflow name or step name)"""

    updated_by: Annotated[
        OptionalNullable[ResourceDiffDtoTargetResourceUpdatedBy],
        pydantic.Field(alias="updatedBy"),
    ] = UNSET
    r"""User who last updated the resource"""

    updated_at: Annotated[
        OptionalNullable[datetime], pydantic.Field(alias="updatedAt")
    ] = UNSET
    r"""When the resource was last updated"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["id", "name", "updatedBy", "updatedAt"])
        nullable_fields = set(["id", "name", "updatedBy", "updatedAt"])
        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


class DiffsTypedDict(TypedDict):
    r"""Detailed changes (only for modified resources)"""

    previous: NotRequired[Nullable[Dict[str, Any]]]
    r"""Previous state of the resource (null for added resources)"""
    new: NotRequired[Nullable[Dict[str, Any]]]
    r"""New state of the resource (null for deleted resources)"""


class Diffs(BaseModel):
    r"""Detailed changes (only for modified resources)"""

    previous: OptionalNullable[Dict[str, Any]] = UNSET
    r"""Previous state of the resource (null for added resources)"""

    new: OptionalNullable[Dict[str, Any]] = UNSET
    r"""New state of the resource (null for deleted resources)"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["previous", "new"])
        nullable_fields = set(["previous", "new"])
        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


class ResourceDiffDtoTypedDict(TypedDict):
    resource_type: ResourceTypeEnum
    r"""Type of the layout"""
    action: DiffActionEnum
    r"""Type of change"""
    source_resource: NotRequired[Nullable[ResourceDiffDtoSourceResourceTypedDict]]
    r"""Source resource information"""
    target_resource: NotRequired[Nullable[ResourceDiffDtoTargetResourceTypedDict]]
    r"""Target resource information"""
    diffs: NotRequired[DiffsTypedDict]
    r"""Detailed changes (only for modified resources)"""
    step_type: NotRequired[str]
    r"""Step type (only for step resources)"""
    previous_index: NotRequired[float]
    r"""Previous index in steps array (for moved/deleted steps)"""
    new_index: NotRequired[float]
    r"""New index in steps array (for moved/added steps)"""


class ResourceDiffDto(BaseModel):
    resource_type: Annotated[ResourceTypeEnum, pydantic.Field(alias="resourceType")]
    r"""Type of the layout"""

    action: DiffActionEnum
    r"""Type of change"""

    source_resource: Annotated[
        OptionalNullable[ResourceDiffDtoSourceResource],
        pydantic.Field(alias="sourceResource"),
    ] = UNSET
    r"""Source resource information"""

    target_resource: Annotated[
        OptionalNullable[ResourceDiffDtoTargetResource],
        pydantic.Field(alias="targetResource"),
    ] = UNSET
    r"""Target resource information"""

    diffs: Optional[Diffs] = None
    r"""Detailed changes (only for modified resources)"""

    step_type: Annotated[Optional[str], pydantic.Field(alias="stepType")] = None
    r"""Step type (only for step resources)"""

    previous_index: Annotated[
        Optional[float], pydantic.Field(alias="previousIndex")
    ] = None
    r"""Previous index in steps array (for moved/deleted steps)"""

    new_index: Annotated[Optional[float], pydantic.Field(alias="newIndex")] = None
    r"""New index in steps array (for moved/added steps)"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(
            [
                "sourceResource",
                "targetResource",
                "diffs",
                "stepType",
                "previousIndex",
                "newIndex",
            ]
        )
        nullable_fields = set(["sourceResource", "targetResource"])
        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


try:
    ResourceDiffDtoUpdatedBy.model_rebuild()
except NameError:
    pass
try:
    ResourceDiffDtoSourceResource.model_rebuild()
except NameError:
    pass
try:
    ResourceDiffDtoTargetResourceUpdatedBy.model_rebuild()
except NameError:
    pass
try:
    ResourceDiffDtoTargetResource.model_rebuild()
except NameError:
    pass
try:
    ResourceDiffDto.model_rebuild()
except NameError:
    pass
