# coding: utf-8

"""
Waybiller External API - with fixes

The **Waybiller External API** is a feature that allows companies to access **Waybiller** data as JSON objects and create **Waybiller** instances out of their own data.  To make integration easier for the companies, the external API provides mapping support - it is possible to create company-specific mappings for object identifiers (such as destination and origin).  These mappings will be used for representing companies data from external API, and for converting the values during the creation of **Waybiller** instances (such as transport orders and waybills).  Most of the API responses contain mapped values, which may be null if the company doesn't have a mapping for this object.  Unique **Waybiller** identifiers and values can be accessed via the `raw_data` key.  The API is HTTPS and JSON based.  ### Pagination  By default, list endpoint responses are presented in pages of 30 items.  It is possible to control the page size using the `limit` parameter: `/external-api/<some-list-endpoint>/?limit=<number>`, where `<number>` is an integer between 1 and 1000.

The version of the OpenAPI document: v1
Generated by OpenAPI Generator (https://openapi-generator.tech)

Do not edit the class manually.
"""  # noqa: E501

from __future__ import annotations

import json
import pprint
import re  # noqa: F401
from datetime import datetime
from typing import Any, ClassVar, Dict, List, Optional, Set, Union

from pydantic import BaseModel, ConfigDict, Field, StrictFloat, StrictInt, StrictStr
from typing_extensions import Annotated, Self

from pywaybiller.openapi_client.models.external_api_waybill_holding_right import (
    ExternalAPIWaybillHoldingRight,
)
from pywaybiller.openapi_client.models.external_api_waybill_raw_data import (
    ExternalAPIWaybillRawData,
)
from pywaybiller.openapi_client.models.external_api_waybill_row import (
    ExternalAPIWaybillRow,
)
from pywaybiller.openapi_client.models.external_api_waybill_transport_costs import (
    ExternalAPIWaybillTransportCosts,
)
from pywaybiller.openapi_client.models.waybill_status_enum import WaybillStatusEnum


