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

from __future__ import annotations
from .documents import Documents, DocumentsTypedDict
from .recipients import Recipients, RecipientsTypedDict
from datetime import date
from postivo_client.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
)
from pydantic import model_serializer
from typing import List, Optional, Union
from typing_extensions import NotRequired, TypeAliasType, TypedDict


ShipmentRecipientsTypedDict = TypeAliasType(
    "ShipmentRecipientsTypedDict", Union[RecipientsTypedDict, List[RecipientsTypedDict]]
)
r"""Recipient data for a single shipment. For one recipient, provide a `RecipientInline`, `RecipientFromAddressBook`, or `RecipientFromAddressBookByExternalId` object. For multiple recipients, provide an array of these objects (1–50)."""


ShipmentRecipients = TypeAliasType(
    "ShipmentRecipients", Union[Recipients, List[Recipients]]
)
r"""Recipient data for a single shipment. For one recipient, provide a `RecipientInline`, `RecipientFromAddressBook`, or `RecipientFromAddressBookByExternalId` object. For multiple recipients, provide an array of these objects (1–50)."""


ShipmentDocumentsTypedDict = TypeAliasType(
    "ShipmentDocumentsTypedDict", Union[DocumentsTypedDict, List[DocumentsTypedDict]]
)
r"""Document payload to print and enclose into shipment. For a single document, provide `DocumentPdf`, `DocumentLibrary`, or `DocumentMock` (for checking the price only). For multiple documents, provide an array of `DocumentPdf`, `DocumentLibrary`, or `DocumentMock` objects (1–20)."""


ShipmentDocuments = TypeAliasType(
    "ShipmentDocuments", Union[Documents, List[Documents]]
)
r"""Document payload to print and enclose into shipment. For a single document, provide `DocumentPdf`, `DocumentLibrary`, or `DocumentMock` (for checking the price only). For multiple documents, provide an array of `DocumentPdf`, `DocumentLibrary`, or `DocumentMock` objects (1–20)."""


class InlineConfigTypedDict(TypedDict):
    r"""Shipment configuration parameters. Overrides settings loaded from `predefined_config_id`."""

    carrier_id: int
    r"""Preferred carrier identifier."""
    service_id: int
    r"""Preferred service identifier (shipment type)."""
    paper_id: NotRequired[int]
    r"""Preferred paper type identifier."""
    color_print: NotRequired[bool]
    r"""Print documents in color (`true`) or grayscale (`false`)."""
    duplex_print: NotRequired[bool]
    r"""Print documents duplex (`true`) or single-sided (`false`)."""
    envelope_id: NotRequired[int]
    r"""Preferred envelope size/template identifier defined in the user account."""
    envelope_color_print: NotRequired[bool]
    r"""Print the envelope in color (`true`) or grayscale (`false`)."""


class InlineConfig(BaseModel):
    r"""Shipment configuration parameters. Overrides settings loaded from `predefined_config_id`."""

    carrier_id: int
    r"""Preferred carrier identifier."""

    service_id: int
    r"""Preferred service identifier (shipment type)."""

    paper_id: Optional[int] = None
    r"""Preferred paper type identifier."""

    color_print: Optional[bool] = None
    r"""Print documents in color (`true`) or grayscale (`false`)."""

    duplex_print: Optional[bool] = None
    r"""Print documents duplex (`true`) or single-sided (`false`)."""

    envelope_id: Optional[int] = None
    r"""Preferred envelope size/template identifier defined in the user account."""

    envelope_color_print: Optional[bool] = None
    r"""Print the envelope in color (`true`) or grayscale (`false`)."""


InlineConfigUnionTypedDict = InlineConfigTypedDict


InlineConfigUnion = InlineConfig


class CallbackTypedDict(TypedDict):
    r"""Per-shipment callback configuration. When set, overrides the global callback defined in the user account."""

    url: str
    r"""Callback target URL."""
    user_token: NotRequired[Nullable[str]]
    r"""Bearer token to include in callback requests for authentication."""


class Callback(BaseModel):
    r"""Per-shipment callback configuration. When set, overrides the global callback defined in the user account."""

    url: str
    r"""Callback target URL."""

    user_token: OptionalNullable[str] = None
    r"""Bearer token to include in callback requests for authentication."""

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

        serialized = handler(self)

        m = {}

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


CallbackUnionTypedDict = CallbackTypedDict


CallbackUnion = Callback


