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

from __future__ import annotations
from .acatsasset import AcatsAsset, AcatsAssetTypedDict
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 ExternalAccountTypedDict(TypedDict):
    r"""The external account information"""

    account_number: NotRequired[str]
    r"""The account identifier The account number for external communications"""
    account_title: NotRequired[str]
    r"""Account owner title"""
    participant_number: NotRequired[str]
    r"""The NSCC brokerage / clearing house identifier"""


class ExternalAccount(BaseModel):
    r"""The external account information"""

    account_number: Optional[str] = None
    r"""The account identifier The account number for external communications"""

    account_title: Optional[str] = None
    r"""Account owner title"""

    participant_number: Optional[str] = None
    r"""The NSCC brokerage / clearing house identifier"""


class DelivererTypedDict(TypedDict):
    r"""The delivering party information"""

    apex_account_id: NotRequired[str]
    r"""The internal apex account id"""
    external_account: NotRequired[Nullable[ExternalAccountTypedDict]]
    r"""The external account information"""


class Deliverer(BaseModel):
    r"""The delivering party information"""

    apex_account_id: Optional[str] = None
    r"""The internal apex account id"""

    external_account: OptionalNullable[ExternalAccount] = UNSET
    r"""The external account information"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["apex_account_id", "external_account"]
        nullable_fields = ["external_account"]
        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 Direction(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The direction of the transfer"""

    DIRECTION_UNSPECIFIED = "DIRECTION_UNSPECIFIED"
    OUTGOING = "OUTGOING"
    INCOMING = "INCOMING"


