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

from __future__ import annotations
from .decimalcreate import DecimalCreate, DecimalCreateTypedDict
from .feecreate import FeeCreate, FeeCreateTypedDict
from .letterofintentcreate import LetterOfIntentCreate, LetterOfIntentCreateTypedDict
from .rightsofaccumulationcreate import (
    RightsOfAccumulationCreate,
    RightsOfAccumulationCreateTypedDict,
)
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 datetime import datetime
from enum import Enum
from pydantic import model_serializer
from pydantic.functional_validators import PlainValidator
from typing import List, Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class BasketOrderCreateAssetType(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The type of the asset in this order"""

    ASSET_TYPE_UNSPECIFIED = "ASSET_TYPE_UNSPECIFIED"
    EQUITY = "EQUITY"
    MUTUAL_FUND = "MUTUAL_FUND"


class BasketOrderCreateIdentifierType(str, Enum):
    r"""The identifier type of the asset being ordered. For Equities: only SYMBOL is supported For Mutual Funds: only SYMBOL and CUSIP are supported"""

    SYMBOL = "SYMBOL"
    CUSIP = "CUSIP"
    ISIN = "ISIN"


class BasketOrderCreateOrderType(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The execution type of this order."""

    ORDER_TYPE_UNSPECIFIED = "ORDER_TYPE_UNSPECIFIED"
    MARKET = "MARKET"


class BasketOrderCreateSide(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The side of this order."""

    SIDE_UNSPECIFIED = "SIDE_UNSPECIFIED"
    BUY = "BUY"
    SELL = "SELL"


class BasketOrderCreateTimeInForce(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""Must be the value \"DAY\". Regulatory requirements dictate that the system capture the intended time_in_force, which is why this a mandatory field."""

    TIME_IN_FORCE_UNSPECIFIED = "TIME_IN_FORCE_UNSPECIFIED"
    DAY = "DAY"


class BasketOrderCreateTypedDict(TypedDict):
    r"""The message describing an order that has been added to a basket"""

    account_id: str
    r"""The identifier of the account transacting this order"""
    asset_type: BasketOrderCreateAssetType
    r"""The type of the asset in this order"""
    client_order_id: str
    r"""User-supplied unique order ID. Cannot be more than 40 characters long."""
    identifier: str
    r"""Identifier of the asset (of the type specified in `identifier_type`)."""
    identifier_type: BasketOrderCreateIdentifierType
    r"""The identifier type of the asset being ordered. For Equities: only SYMBOL is supported For Mutual Funds: only SYMBOL and CUSIP are supported"""
    order_type: BasketOrderCreateOrderType
    r"""The execution type of this order."""
    side: BasketOrderCreateSide
    r"""The side of this order."""
    time_in_force: BasketOrderCreateTimeInForce
    r"""Must be the value \"DAY\". Regulatory requirements dictate that the system capture the intended time_in_force, which is why this a mandatory field."""
    client_order_received_time: NotRequired[Nullable[datetime]]
    r"""Time the order request was received by the client"""
    currency_code: NotRequired[str]
    r"""Defaults to \"USD\". Only \"USD\" is supported. Full list of currency codes is defined at: https://en.wikipedia.org/wiki/ISO_4217"""
    fees: NotRequired[List[FeeCreateTypedDict]]
    r"""Fees that will be applied to this order."""
    letter_of_intent: NotRequired[LetterOfIntentCreateTypedDict]
    r"""Letter of Intent (LOI). An LOI allows investors to receive sales charge discounts based on a commitment to buy a specified monetary amount of shares over a period of time, usually 13 months."""
    notional_value: NotRequired[DecimalCreateTypedDict]
    r"""A representation of a decimal value, such as 2.5. Clients may convert values into language-native decimal formats, such as Java's [BigDecimal][] or Python's [decimal.Decimal][].

    [BigDecimal]:
    https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/math/BigDecimal.html
    [decimal.Decimal]: https://docs.python.org/3/library/decimal.html
    """
    quantity: NotRequired[DecimalCreateTypedDict]
    r"""A representation of a decimal value, such as 2.5. Clients may convert values into language-native decimal formats, such as Java's [BigDecimal][] or Python's [decimal.Decimal][].

    [BigDecimal]:
    https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/math/BigDecimal.html
    [decimal.Decimal]: https://docs.python.org/3/library/decimal.html
    """
    rights_of_accumulation: NotRequired[RightsOfAccumulationCreateTypedDict]
    r"""Rights of Accumulation (ROA). An ROA allows an investor to aggregate their own fund shares with the holdings of certain related parties toward achieving the investment thresholds at which sales charge discounts become available."""


class BasketOrderCreate(BaseModel):
    r"""The message describing an order that has been added to a basket"""

    account_id: str
    r"""The identifier of the account transacting this order"""

    asset_type: Annotated[
        BasketOrderCreateAssetType, PlainValidator(validate_open_enum(False))
    ]
    r"""The type of the asset in this order"""

    client_order_id: str
    r"""User-supplied unique order ID. Cannot be more than 40 characters long."""

    identifier: str
    r"""Identifier of the asset (of the type specified in `identifier_type`)."""

    identifier_type: BasketOrderCreateIdentifierType
    r"""The identifier type of the asset being ordered. For Equities: only SYMBOL is supported For Mutual Funds: only SYMBOL and CUSIP are supported"""

    order_type: Annotated[
        BasketOrderCreateOrderType, PlainValidator(validate_open_enum(False))
    ]
    r"""The execution type of this order."""

    side: Annotated[BasketOrderCreateSide, PlainValidator(validate_open_enum(False))]
    r"""The side of this order."""

    time_in_force: Annotated[
        BasketOrderCreateTimeInForce, PlainValidator(validate_open_enum(False))
    ]
    r"""Must be the value \"DAY\". Regulatory requirements dictate that the system capture the intended time_in_force, which is why this a mandatory field."""

    client_order_received_time: OptionalNullable[datetime] = UNSET
    r"""Time the order request was received by the client"""

    currency_code: Optional[str] = None
    r"""Defaults to \"USD\". Only \"USD\" is supported. Full list of currency codes is defined at: https://en.wikipedia.org/wiki/ISO_4217"""

    fees: Optional[List[FeeCreate]] = None
    r"""Fees that will be applied to this order."""

    letter_of_intent: Optional[LetterOfIntentCreate] = None
    r"""Letter of Intent (LOI). An LOI allows investors to receive sales charge discounts based on a commitment to buy a specified monetary amount of shares over a period of time, usually 13 months."""

    notional_value: Optional[DecimalCreate] = None
    r"""A representation of a decimal value, such as 2.5. Clients may convert values into language-native decimal formats, such as Java's [BigDecimal][] or Python's [decimal.Decimal][].

    [BigDecimal]:
    https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/math/BigDecimal.html
    [decimal.Decimal]: https://docs.python.org/3/library/decimal.html
    """

    quantity: Optional[DecimalCreate] = None
    r"""A representation of a decimal value, such as 2.5. Clients may convert values into language-native decimal formats, such as Java's [BigDecimal][] or Python's [decimal.Decimal][].

    [BigDecimal]:
    https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/math/BigDecimal.html
    [decimal.Decimal]: https://docs.python.org/3/library/decimal.html
    """

    rights_of_accumulation: Optional[RightsOfAccumulationCreate] = None
    r"""Rights of Accumulation (ROA). An ROA allows an investor to aggregate their own fund shares with the holdings of certain related parties toward achieving the investment thresholds at which sales charge discounts become available."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "client_order_received_time",
            "currency_code",
            "fees",
            "letter_of_intent",
            "notional_value",
            "quantity",
            "rights_of_accumulation",
        ]
        nullable_fields = ["client_order_received_time"]
        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
