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

from __future__ import annotations
from .output_value import OutputValue, OutputValueTypedDict
from attio.types import BaseModel, Nullable, UNSET_SENTINEL
from attio.utils import get_discriminator
from pydantic import Discriminator, Tag, model_serializer
from typing import Any, List, Literal, Union
from typing_extensions import Annotated, TypeAliasType, TypedDict


class AttributeIDTypedDict(TypedDict):
    workspace_id: str
    r"""A UUID representing the workspace this attribute belongs to."""
    object_id: str
    r"""A UUID to identify the object or list that this attribute belongs to"""
    attribute_id: str
    r"""A UUID to identify this attribute."""


class AttributeID(BaseModel):
    workspace_id: str
    r"""A UUID representing the workspace this attribute belongs to."""

    object_id: str
    r"""A UUID to identify the object or list that this attribute belongs to"""

    attribute_id: str
    r"""A UUID to identify this attribute."""


AttributeType = Literal[
    "text",
    "number",
    "checkbox",
    "currency",
    "date",
    "timestamp",
    "rating",
    "status",
    "select",
    "record-reference",
    "actor-reference",
    "location",
    "domain",
    "email-address",
    "phone-number",
    "interaction",
    "personal-name",
]
r"""The type of the attribute."""


AttributeTypeStatic = Literal["static",]


class DefaultValueStaticTypedDict(TypedDict):
    type: AttributeTypeStatic
    template: List[OutputValueTypedDict]


class DefaultValueStatic(BaseModel):
    type: AttributeTypeStatic

    template: List[OutputValue]


AttributeTypeDynamic = Literal["dynamic",]


Template = 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 DefaultValueDynamicTypedDict(TypedDict):
    type: AttributeTypeDynamic
    template: Any


class DefaultValueDynamic(BaseModel):
    type: AttributeTypeDynamic

    template: Any


DefaultValueUnionTypedDict = TypeAliasType(
    "DefaultValueUnionTypedDict",
    Union[DefaultValueDynamicTypedDict, DefaultValueStaticTypedDict],
)
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."""


DefaultValueUnion = Annotated[
    Union[
        Annotated[DefaultValueDynamic, Tag("dynamic")],
        Annotated[DefaultValueStatic, 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."""


class RelationshipIDTypedDict(TypedDict):
    workspace_id: str
    r"""A UUID representing the workspace this attribute belongs to."""
    object_id: str
    r"""A UUID to identify the object or list that this attribute belongs to"""
    attribute_id: str
    r"""A UUID to identify this attribute."""


class RelationshipID(BaseModel):
    workspace_id: str
    r"""A UUID representing the workspace this attribute belongs to."""

    object_id: str
    r"""A UUID to identify the object or list that this attribute belongs to"""

    attribute_id: str
    r"""A UUID to identify this attribute."""


