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

from __future__ import annotations
from .attribute import Attribute, AttributeTypedDict
from .input_value_union import InputValueUnion, InputValueUnionTypedDict
from attio.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL
from attio.utils import (
    FieldMetadata,
    PathParamMetadata,
    RequestMetadata,
    get_discriminator,
)
from pydantic import Discriminator, Tag, model_serializer
from typing import Any, List, Literal, Optional, Union
from typing_extensions import Annotated, NotRequired, TypeAliasType, TypedDict


PostV2TargetIdentifierAttributesTarget = Literal[
    "objects",
    "lists",
]
r"""Whether the attribute is to be created on an object or a list."""


PostV2TargetIdentifierAttributesTypeRequest = Literal[
    "text",
    "number",
    "checkbox",
    "currency",
    "date",
    "timestamp",
    "rating",
    "status",
    "select",
    "record-reference",
    "actor-reference",
    "location",
    "domain",
    "email-address",
    "phone-number",
]
r"""The type of the attribute. This value affects the possible `config` values. Attributes of type \"status\" are not supported on objects."""


PostV2TargetIdentifierAttributesTypeStatic = Literal["static",]


class PostV2TargetIdentifierAttributesDefaultValueStaticTypedDict(TypedDict):
    type: PostV2TargetIdentifierAttributesTypeStatic
    template: List[InputValueUnionTypedDict]


class PostV2TargetIdentifierAttributesDefaultValueStatic(BaseModel):
    type: PostV2TargetIdentifierAttributesTypeStatic

    template: List[InputValueUnion]


PostV2TargetIdentifierAttributesTypeDynamic = Literal["dynamic",]


PostV2TargetIdentifierAttributesTemplate = Literal["current-user",]
r"""For actor reference attributes, you may pass a dynamic value of `\"current-user\"`. When creating new records or entries, this will cause the actor reference value to be populated with either the workspace member or API token that created the record/entry."""


class PostV2TargetIdentifierAttributesDefaultValueDynamicTypedDict(TypedDict):
    type: PostV2TargetIdentifierAttributesTypeDynamic
    template: Any


class PostV2TargetIdentifierAttributesDefaultValueDynamic(BaseModel):
    type: PostV2TargetIdentifierAttributesTypeDynamic

    template: Any


PostV2TargetIdentifierAttributesDefaultValueUnionTypedDict = TypeAliasType(
    "PostV2TargetIdentifierAttributesDefaultValueUnionTypedDict",
    Union[
        PostV2TargetIdentifierAttributesDefaultValueDynamicTypedDict,
        PostV2TargetIdentifierAttributesDefaultValueStaticTypedDict,
    ],
)
r"""The default value for this attribute. Static values are used to directly populate values using their contents. Dynamic values are used to lookup data at the point of creation. For example, you could use a dynamic value to insert a value for the currently logged in user. Which default values are available is dependent on the type of the attribute. Default values are not currently supported on people or company objects."""


PostV2TargetIdentifierAttributesDefaultValueUnion = Annotated[
    Union[
        Annotated[PostV2TargetIdentifierAttributesDefaultValueDynamic, Tag("dynamic")],
        Annotated[PostV2TargetIdentifierAttributesDefaultValueStatic, Tag("static")],
    ],
    Discriminator(lambda m: get_discriminator(m, "type", "type")),
]
r"""The default value for this attribute. Static values are used to directly populate values using their contents. Dynamic values are used to lookup data at the point of creation. For example, you could use a dynamic value to insert a value for the currently logged in user. Which default values are available is dependent on the type of the attribute. Default values are not currently supported on people or company objects."""


class PostV2TargetIdentifierAttributesRelationshipTypedDict(TypedDict):
    r"""Optional relationship configuration. When provided, creates a bidirectional relationship between two objects. Can only be used with attributes of type \"record-reference\". If `config.record_reference.allowed_objects` is also provided, it must contain only the relationship object."""

    object: str
    r"""The slug or UUID of the object to create the reverse relationship attribute on."""
    title: str
    r"""The title for the reverse relationship attribute."""
    api_slug: str
    r"""The API slug for the reverse relationship attribute."""
    is_multiselect: bool
    r"""Whether the related attribute supports selecting multiple values. Combined with the parent attribute's `is_multiselect`, this determines the relationship type: both `false` = one-to-one, parent `true` + related `false` = many-to-one, parent `false` + related `true` = one-to-many, both `true` = many-to-many."""


class PostV2TargetIdentifierAttributesRelationship(BaseModel):
    r"""Optional relationship configuration. When provided, creates a bidirectional relationship between two objects. Can only be used with attributes of type \"record-reference\". If `config.record_reference.allowed_objects` is also provided, it must contain only the relationship object."""

    object: str
    r"""The slug or UUID of the object to create the reverse relationship attribute on."""

    title: str
    r"""The title for the reverse relationship attribute."""

    api_slug: str
    r"""The API slug for the reverse relationship attribute."""

    is_multiselect: bool
    r"""Whether the related attribute supports selecting multiple values. Combined with the parent attribute's `is_multiselect`, this determines the relationship type: both `false` = one-to-one, parent `true` + related `false` = many-to-one, parent `false` + related `true` = one-to-many, both `true` = many-to-many."""


