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

from __future__ import annotations
from ascend_sdk import utils
from ascend_sdk.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
)
from ascend_sdk.utils import validate_open_enum
from enum import Enum
from pydantic import model_serializer
from pydantic.functional_validators import PlainValidator
from typing import Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class AssetCategory(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The NSCC asset category"""

    ASSET_CATEGORY_UNSPECIFIED = "ASSET_CATEGORY_UNSPECIFIED"
    ALTERNATIVE_INVESTMENT = "ALTERNATIVE_INVESTMENT"
    ANNUITY = "ANNUITY"
    AUCTION_RATE_PREFERRED_UIT = "AUCTION_RATE_PREFERRED_UIT"
    CD_AND_COMMERCIAL_PAPER = "CD_AND_COMMERCIAL_PAPER"
    CORPORATE_BOND = "CORPORATE_BOND"
    DEFERRED_SALE_CHARGE_UIT = "DEFERRED_SALE_CHARGE_UIT"
    EQUITY = "EQUITY"
    FOREIGN_CURRENCY = "FOREIGN_CURRENCY"
    FOREIGN_DEBT = "FOREIGN_DEBT"
    FOREIGN_EQUITY = "FOREIGN_EQUITY"
    LIFE_INSURANCE = "LIFE_INSURANCE"
    LIMITED_PARTNERSHIP = "LIMITED_PARTNERSHIP"
    MORTGAGE_BACKED_SECURITY = "MORTGAGE_BACKED_SECURITY"
    MUTUAL_FUND_MONEY_MARKET = "MUTUAL_FUND_MONEY_MARKET"
    MUTUAL_FUND_NON_MONEY_MARKET = "MUTUAL_FUND_NON_MONEY_MARKET"
    MUNICIPAL_BOND = "MUNICIPAL_BOND"
    OPTION = "OPTION"
    REAL_ESTATE_INVESTMENT_TRUST = "REAL_ESTATE_INVESTMENT_TRUST"
    RIGHT = "RIGHT"
    US_GOVERNMENT = "US_GOVERNMENT"
    UNIT_INVESTMENT_TRUST = "UNIT_INVESTMENT_TRUST"
    UNIT = "UNIT"
    WARRANT = "WARRANT"
    ZERO_COUPON_BOND = "ZERO_COUPON_BOND"


class AcatsAssetQuantityTypedDict(TypedDict):
    r"""The quantity of the asset, or the amount if the asset is cash; negative quantity denotes short position Fractional amounts only supported for certain asset types"""

    value: NotRequired[str]
    r"""The decimal value, as a string; Refer to [Google’s Decimal type protocol buffer](https://github.com/googleapis/googleapis/blob/40203ca1880849480bbff7b8715491060bbccdf1/google/type/decimal.proto#L33) for details"""


class AcatsAssetQuantity(BaseModel):
    r"""The quantity of the asset, or the amount if the asset is cash; negative quantity denotes short position Fractional amounts only supported for certain asset types"""

    value: Optional[str] = None
    r"""The decimal value, as a string; Refer to [Google’s Decimal type protocol buffer](https://github.com/googleapis/googleapis/blob/40203ca1880849480bbff7b8715491060bbccdf1/google/type/decimal.proto#L33) for details"""


class AcatsAssetPositionTypedDict(TypedDict):
    r"""The position or amount of the asset"""

    quantity: NotRequired[Nullable[AcatsAssetQuantityTypedDict]]
    r"""The quantity of the asset, or the amount if the asset is cash; negative quantity denotes short position Fractional amounts only supported for certain asset types"""


class AcatsAssetPosition(BaseModel):
    r"""The position or amount of the asset"""

    quantity: OptionalNullable[AcatsAssetQuantity] = UNSET
    r"""The quantity of the asset, or the amount if the asset is cash; negative quantity denotes short position Fractional amounts only supported for certain asset types"""

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

        serialized = handler(self)

        m = {}

        for n, f in 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 AcatsAssetType(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The asset identifier type"""

    IDENTIFIER_TYPE_UNSPECIFIED = "IDENTIFIER_TYPE_UNSPECIFIED"
    CURRENCY_CODE = "CURRENCY_CODE"
    CUSIP = "CUSIP"
    SYMBOL = "SYMBOL"
    ISIN = "ISIN"


class AcatsAssetTypedDict(TypedDict):
    r"""The asset being transferred If cash, the asset_id is the currency code (e.g. USD) and the position is the amount"""

    asset_category: NotRequired[AssetCategory]
    r"""The NSCC asset category"""
    asset_id: NotRequired[str]
    r"""The asset identifier"""
    identifier: NotRequired[str]
    r"""The asset identifier"""
    position: NotRequired[Nullable[AcatsAssetPositionTypedDict]]
    r"""The position or amount of the asset"""
    type: NotRequired[AcatsAssetType]
    r"""The asset identifier type"""


class AcatsAsset(BaseModel):
    r"""The asset being transferred If cash, the asset_id is the currency code (e.g. USD) and the position is the amount"""

    asset_category: Annotated[
        Optional[AssetCategory], PlainValidator(validate_open_enum(False))
    ] = None
    r"""The NSCC asset category"""

    asset_id: Optional[str] = None
    r"""The asset identifier"""

    identifier: Optional[str] = None
    r"""The asset identifier"""

    position: OptionalNullable[AcatsAssetPosition] = UNSET
    r"""The position or amount of the asset"""

    type: Annotated[
        Optional[AcatsAssetType], PlainValidator(validate_open_enum(False))
    ] = None
    r"""The asset identifier type"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "asset_category",
            "asset_id",
            "identifier",
            "position",
            "type",
        ]
        nullable_fields = ["position"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in 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