class MiscInfoTypedDict(TypedDict):
    r"""Additional shipment metadata. At least one of `order_name` or `mpk` must be provided."""

    mpk: NotRequired[Nullable[str]]
    r"""MPK (“miejsce powstania kosztu”) — billing cost-center identifier to be included on invoices."""
    order_name: NotRequired[Nullable[str]]
    r"""Order name assigned to this shipment; displayed in reports and related views."""


class MiscInfo(BaseModel):
    r"""Additional shipment metadata. At least one of `order_name` or `mpk` must be provided."""

    mpk: OptionalNullable[str] = None
    r"""MPK (“miejsce powstania kosztu”) — billing cost-center identifier to be included on invoices."""

    order_name: OptionalNullable[str] = None
    r"""Order name assigned to this shipment; displayed in reports and related views."""

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

        serialized = handler(self)

        m = {}

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


MiscInfoUnionTypedDict = MiscInfoTypedDict


MiscInfoUnion = MiscInfo


class ShipmentOptionsTypedDict(TypedDict):
    r"""Additional shipment settings."""

    predefined_config_id: NotRequired[Nullable[int]]
    r"""ID of the shipment configuration profile stored in the user account."""
    inline_config: NotRequired[Nullable[InlineConfigUnionTypedDict]]
    sender_id: NotRequired[Nullable[int]]
    r"""ID of the sender stored in the user account."""
    dispatch_date: NotRequired[date]
    r"""Scheduled dispatch date (ISO 8601)."""
    callback: NotRequired[Nullable[CallbackUnionTypedDict]]
    misc_info: NotRequired[Nullable[MiscInfoUnionTypedDict]]
    rotate_documents: NotRequired[bool]
    r"""If true, rotate all documents 180° before printing (barcodes will be printed on opposite margins)."""


class ShipmentOptions(BaseModel):
    r"""Additional shipment settings."""

    predefined_config_id: OptionalNullable[int] = UNSET
    r"""ID of the shipment configuration profile stored in the user account."""

    inline_config: OptionalNullable[InlineConfigUnion] = UNSET

    sender_id: OptionalNullable[int] = UNSET
    r"""ID of the sender stored in the user account."""

    dispatch_date: Optional[date] = None
    r"""Scheduled dispatch date (ISO 8601)."""

    callback: OptionalNullable[CallbackUnion] = UNSET

    misc_info: OptionalNullable[MiscInfoUnion] = UNSET

    rotate_documents: Optional[bool] = None
    r"""If true, rotate all documents 180° before printing (barcodes will be printed on opposite margins)."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "predefined_config_id",
            "inline_config",
            "sender_id",
            "dispatch_date",
            "callback",
            "misc_info",
            "rotate_documents",
        ]
        nullable_fields = [
            "predefined_config_id",
            "inline_config",
            "sender_id",
            "callback",
            "misc_info",
        ]
        null_default_fields = []

        serialized = handler(self)

        m = {}

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


OptionsTypedDict = ShipmentOptionsTypedDict


Options = ShipmentOptions


class ShipmentTypedDict(TypedDict):
    r"""Properties of a new shipment."""

    recipients: ShipmentRecipientsTypedDict
    r"""Recipient data for a single shipment. For one recipient, provide a `RecipientInline`, `RecipientFromAddressBook`, or `RecipientFromAddressBookByExternalId` object. For multiple recipients, provide an array of these objects (1–50)."""
    documents: ShipmentDocumentsTypedDict
    r"""Document payload to print and enclose into shipment. For a single document, provide `DocumentPdf`, `DocumentLibrary`, or `DocumentMock` (for checking the price only). For multiple documents, provide an array of `DocumentPdf`, `DocumentLibrary`, or `DocumentMock` objects (1–20)."""
    options: NotRequired[Nullable[OptionsTypedDict]]


class Shipment(BaseModel):
    r"""Properties of a new shipment."""

    recipients: ShipmentRecipients
    r"""Recipient data for a single shipment. For one recipient, provide a `RecipientInline`, `RecipientFromAddressBook`, or `RecipientFromAddressBookByExternalId` object. For multiple recipients, provide an array of these objects (1–50)."""

    documents: ShipmentDocuments
    r"""Document payload to print and enclose into shipment. For a single document, provide `DocumentPdf`, `DocumentLibrary`, or `DocumentMock` (for checking the price only). For multiple documents, provide an array of `DocumentPdf`, `DocumentLibrary`, or `DocumentMock` objects (1–20)."""

    options: OptionalNullable[Options] = UNSET

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

        serialized = handler(self)

        m = {}

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