PostV2TargetIdentifierAttributesDefaultCurrencyCode = Literal[
    "ARS",
    "AUD",
    "BRL",
    "BGN",
    "CAD",
    "CLP",
    "CNY",
    "COP",
    "CZK",
    "DKK",
    "EUR",
    "FJD",
    "HKD",
    "HUF",
    "ISK",
    "INR",
    "ILS",
    "JPY",
    "KES",
    "KRW",
    "MYR",
    "MXN",
    "NTD",
    "NZD",
    "NGN",
    "NOK",
    "XPF",
    "PEN",
    "PHP",
    "PLN",
    "GBP",
    "RWF",
    "SAR",
    "SGD",
    "ZAR",
    "SEK",
    "CHF",
    "THB",
    "AED",
    "UYU",
    "USD",
]
r"""The ISO4217 code representing the currency that values for this attribute should be stored in."""


PostV2TargetIdentifierAttributesDisplayType = Literal[
    "code",
    "name",
    "narrowSymbol",
    "symbol",
]
r"""How the currency should be displayed across the app. \"code\" will display the ISO currency code e.g. \"USD\", \"name\" will display the localized currency name e.g. \"British pound\", \"narrowSymbol\" will display \"$1\" instead of \"US$1\" and \"symbol\" will display a localized currency symbol such as \"$\"."""


class PostV2TargetIdentifierAttributesCurrencyTypedDict(TypedDict):
    r"""Configuration available for attributes of type \"currency\"."""

    default_currency_code: PostV2TargetIdentifierAttributesDefaultCurrencyCode
    r"""The ISO4217 code representing the currency that values for this attribute should be stored in."""
    display_type: PostV2TargetIdentifierAttributesDisplayType
    r"""How the currency should be displayed across the app. \"code\" will display the ISO currency code e.g. \"USD\", \"name\" will display the localized currency name e.g. \"British pound\", \"narrowSymbol\" will display \"$1\" instead of \"US$1\" and \"symbol\" will display a localized currency symbol such as \"$\"."""


class PostV2TargetIdentifierAttributesCurrency(BaseModel):
    r"""Configuration available for attributes of type \"currency\"."""

    default_currency_code: PostV2TargetIdentifierAttributesDefaultCurrencyCode
    r"""The ISO4217 code representing the currency that values for this attribute should be stored in."""

    display_type: PostV2TargetIdentifierAttributesDisplayType
    r"""How the currency should be displayed across the app. \"code\" will display the ISO currency code e.g. \"USD\", \"name\" will display the localized currency name e.g. \"British pound\", \"narrowSymbol\" will display \"$1\" instead of \"US$1\" and \"symbol\" will display a localized currency symbol such as \"$\"."""


class PostV2TargetIdentifierAttributesRecordReferenceTypedDict(TypedDict):
    r"""Configuration available for attributes of type \"record-reference\"."""

    allowed_objects: List[str]
    r"""A list of slugs or UUIDs to indicate which objects records are allowed to belong to. If `relationship` is also provided, this must contain only the relationship object."""


class PostV2TargetIdentifierAttributesRecordReference(BaseModel):
    r"""Configuration available for attributes of type \"record-reference\"."""

    allowed_objects: List[str]
    r"""A list of slugs or UUIDs to indicate which objects records are allowed to belong to. If `relationship` is also provided, this must contain only the relationship object."""


class PostV2TargetIdentifierAttributesConfigTypedDict(TypedDict):
    currency: NotRequired[PostV2TargetIdentifierAttributesCurrencyTypedDict]
    r"""Configuration available for attributes of type \"currency\"."""
    record_reference: NotRequired[
        PostV2TargetIdentifierAttributesRecordReferenceTypedDict
    ]
    r"""Configuration available for attributes of type \"record-reference\"."""