class NsccStatus(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The NSCC transfer status"""

    NSCC_STATUS_UNSPECIFIED = "NSCC_STATUS_UNSPECIFIED"
    REQUEST = "REQUEST"
    REQUEST_ADJUST = "REQUEST_ADJUST"
    REQUEST_ADJUST_PAST = "REQUEST_ADJUST_PAST"
    REQUEST_PAST = "REQUEST_PAST"
    REQUEST_REJECT = "REQUEST_REJECT"
    REVIEW = "REVIEW"
    REVIEW_ADJUST_DELIVERER = "REVIEW_ADJUST_DELIVERER"
    REVIEW_ERROR = "REVIEW_ERROR"
    REVIEW_ACCELERATE = "REVIEW_ACCELERATE"
    REVIEW_ADJUST_RECEIVER_ACCELERATE = "REVIEW_ADJUST_RECEIVER_ACCELERATE"
    SETTLE_PREP = "SETTLE_PREP"
    SETTLE_CLOSE = "SETTLE_CLOSE"
    CLOSE_PURGE = "CLOSE_PURGE"
    PARTIAL_REQUEST = "PARTIAL_REQUEST"
    MEMO_PURGE_PARTIAL_TRANSFER_REQUEST_RECEIVER = (
        "MEMO_PURGE_PARTIAL_TRANSFER_REQUEST_RECEIVER"
    )
    REJECT = "REJECT"
    SYSTEM_PURGE = "SYSTEM_PURGE"


class AcatsTransferExternalAccountTypedDict(TypedDict):
    r"""The external account information"""

    account_number: NotRequired[str]
    r"""The account identifier The account number for external communications"""
    account_title: NotRequired[str]
    r"""Account owner title"""
    participant_number: NotRequired[str]
    r"""The NSCC brokerage / clearing house identifier"""


class AcatsTransferExternalAccount(BaseModel):
    r"""The external account information"""

    account_number: Optional[str] = None
    r"""The account identifier The account number for external communications"""

    account_title: Optional[str] = None
    r"""Account owner title"""

    participant_number: Optional[str] = None
    r"""The NSCC brokerage / clearing house identifier"""


class ReceiverTypedDict(TypedDict):
    r"""The receiving party information"""

    apex_account_id: NotRequired[str]
    r"""The internal apex account id"""
    external_account: NotRequired[Nullable[AcatsTransferExternalAccountTypedDict]]
    r"""The external account information"""


class Receiver(BaseModel):
    r"""The receiving party information"""

    apex_account_id: Optional[str] = None
    r"""The internal apex account id"""

    external_account: OptionalNullable[AcatsTransferExternalAccount] = UNSET
    r"""The external account information"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["apex_account_id", "external_account"]
        nullable_fields = ["external_account"]
        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 RejectCode(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The reject code"""

    REJECT_CODE_UNSPECIFIED = "REJECT_CODE_UNSPECIFIED"
    REJECT_CODE_SSN_TAX_ID_MISMATCH = "REJECT_CODE_SSN_TAX_ID_MISMATCH"
    REJECT_CODE_ACCOUNT_TITLE_MISMATCH = "REJECT_CODE_ACCOUNT_TITLE_MISMATCH"
    REJECT_CODE_DOCUMENTATION_NEEDED = "REJECT_CODE_DOCUMENTATION_NEEDED"
    REJECT_CODE_ACCOUNT_FLAT = "REJECT_CODE_ACCOUNT_FLAT"
    REJECT_CODE_INVALID_ACCOUNT_NUMBER = "REJECT_CODE_INVALID_ACCOUNT_NUMBER"
    REJECT_CODE_DUPLICATE = "REJECT_CODE_DUPLICATE"
    REJECT_CODE_ACCOUNT_IN_DISTRIBUTION_OR_TRANSFER = (
        "REJECT_CODE_ACCOUNT_IN_DISTRIBUTION_OR_TRANSFER"
    )
    REJECT_CODE_CLIENT_RESCINDED = "REJECT_CODE_CLIENT_RESCINDED"
    REJECT_CODE_MISSING_AUTHORIZATION_SIGNATURE = (
        "REJECT_CODE_MISSING_AUTHORIZATION_SIGNATURE"
    )
    REJECT_CODE_ACCOUNT_VIOLATES_CREDIT_POLICY_OF_RECEIVING_FIRM = (
        "REJECT_CODE_ACCOUNT_VIOLATES_CREDIT_POLICY_OF_RECEIVING_FIRM"
    )
    REJECT_CODE_UNRECOGNIZED_FOR_RESIDUAL_CREDIT_BALANCE = (
        "REJECT_CODE_UNRECOGNIZED_FOR_RESIDUAL_CREDIT_BALANCE"
    )
    REJECT_CODE_PARTIAL_TRANSFER_DELIVERER = "REJECT_CODE_PARTIAL_TRANSFER_DELIVERER"
    REJECT_CODE_FAIL_REVERSAL = "REJECT_CODE_FAIL_REVERSAL"
    REJECT_CODE_RECLAIM = "REJECT_CODE_RECLAIM"
    REJECT_CODE_MUTUAL_FUND_CLEANUP = "REJECT_CODE_MUTUAL_FUND_CLEANUP"


class AcatsTransferState(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The transfer state"""

    STATE_UNSPECIFIED = "STATE_UNSPECIFIED"
    RECEIVED = "RECEIVED"
    SUBMITTED = "SUBMITTED"
    REJECTED = "REJECTED"
    PENDING_CONTRA_RESPONSE = "PENDING_CONTRA_RESPONSE"
    ERROR = "ERROR"
    ACCEPTED = "ACCEPTED"
    PENDING_REVIEW = "PENDING_REVIEW"
    PENDING_REJECTION = "PENDING_REJECTION"
    PENDING_SETTLEMENT = "PENDING_SETTLEMENT"
    PENDING_BOOKKEEPING = "PENDING_BOOKKEEPING"
    COMPLETED = "COMPLETED"
    PURGED = "PURGED"


class TransferType(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The type of transfer"""

    TRANSFER_TYPE_UNSPECIFIED = "TRANSFER_TYPE_UNSPECIFIED"
    FAIL_REVERSAL_BROKER_TO_BROKER_ONLY = "FAIL_REVERSAL_BROKER_TO_BROKER_ONLY"
    FULL_TRANSFER = "FULL_TRANSFER"
    MUTUAL_FUND_CLEANUP = "MUTUAL_FUND_CLEANUP"
    PARTIAL_TRANSFER_DELIVERER = "PARTIAL_TRANSFER_DELIVERER"
    PARTIAL_TRANSFER_RECEIVER = "PARTIAL_TRANSFER_RECEIVER"
    POSITION_TRANSFER_FUND_FIRM_TO_MUTUAL_FUND_COMPANY_ONLY = (
        "POSITION_TRANSFER_FUND_FIRM_TO_MUTUAL_FUND_COMPANY_ONLY"
    )
    RECLAIM = "RECLAIM"
    RESIDUAL_CREDIT = "RESIDUAL_CREDIT"


class AcatsTransferTypedDict(TypedDict):
    r"""An account transfer which contains the receiving and delivering party information, assets being transferred, NSCC status information, etc."""

    acat_control_number: NotRequired[str]
    r"""The NSCC transfer identifier"""
    assets: NotRequired[List[AcatsAssetTypedDict]]
    r"""The assets being transferred (Cash, Equities, etc.)"""
    comment: NotRequired[str]
    r"""User supplied comment"""
    create_time: NotRequired[Nullable[datetime]]
    r"""The transfer creation timestamp"""
    deliverer: NotRequired[Nullable[DelivererTypedDict]]
    r"""The delivering party information"""
    direction: NotRequired[Direction]
    r"""The direction of the transfer"""
    name: NotRequired[str]
    r"""The service generated name of the transfer. Format: correspondents/{correspondent_id}/accounts/{account_id}/transfers/{transfer_id}"""
    nscc_status: NotRequired[NsccStatus]
    r"""The NSCC transfer status"""
    original_control_number: NotRequired[str]
    r"""An associated NSCC transfer identifier, if applicable"""
    receiver: NotRequired[Nullable[ReceiverTypedDict]]
    r"""The receiving party information"""
    reject_code: NotRequired[RejectCode]
    r"""The reject code"""
    state: NotRequired[AcatsTransferState]
    r"""The transfer state"""
    transfer_type: NotRequired[TransferType]
    r"""The type of transfer"""


class AcatsTransfer(BaseModel):
    r"""An account transfer which contains the receiving and delivering party information, assets being transferred, NSCC status information, etc."""

    acat_control_number: Optional[str] = None
    r"""The NSCC transfer identifier"""

    assets: Optional[List[AcatsAsset]] = None
    r"""The assets being transferred (Cash, Equities, etc.)"""

    comment: Optional[str] = None
    r"""User supplied comment"""

    create_time: OptionalNullable[datetime] = UNSET
    r"""The transfer creation timestamp"""

    deliverer: OptionalNullable[Deliverer] = UNSET
    r"""The delivering party information"""

    direction: Annotated[
        Optional[Direction], PlainValidator(validate_open_enum(False))
    ] = None
    r"""The direction of the transfer"""

    name: Optional[str] = None
    r"""The service generated name of the transfer. Format: correspondents/{correspondent_id}/accounts/{account_id}/transfers/{transfer_id}"""

    nscc_status: Annotated[
        Optional[NsccStatus], PlainValidator(validate_open_enum(False))
    ] = None
    r"""The NSCC transfer status"""

    original_control_number: Optional[str] = None
    r"""An associated NSCC transfer identifier, if applicable"""

    receiver: OptionalNullable[Receiver] = UNSET
    r"""The receiving party information"""

    reject_code: Annotated[
        Optional[RejectCode], PlainValidator(validate_open_enum(False))
    ] = None
    r"""The reject code"""

    state: Annotated[
        Optional[AcatsTransferState], PlainValidator(validate_open_enum(False))
    ] = None
    r"""The transfer state"""

    transfer_type: Annotated[
        Optional[TransferType], PlainValidator(validate_open_enum(False))
    ] = None
    r"""The type of transfer"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "acat_control_number",
            "assets",
            "comment",
            "create_time",
            "deliverer",
            "direction",
            "name",
            "nscc_status",
            "original_control_number",
            "receiver",
            "reject_code",
            "state",
            "transfer_type",
        ]
        nullable_fields = ["create_time", "deliverer", "receiver"]
        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