class RelationshipTypedDict(TypedDict):
    r"""If this attribute is related to another attribute, this is an object that includes an `id` property that identifies the other attribute. `null` means no relationship exists. See [the help center](https://attio.com/help/reference/managing-your-data/attributes#relationship-attributes) for more details about relationship attributes."""

    id: RelationshipIDTypedDict
    object_slug: str
    r"""The slug of the object that the related attribute belongs to."""
    title: str
    r"""The title of the related attribute."""
    api_slug: str
    r"""The API slug identifying the related 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 Relationship(BaseModel):
    r"""If this attribute is related to another attribute, this is an object that includes an `id` property that identifies the other attribute. `null` means no relationship exists. See [the help center](https://attio.com/help/reference/managing-your-data/attributes#relationship-attributes) for more details about relationship attributes."""

    id: RelationshipID

    object_slug: str
    r"""The slug of the object that the related attribute belongs to."""

    title: str
    r"""The title of the related attribute."""

    api_slug: str
    r"""The API slug identifying the related 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."""


DefaultCurrencyCode = 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."""


DisplayType = 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 CurrencyTypedDict(TypedDict):
    r"""Configuration available for attributes of type \"currency\"."""

    default_currency_code: Nullable[DefaultCurrencyCode]
    r"""The ISO4217 code representing the currency that values for this attribute should be stored in."""
    display_type: Nullable[DisplayType]
    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 Currency(BaseModel):
    r"""Configuration available for attributes of type \"currency\"."""

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

    display_type: Nullable[DisplayType]
    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 \"$\"."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        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:
                m[k] = val

        return m


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

    allowed_object_ids: Nullable[List[str]]
    r"""A list of UUIDs to indicate which objects records are allowed to belong to. Leave empty to to allow records from all object types."""


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

    allowed_object_ids: Nullable[List[str]]
    r"""A list of UUIDs to indicate which objects records are allowed to belong to. Leave empty to to allow records from all object types."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        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:
                m[k] = val

        return m


class ConfigTypedDict(TypedDict):
    r"""Additional, type-dependent configuration for the attribute."""

    currency: CurrencyTypedDict
    r"""Configuration available for attributes of type \"currency\"."""
    record_reference: RecordReferenceTypedDict
    r"""Configuration available for attributes of type \"record-reference\"."""


class Config(BaseModel):
    r"""Additional, type-dependent configuration for the attribute."""

    currency: Currency
    r"""Configuration available for attributes of type \"currency\"."""

    record_reference: RecordReference
    r"""Configuration available for attributes of type \"record-reference\"."""


class AttributeTypedDict(TypedDict):
    id: AttributeIDTypedDict
    title: str
    r"""A title for the attribute, to be displayed across the app."""
    description: Nullable[str]
    r"""A text description of the attribute."""
    api_slug: str
    r"""A unique slug for the attribute for use in API responses and URLs. Formatted in snake case."""
    type: AttributeType
    r"""The type of the attribute."""
    is_system_attribute: bool
    r"""`true` if this is an Attio system-defined attribute, `false` if defined by a user or non-Attio system."""
    is_writable: bool
    r"""Whether or not this attribute can be written to. Can only be false when `is_system_attribute` is `true` (user-defined attributes are always writeable). If `false`, this usually means the attribute is enriched by Attio."""
    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."""
    is_default_value_enabled: bool
    r"""Whether this attribute has a default value enabled. Must be `true` when `is_required` is `true`."""
    is_archived: bool
    r"""Whether this attribute has been archived. Archived attributes are hidden from most UI, but can be restored either over the API or in workspace settings. See the [guide on archiving and deleting](/docs/archiving-vs-deleting)for more information."""
    default_value: Nullable[DefaultValueUnionTypedDict]
    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."""
    relationship: Nullable[RelationshipTypedDict]
    r"""If this attribute is related to another attribute, this is an object that includes an `id` property that identifies the other attribute. `null` means no relationship exists. See [the help center](https://attio.com/help/reference/managing-your-data/attributes#relationship-attributes) for more details about relationship attributes."""
    created_at: str
    r"""When this attribute was created."""
    config: ConfigTypedDict
    r"""Additional, type-dependent configuration for the attribute."""


class Attribute(BaseModel):
    id: AttributeID

    title: str
    r"""A title for the attribute, to be displayed across the app."""

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

    api_slug: str
    r"""A unique slug for the attribute for use in API responses and URLs. Formatted in snake case."""

    type: AttributeType
    r"""The type of the attribute."""

    is_system_attribute: bool
    r"""`true` if this is an Attio system-defined attribute, `false` if defined by a user or non-Attio system."""

    is_writable: bool
    r"""Whether or not this attribute can be written to. Can only be false when `is_system_attribute` is `true` (user-defined attributes are always writeable). If `false`, this usually means the attribute is enriched by Attio."""

    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."""

    is_default_value_enabled: bool
    r"""Whether this attribute has a default value enabled. Must be `true` when `is_required` is `true`."""

    is_archived: bool
    r"""Whether this attribute has been archived. Archived attributes are hidden from most UI, but can be restored either over the API or in workspace settings. See the [guide on archiving and deleting](/docs/archiving-vs-deleting)for more information."""

    default_value: Nullable[DefaultValueUnion]
    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."""

    relationship: Nullable[Relationship]
    r"""If this attribute is related to another attribute, this is an object that includes an `id` property that identifies the other attribute. `null` means no relationship exists. See [the help center](https://attio.com/help/reference/managing-your-data/attributes#relationship-attributes) for more details about relationship attributes."""

    created_at: str
    r"""When this attribute was created."""

    config: Config
    r"""Additional, type-dependent configuration for the attribute."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        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:
                m[k] = val

        return m