class PostV2TargetIdentifierAttributesConfig(BaseModel):
    currency: Optional[PostV2TargetIdentifierAttributesCurrency] = None
    r"""Configuration available for attributes of type \"currency\"."""

    record_reference: Optional[PostV2TargetIdentifierAttributesRecordReference] = None
    r"""Configuration available for attributes of type \"record-reference\"."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["currency", "record_reference"])
        serialized = handler(self)
        m = {}

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

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

        return m


class PostV2TargetIdentifierAttributesDataTypedDict(TypedDict):
    title: str
    r"""The name of the attribute. The title will be visible across Attio's UI."""
    description: Nullable[str]
    r"""A text description for the attribute."""
    api_slug: str
    r"""A unique, human-readable slug to access the attribute through URLs and API calls. Formatted in snake case."""
    type: PostV2TargetIdentifierAttributesTypeRequest
    r"""The type of the attribute. This value affects the possible `config` values. Attributes of type \"status\" are not supported on objects."""
    is_required: bool
    r"""When `is_required` is `true`, new records/entries must have a value for this attribute. If `false`, values may be `null`. This value does not affect existing data and you do not need to backfill `null` values if changing `is_required` from `false` to `true`."""
    is_unique: bool
    r"""Whether or not new values for this attribute must be unique. Uniqueness restrictions are only applied to new data and do not apply retroactively to previously created data."""
    is_multiselect: bool
    r"""Whether or not this attribute can have multiple values. Multiselect is only available on some value types."""
    config: PostV2TargetIdentifierAttributesConfigTypedDict
    default_value: NotRequired[
        Nullable[PostV2TargetIdentifierAttributesDefaultValueUnionTypedDict]
    ]
    r"""The default value for this attribute. Static values are used to directly populate values using their contents. Dynamic values are used to lookup data at the point of creation. For example, you could use a dynamic value to insert a value for the currently logged in user. Which default values are available is dependent on the type of the attribute. Default values are not currently supported on people or company objects."""
    relationship: NotRequired[
        Nullable[PostV2TargetIdentifierAttributesRelationshipTypedDict]
    ]
    r"""Optional relationship configuration. When provided, creates a bidirectional relationship between two objects. Can only be used with attributes of type \"record-reference\". If `config.record_reference.allowed_objects` is also provided, it must contain only the relationship object."""


class PostV2TargetIdentifierAttributesData(BaseModel):
    title: str
    r"""The name of the attribute. The title will be visible across Attio's UI."""

    description: Nullable[str]
    r"""A text description for the attribute."""

    api_slug: str
    r"""A unique, human-readable slug to access the attribute through URLs and API calls. Formatted in snake case."""

    type: PostV2TargetIdentifierAttributesTypeRequest
    r"""The type of the attribute. This value affects the possible `config` values. Attributes of type \"status\" are not supported on objects."""

    is_required: bool
    r"""When `is_required` is `true`, new records/entries must have a value for this attribute. If `false`, values may be `null`. This value does not affect existing data and you do not need to backfill `null` values if changing `is_required` from `false` to `true`."""

    is_unique: bool
    r"""Whether or not new values for this attribute must be unique. Uniqueness restrictions are only applied to new data and do not apply retroactively to previously created data."""

    is_multiselect: bool
    r"""Whether or not this attribute can have multiple values. Multiselect is only available on some value types."""

    config: PostV2TargetIdentifierAttributesConfig

    default_value: OptionalNullable[
        PostV2TargetIdentifierAttributesDefaultValueUnion
    ] = UNSET
    r"""The default value for this attribute. Static values are used to directly populate values using their contents. Dynamic values are used to lookup data at the point of creation. For example, you could use a dynamic value to insert a value for the currently logged in user. Which default values are available is dependent on the type of the attribute. Default values are not currently supported on people or company objects."""

    relationship: OptionalNullable[PostV2TargetIdentifierAttributesRelationship] = UNSET
    r"""Optional relationship configuration. When provided, creates a bidirectional relationship between two objects. Can only be used with attributes of type \"record-reference\". If `config.record_reference.allowed_objects` is also provided, it must contain only the relationship object."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["default_value", "relationship"])
        nullable_fields = set(["description", "default_value", "relationship"])
        serialized = handler(self)
        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k, serialized.get(n))
            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 PostV2TargetIdentifierAttributesRequestBodyTypedDict(TypedDict):
    data: PostV2TargetIdentifierAttributesDataTypedDict


class PostV2TargetIdentifierAttributesRequestBody(BaseModel):
    data: PostV2TargetIdentifierAttributesData


class PostV2TargetIdentifierAttributesRequestTypedDict(TypedDict):
    target: PostV2TargetIdentifierAttributesTarget
    r"""Whether the attribute is to be created on an object or a list."""
    identifier: str
    request_body: PostV2TargetIdentifierAttributesRequestBodyTypedDict


class PostV2TargetIdentifierAttributesRequest(BaseModel):
    target: Annotated[
        PostV2TargetIdentifierAttributesTarget,
        FieldMetadata(path=PathParamMetadata(style="simple", explode=False)),
    ]
    r"""Whether the attribute is to be created on an object or a list."""

    identifier: Annotated[
        str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))
    ]

    request_body: Annotated[
        PostV2TargetIdentifierAttributesRequestBody,
        FieldMetadata(request=RequestMetadata(media_type="application/json")),
    ]


PostV2TargetIdentifierAttributesConflictType = Literal["invalid_request_error",]


PostV2TargetIdentifierAttributesConflictCode = Literal["slug_conflict",]


PostV2TargetIdentifierAttributesNotFoundType = Literal["invalid_request_error",]


PostV2TargetIdentifierAttributesNotFoundCode = Literal["not_found",]


PostV2TargetIdentifierAttributesBadRequestType = Literal["invalid_request_error",]


PostV2TargetIdentifierAttributesCodeValidationType = Literal["validation_type",]


class PostV2TargetIdentifierAttributesResponseTypedDict(TypedDict):
    r"""Success"""

    data: AttributeTypedDict


class PostV2TargetIdentifierAttributesResponse(BaseModel):
    r"""Success"""

    data: Attribute