class ExternalAPIWaybillRetrieve(BaseModel):
    """
    ExternalAPIWaybillRetrieve
    """  # noqa: E501

    waybill_id: Optional[StrictStr] = Field(
        description="The external ID of the waybill. Usually `null` if waybill was created in Waybiller UI and not over Waybiller External API."
    )
    number: StrictStr
    status: WaybillStatusEnum
    status_description: Annotated[str, Field(strict=True, max_length=255)] = Field(
        description="Human readable status description (`Created`, `In progress`, `At destination`, `Confirmed` or `Cancelled`)."
    )
    rows: List[ExternalAPIWaybillRow] = Field(description="Waybill rows.")
    destination_raw_id: Optional[StrictStr] = Field(
        default=None, description="The ID of the destination."
    )
    destination_id: Optional[StrictStr] = Field(
        description="The external ID of the destination. Usually `null` if waybill was created in Waybiller UI and not over Waybiller External API."
    )
    destination_name: StrictStr = Field(description="The name of the destination.")
    destination_address: StrictStr = Field(
        description="The address of the destination."
    )
    destination_latitude: Optional[Union[StrictFloat, StrictInt]] = Field(
        default=None, description="The latitude of the destination."
    )
    destination_longitude: Optional[Union[StrictFloat, StrictInt]] = Field(
        default=None, description="The longitude of the destination."
    )
    destination_waybill_reached_destination_emails: Optional[
        List[Annotated[str, Field(strict=True, max_length=254)]]
    ] = Field(
        description="Comma separated list of e-mail addresses to whom send an e-mail when waybill reaches destination."
    )
    destination_waybill_accepted_emails: Optional[
        List[Annotated[str, Field(strict=True, max_length=254)]]
    ] = Field(
        description="Comma separated list of e-mail addresses to whom send an e-mail when waybill is accepted."
    )
    receiver_company_name: StrictStr = Field(
        description="The name of the receiving company."
    )
    receiver_company_reg_code: StrictStr = Field(
        description="The registry code of the receiving company."
    )
    origin_raw_id: Optional[StrictStr] = Field(
        default=None, description="The ID of the origin."
    )
    origin_id: Optional[StrictInt] = Field(
        default=None,
        description="The external ID of the origin. Usually `null` if waybill was created in Waybiller UI and not over Waybiller External API.",
    )
    origin_name: Optional[StrictStr] = Field(
        default=None, description="The name of the origin."
    )
    origin_address: Optional[StrictStr] = Field(
        default=None, description="The address of the origin."
    )
    origin_latitude: Optional[Union[StrictFloat, StrictInt]] = Field(
        default=None, description="The latitude of the origin."
    )
    origin_longitude: Optional[Union[StrictFloat, StrictInt]] = Field(
        default=None, description="The longitude of the origin."
    )
    origin_waybill_reached_destination_emails: Optional[
        List[Annotated[str, Field(strict=True, max_length=254)]]
    ] = Field(
        description="Comma separated list of e-mail addresses to whom send an e-mail when waybill reaches destination."
    )
    origin_waybill_accepted_emails: Optional[
        List[Annotated[str, Field(strict=True, max_length=254)]]
    ] = Field(
        description="Comma separated list of e-mail addresses to whom send an e-mail when waybill is accepted."
    )
    cadaster_number: Annotated[str, Field(strict=True, max_length=500)] = Field(
        description="Cadaster number."
    )
    dispatcher_name: StrictStr
    dispatcher_phone: StrictStr
    holding_rights: Optional[List[ExternalAPIWaybillHoldingRight]] = None
    shipper_company_name: Annotated[str, Field(strict=True, max_length=64)] = Field(
        description="The name of the shipper company."
    )
    shipper_company_reg_code: Annotated[str, Field(strict=True, max_length=16)] = Field(
        description="The registry code of the shipper company."
    )
    transportation_company_name: Annotated[str, Field(strict=True, max_length=64)] = (
        Field(description="The name of the transportation company.")
    )
    transportation_company_reg_code: Annotated[
        str, Field(strict=True, max_length=16)
    ] = Field(description="The registry code of the transportation company.")
    truck_reg_number: StrictStr = Field(
        description="The registration number of the vehicle."
    )
    trailer_reg_number: Optional[StrictStr] = Field(
        default=None, description="The registration number of the trailer."
    )
    driver_email: Optional[Annotated[str, Field(strict=True, max_length=254)]] = Field(
        default=None, description="The e-mail address of the driver user."
    )
    driver_name: Annotated[str, Field(strict=True, max_length=255)] = Field(
        description="The name of the driver."
    )
    driver_phone: Annotated[str, Field(strict=True, max_length=128)] = Field(
        description="The phone number of the driver."
    )
    driver_personal_code: Optional[
        Annotated[str, Field(strict=True, max_length=24)]
    ] = Field(default=None, description="The personal code of the driver.")
    mileage: Optional[StrictInt] = Field(
        description="The mileage can be calculated using a map or can be taken from Distance object if exist"
    )
    mileage_by_driver: Optional[StrictInt]
    confirmed_by_email: Optional[Annotated[str, Field(strict=True, max_length=255)]] = (
        Field(
            default=None,
            description="The e-mail address of the user that accepted the waybill.",
        )
    )
    confirmed_by_name: StrictStr
    confirmed_by_phone: StrictStr
    cancelled_by_email: Optional[Annotated[str, Field(strict=True, max_length=255)]] = (
        Field(
            default=None,
            description="The e-mail address of the user that cancelled the waybill.",
        )
    )
    cancelled_by_name: StrictStr
    cancelled_by_phone: StrictStr
    cancelling_reason: StrictStr
    dispatcher_timestamp: datetime = Field(description="Waybill creation timestamp")
    driver_timestamp: Optional[datetime] = Field(
        description="Timestamp when driver started driving"
    )
    destination_timestamp: Optional[datetime] = Field(
        description="Time when waybill reached destination."
    )
    confirmed_timestamp: Optional[datetime] = Field(
        description="Time of confirmation in the destination"
    )
    cancelled_timestamp: Optional[datetime] = Field(
        description="Time of waybill cancelling"
    )
    pdf_url: StrictStr
    navision_bin_code: Optional[StrictStr] = Field(description="Bin code.")
    evr_waybill_number: Optional[StrictStr] = Field(description="EVR waybill number.")
    project: Optional[StrictStr] = Field(description="Project code in your system.")
    transport_costs: Optional[ExternalAPIWaybillTransportCosts] = Field(
        description="Information about transport costs"
    )
    raw_data: ExternalAPIWaybillRawData = Field(
        description="The IDs of the Waybiller internal objects"
    )
    __properties: ClassVar[List[str]] = [
        "waybill_id",
        "number",
        "status",
        "status_description",
        "rows",
        "destination_raw_id",
        "destination_id",
        "destination_name",
        "destination_address",
        "destination_latitude",
        "destination_longitude",
        "destination_waybill_reached_destination_emails",
        "destination_waybill_accepted_emails",
        "receiver_company_name",
        "receiver_company_reg_code",
        "origin_raw_id",
        "origin_id",
        "origin_name",
        "origin_address",
        "origin_latitude",
        "origin_longitude",
        "origin_waybill_reached_destination_emails",
        "origin_waybill_accepted_emails",
        "cadaster_number",
        "dispatcher_name",
        "dispatcher_phone",
        "holding_rights",
        "shipper_company_name",
        "shipper_company_reg_code",
        "transportation_company_name",
        "transportation_company_reg_code",
        "truck_reg_number",
        "trailer_reg_number",
        "driver_email",
        "driver_name",
        "driver_phone",
        "driver_personal_code",
        "mileage",
        "mileage_by_driver",
        "confirmed_by_email",
        "confirmed_by_name",
        "confirmed_by_phone",
        "cancelled_by_email",
        "cancelled_by_name",
        "cancelled_by_phone",
        "cancelling_reason",
        "dispatcher_timestamp",
        "driver_timestamp",
        "destination_timestamp",
        "confirmed_timestamp",
        "cancelled_timestamp",
        "pdf_url",
        "navision_bin_code",
        "evr_waybill_number",
        "project",
        "transport_costs",
        "raw_data",
    ]

    model_config = ConfigDict(
        populate_by_name=True,
        validate_assignment=True,
        protected_namespaces=(),
    )

    def to_str(self) -> str:
        """Returns the string representation of the model using alias"""
        return pprint.pformat(self.model_dump(by_alias=True))

    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias"""
        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
        return json.dumps(self.to_dict())

    @classmethod
    def from_json(cls, json_str: str) -> Optional[Self]:
        """Create an instance of ExternalAPIWaybillRetrieve from a JSON string"""
        return cls.from_dict(json.loads(json_str))

    def to_dict(self) -> Dict[str, Any]:
        """Return the dictionary representation of the model using alias.

        This has the following differences from calling pydantic's
        `self.model_dump(by_alias=True)`:

        * `None` is only added to the output dict for nullable fields that
          were set at model initialization. Other fields with value `None`
          are ignored.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        """
        excluded_fields: Set[str] = set(
            [
                "waybill_id",
                "number",
                "status",
                "status_description",
                "destination_id",
                "destination_name",
                "destination_address",
                "destination_waybill_reached_destination_emails",
                "destination_waybill_accepted_emails",
                "receiver_company_name",
                "receiver_company_reg_code",
                "origin_waybill_reached_destination_emails",
                "origin_waybill_accepted_emails",
                "cadaster_number",
                "dispatcher_name",
                "dispatcher_phone",
                "shipper_company_name",
                "shipper_company_reg_code",
                "transportation_company_name",
                "transportation_company_reg_code",
                "driver_name",
                "driver_phone",
                "mileage",
                "mileage_by_driver",
                "confirmed_by_name",
                "confirmed_by_phone",
                "cancelled_by_name",
                "cancelled_by_phone",
                "cancelling_reason",
                "dispatcher_timestamp",
                "driver_timestamp",
                "destination_timestamp",
                "confirmed_timestamp",
                "cancelled_timestamp",
                "pdf_url",
                "navision_bin_code",
                "evr_waybill_number",
                "project",
                "raw_data",
            ]
        )

        _dict = self.model_dump(
            by_alias=True,
            exclude=excluded_fields,
            exclude_none=True,
        )
        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
        _items = []
        if self.rows:
            for _item_rows in self.rows:
                if _item_rows:
                    _items.append(_item_rows.to_dict())
            _dict["rows"] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in holding_rights (list)
        _items = []
        if self.holding_rights:
            for _item_holding_rights in self.holding_rights:
                if _item_holding_rights:
                    _items.append(_item_holding_rights.to_dict())
            _dict["holding_rights"] = _items
        # override the default output from pydantic by calling `to_dict()` of transport_costs
        if self.transport_costs:
            _dict["transport_costs"] = self.transport_costs.to_dict()
        # override the default output from pydantic by calling `to_dict()` of raw_data
        if self.raw_data:
            _dict["raw_data"] = self.raw_data.to_dict()
        # set to None if waybill_id (nullable) is None
        # and model_fields_set contains the field
        if self.waybill_id is None and "waybill_id" in self.model_fields_set:
            _dict["waybill_id"] = None

        # set to None if destination_id (nullable) is None
        # and model_fields_set contains the field
        if self.destination_id is None and "destination_id" in self.model_fields_set:
            _dict["destination_id"] = None

        # set to None if destination_waybill_reached_destination_emails (nullable) is None
        # and model_fields_set contains the field
        if (
            self.destination_waybill_reached_destination_emails is None
            and "destination_waybill_reached_destination_emails"
            in self.model_fields_set
        ):
            _dict["destination_waybill_reached_destination_emails"] = None

        # set to None if destination_waybill_accepted_emails (nullable) is None
        # and model_fields_set contains the field
        if (
            self.destination_waybill_accepted_emails is None
            and "destination_waybill_accepted_emails" in self.model_fields_set
        ):
            _dict["destination_waybill_accepted_emails"] = None

        # set to None if origin_waybill_reached_destination_emails (nullable) is None
        # and model_fields_set contains the field
        if (
            self.origin_waybill_reached_destination_emails is None
            and "origin_waybill_reached_destination_emails" in self.model_fields_set
        ):
            _dict["origin_waybill_reached_destination_emails"] = None

        # set to None if origin_waybill_accepted_emails (nullable) is None
        # and model_fields_set contains the field
        if (
            self.origin_waybill_accepted_emails is None
            and "origin_waybill_accepted_emails" in self.model_fields_set
        ):
            _dict["origin_waybill_accepted_emails"] = None

        # set to None if mileage (nullable) is None
        # and model_fields_set contains the field
        if self.mileage is None and "mileage" in self.model_fields_set:
            _dict["mileage"] = None

        # set to None if mileage_by_driver (nullable) is None
        # and model_fields_set contains the field
        if (
            self.mileage_by_driver is None
            and "mileage_by_driver" in self.model_fields_set
        ):
            _dict["mileage_by_driver"] = None

        # set to None if confirmed_by_email (nullable) is None
        # and model_fields_set contains the field
        if (
            self.confirmed_by_email is None
            and "confirmed_by_email" in self.model_fields_set
        ):
            _dict["confirmed_by_email"] = None

        # set to None if cancelled_by_email (nullable) is None
        # and model_fields_set contains the field
        if (
            self.cancelled_by_email is None
            and "cancelled_by_email" in self.model_fields_set
        ):
            _dict["cancelled_by_email"] = None

        # set to None if driver_timestamp (nullable) is None
        # and model_fields_set contains the field
        if (
            self.driver_timestamp is None
            and "driver_timestamp" in self.model_fields_set
        ):
            _dict["driver_timestamp"] = None

        # set to None if destination_timestamp (nullable) is None
        # and model_fields_set contains the field
        if (
            self.destination_timestamp is None
            and "destination_timestamp" in self.model_fields_set
        ):
            _dict["destination_timestamp"] = None

        # set to None if confirmed_timestamp (nullable) is None
        # and model_fields_set contains the field
        if (
            self.confirmed_timestamp is None
            and "confirmed_timestamp" in self.model_fields_set
        ):
            _dict["confirmed_timestamp"] = None

        # set to None if cancelled_timestamp (nullable) is None
        # and model_fields_set contains the field
        if (
            self.cancelled_timestamp is None
            and "cancelled_timestamp" in self.model_fields_set
        ):
            _dict["cancelled_timestamp"] = None

        # set to None if navision_bin_code (nullable) is None
        # and model_fields_set contains the field
        if (
            self.navision_bin_code is None
            and "navision_bin_code" in self.model_fields_set
        ):
            _dict["navision_bin_code"] = None

        # set to None if evr_waybill_number (nullable) is None
        # and model_fields_set contains the field
        if (
            self.evr_waybill_number is None
            and "evr_waybill_number" in self.model_fields_set
        ):
            _dict["evr_waybill_number"] = None

        # set to None if project (nullable) is None
        # and model_fields_set contains the field
        if self.project is None and "project" in self.model_fields_set:
            _dict["project"] = None

        # set to None if transport_costs (nullable) is None
        # and model_fields_set contains the field
        if self.transport_costs is None and "transport_costs" in self.model_fields_set:
            _dict["transport_costs"] = None

        return _dict

    @classmethod
    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
        """Create an instance of ExternalAPIWaybillRetrieve from a dict"""
        if obj is None:
            return None

        if not isinstance(obj, dict):
            return cls.model_validate(obj)

        _obj = cls.model_validate(
            {
                "waybill_id": obj.get("waybill_id"),
                "number": obj.get("number"),
                "status": obj.get("status"),
                "status_description": obj.get("status_description"),
                "rows": [
                    ExternalAPIWaybillRow.from_dict(_item) for _item in obj["rows"]
                ]
                if obj.get("rows") is not None
                else None,
                "destination_raw_id": obj.get("destination_raw_id"),
                "destination_id": obj.get("destination_id"),
                "destination_name": obj.get("destination_name"),
                "destination_address": obj.get("destination_address"),
                "destination_latitude": obj.get("destination_latitude"),
                "destination_longitude": obj.get("destination_longitude"),
                "destination_waybill_reached_destination_emails": obj.get(
                    "destination_waybill_reached_destination_emails"
                ),
                "destination_waybill_accepted_emails": obj.get(
                    "destination_waybill_accepted_emails"
                ),
                "receiver_company_name": obj.get("receiver_company_name"),
                "receiver_company_reg_code": obj.get("receiver_company_reg_code"),
                "origin_raw_id": obj.get("origin_raw_id"),
                "origin_id": obj.get("origin_id"),
                "origin_name": obj.get("origin_name"),
                "origin_address": obj.get("origin_address"),
                "origin_latitude": obj.get("origin_latitude"),
                "origin_longitude": obj.get("origin_longitude"),
                "origin_waybill_reached_destination_emails": obj.get(
                    "origin_waybill_reached_destination_emails"
                ),
                "origin_waybill_accepted_emails": obj.get(
                    "origin_waybill_accepted_emails"
                ),
                "cadaster_number": obj.get("cadaster_number"),
                "dispatcher_name": obj.get("dispatcher_name"),
                "dispatcher_phone": obj.get("dispatcher_phone"),
                "holding_rights": [
                    ExternalAPIWaybillHoldingRight.from_dict(_item)
                    for _item in obj["holding_rights"]
                ]
                if obj.get("holding_rights") is not None
                else None,
                "shipper_company_name": obj.get("shipper_company_name"),
                "shipper_company_reg_code": obj.get("shipper_company_reg_code"),
                "transportation_company_name": obj.get("transportation_company_name"),
                "transportation_company_reg_code": obj.get(
                    "transportation_company_reg_code"
                ),
                "truck_reg_number": obj.get("truck_reg_number"),
                "trailer_reg_number": obj.get("trailer_reg_number"),
                "driver_email": obj.get("driver_email"),
                "driver_name": obj.get("driver_name"),
                "driver_phone": obj.get("driver_phone"),
                "driver_personal_code": obj.get("driver_personal_code"),
                "mileage": obj.get("mileage"),
                "mileage_by_driver": obj.get("mileage_by_driver"),
                "confirmed_by_email": obj.get("confirmed_by_email"),
                "confirmed_by_name": obj.get("confirmed_by_name"),
                "confirmed_by_phone": obj.get("confirmed_by_phone"),
                "cancelled_by_email": obj.get("cancelled_by_email"),
                "cancelled_by_name": obj.get("cancelled_by_name"),
                "cancelled_by_phone": obj.get("cancelled_by_phone"),
                "cancelling_reason": obj.get("cancelling_reason"),
                "dispatcher_timestamp": obj.get("dispatcher_timestamp"),
                "driver_timestamp": obj.get("driver_timestamp"),
                "destination_timestamp": obj.get("destination_timestamp"),
                "confirmed_timestamp": obj.get("confirmed_timestamp"),
                "cancelled_timestamp": obj.get("cancelled_timestamp"),
                "pdf_url": obj.get("pdf_url"),
                "navision_bin_code": obj.get("navision_bin_code"),
                "evr_waybill_number": obj.get("evr_waybill_number"),
                "project": obj.get("project"),
                "transport_costs": ExternalAPIWaybillTransportCosts.from_dict(
                    obj["transport_costs"]
                )
                if obj.get("transport_costs") is not None
                else None,
                "raw_data": ExternalAPIWaybillRawData.from_dict(obj["raw_data"])
                if obj.get("raw_data") is not None
                else None,
            }
        )
        return _obj
