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

from __future__ import annotations
import dataclasses
import dateutil.parser
from .address import Address
from .customsdeclaration import CustomsDeclaration
from .parcel import Parcel
from .rate import Rate
from .responsemessage import ResponseMessage
from .shipmentextra import ShipmentExtra
from dataclasses_json import Undefined, dataclass_json
from datetime import datetime
from enum import Enum
from shippo import utils
from typing import List, Optional


class ShipmentStatus(str, Enum):
    r"""`Waiting` shipments have been successfully submitted but not yet been processed.
    `Queued` shipments are currently being processed. 
    `Success` shipments have been processed successfully, meaning that rate generation has concluded. 
    `Error` does not occur currently and is reserved for future use.
    """
    ERROR = 'ERROR'
    QUEUED = 'QUEUED'
    SUCCESS = 'SUCCESS'
    WAITING = 'WAITING'


@dataclass_json(undefined=Undefined.EXCLUDE)
@dataclasses.dataclass
class Shipment:
    r"""Shipment represents the parcel as retrieved from the database"""
    metadata: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('metadata') }})
    r"""A string of up to 100 characters that can be filled with any additional information you want to attach to the object."""
    address_from: Address = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('address_from') }})
    r"""<a href=\\"#tag/Addresses\\">Address</a> object of the sender / seller. Will be returned expanded by default."""
    address_to: Address = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('address_to') }})
    r"""<a href=\\"#tag/Addresses\\">Address</a> object of the recipient / buyer. Will be returned expanded by default."""
    carrier_accounts: List[str] = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('carrier_accounts') }})
    r"""An array of object_ids of the carrier account objects to be used for getting shipping rates for this shipment.
    If no carrier account object_ids are set in this field, Shippo will attempt to generate rates using all the 
    carrier accounts that have the `active` field set.
    """
    messages: List[ResponseMessage] = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('messages') }})
    object_created: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('object_created'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse }})
    r"""Date and time of Shipment creation."""
    object_id: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('object_id') }})
    r"""Unique identifier of the given Shipment object."""
    object_owner: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('object_owner') }})
    r"""Username of the user who created the Shipment object."""
    object_updated: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('object_updated'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse }})
    r"""Date and time of last Shipment update."""
    parcels: List[Parcel] = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('parcels') }})
    r"""List of Parcel objects to be shipped."""
    rates: List[Rate] = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('rates') }})
    r"""An array with all available rates. If <code>async</code> has been set to <code>false</code> in the request,
    this will be populated with all available rates in the response. Otherwise rates will be created
    asynchronously and this array will initially be empty.
    """
    status: ShipmentStatus = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('status') }})
    r"""`Waiting` shipments have been successfully submitted but not yet been processed.
    `Queued` shipments are currently being processed. 
    `Success` shipments have been processed successfully, meaning that rate generation has concluded. 
    `Error` does not occur currently and is reserved for future use.
    """
    extra: Optional[ShipmentExtra] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('extra'), 'exclude': lambda f: f is None }})
    r"""An object holding optional extra services to be requested."""
    shipment_date: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('shipment_date'), 'exclude': lambda f: f is None }})
    r"""Date the shipment will be tendered to the carrier. Must be in the format `2014-01-18T00:35:03.463Z`.
    Defaults to current date and time if no value is provided. Please note that some carriers require this value to
    be in the future, on a working day, or similar.
    """
    address_return: Optional[Address] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('address_return'), 'exclude': lambda f: f is None }})
    r"""ID of the Address object where the shipment will be sent back to if it is not delivered
    (Only available for UPS, USPS, and Fedex shipments). <br/> 
    If this field is not set, your shipments will be returned to the address_from.
    """
    customs_declaration: Optional[CustomsDeclaration] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('customs_declaration'), 'exclude': lambda f: f is None }})
    test: Optional[bool] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('test'), 'exclude': lambda f: f is None }})
    r"""Indicates whether the object has been created in test mode."""
    

