# 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

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

from pywaybiller.openapi_client.models.external_api_loader_action_log_comment import (
    ExternalAPILoaderActionLogComment,
)
from pywaybiller.openapi_client.models.external_api_loader_action_log_raw_data import (
    ExternalAPILoaderActionLogRawData,
)


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

    log_timestamp: datetime = Field(
        description="Exact date and time when the loading action was recorded (Format: `YYYY-MM-DDThh:mm:ss.ffffff+hh:mm`)"
    )
    log_description: StrictStr = Field(
        description="Detailed description of the loading action and its associated context"
    )
    loader_operator_user_name: Annotated[str, Field(strict=True, max_length=255)] = (
        Field(description="The full name of the loader operator")
    )
    action_name: Annotated[str, Field(strict=True, max_length=1024)] = Field(
        description="Name of the loader action that was performed"
    )
    origin_name: Optional[Annotated[str, Field(strict=True, max_length=255)]] = Field(
        description="Name of the origin where the loading action was performed"
    )
    order_number: Optional[Annotated[str, Field(strict=True, max_length=16)]] = Field(
        description="Number of the order associated with the action, if applicable"
    )
    vehicle_reg_number: Optional[Annotated[str, Field(strict=True, max_length=16)]] = (
        Field(
            description="Registration number of the vehicle associated with the action, if applicable"
        )
    )
    trailer_reg_number: Optional[Annotated[str, Field(strict=True, max_length=16)]] = (
        Field(description="Registration number of the attached trailer, if applicable")
    )
    waybill_number: Optional[Annotated[str, Field(strict=True, max_length=16)]] = Field(
        description="Number of the waybill associated with the action, if applicable"
    )
    loader_unit_name: Optional[Annotated[str, Field(strict=True, max_length=1024)]] = (
        Field(
            description="Identification or name of the loading equipment that was used"
        )
    )
    assortment_name: Optional[Annotated[str, Field(strict=True, max_length=255)]] = (
        Field(description="Name of the assortment associated with the action")
    )
    subset_name: Optional[Annotated[str, Field(strict=True, max_length=64)]] = Field(
        description="Name of the subset associated with the action"
    )
    weight: Optional[StrictStr] = Field(
        description='Weight that was loaded or unloaded (e.g., `"12.345"`)'
    )
    log_comments: List[ExternalAPILoaderActionLogComment] = Field(
        description="List of all comments added to this action"
    )
    raw_data: ExternalAPILoaderActionLogRawData = Field(
        description="The IDs of the Waybiller internal objects"
    )
    __properties: ClassVar[List[str]] = [
        "log_timestamp",
        "log_description",
        "loader_operator_user_name",
        "action_name",
        "origin_name",
        "order_number",
        "vehicle_reg_number",
        "trailer_reg_number",
        "waybill_number",
        "loader_unit_name",
        "assortment_name",
        "subset_name",
        "weight",
        "log_comments",
        "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 ExternalAPILoaderActionLog 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.
        """
        excluded_fields: Set[str] = set(
            [
                "log_timestamp",
                "log_description",
                "loader_operator_user_name",
                "action_name",
                "origin_name",
                "order_number",
                "vehicle_reg_number",
                "trailer_reg_number",
                "waybill_number",
                "loader_unit_name",
                "assortment_name",
                "subset_name",
                "weight",
                "log_comments",
                "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 log_comments (list)
        _items = []
        if self.log_comments:
            for _item_log_comments in self.log_comments:
                if _item_log_comments:
                    _items.append(_item_log_comments.to_dict())
            _dict["log_comments"] = _items
        # 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 origin_name (nullable) is None
        # and model_fields_set contains the field
        if self.origin_name is None and "origin_name" in self.model_fields_set:
            _dict["origin_name"] = None

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

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

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

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

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

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

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

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

        return _dict

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

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

        _obj = cls.model_validate(
            {
                "log_timestamp": obj.get("log_timestamp"),
                "log_description": obj.get("log_description"),
                "loader_operator_user_name": obj.get("loader_operator_user_name"),
                "action_name": obj.get("action_name"),
                "origin_name": obj.get("origin_name"),
                "order_number": obj.get("order_number"),
                "vehicle_reg_number": obj.get("vehicle_reg_number"),
                "trailer_reg_number": obj.get("trailer_reg_number"),
                "waybill_number": obj.get("waybill_number"),
                "loader_unit_name": obj.get("loader_unit_name"),
                "assortment_name": obj.get("assortment_name"),
                "subset_name": obj.get("subset_name"),
                "weight": obj.get("weight"),
                "log_comments": [
                    ExternalAPILoaderActionLogComment.from_dict(_item)
                    for _item in obj["log_comments"]
                ]
                if obj.get("log_comments") is not None
                else None,
                "raw_data": ExternalAPILoaderActionLogRawData.from_dict(obj["raw_data"])
                if obj.get("raw_data") is not None
                else None,
            }
        )
        return _obj
