# 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
from typing import Any, Dict, List, Optional, Set, Union

from pydantic import (
    BaseModel,
    ConfigDict,
    Field,
    StrictStr,
    ValidationError,
    field_validator,
)
from typing_extensions import Literal, Self

from pywaybiller.openapi_client.models.blank_enum import BlankEnum
from pywaybiller.openapi_client.models.pricing_system_enum import PricingSystemEnum

EXTERNALAPIWAYBILLTRANSPORTCOSTSPRICINGSYSTEM_ONE_OF_SCHEMAS = [
    "BlankEnum",
    "PricingSystemEnum",
]


class ExternalAPIWaybillTransportCostsPricingSystem(BaseModel):
    """
    The price used to calculate the transport cost.  * `coefficient_price` - Coefficient price * `ton_price` - Ton price * `mileage_price` - Mileage price * `load_price` - Load price
    """

    # data type: PricingSystemEnum
    oneof_schema_1_validator: Optional[PricingSystemEnum] = None
    # data type: BlankEnum
    oneof_schema_2_validator: Optional[BlankEnum] = None
    actual_instance: Optional[Union[BlankEnum, PricingSystemEnum]] = None
    one_of_schemas: Set[str] = {"BlankEnum", "PricingSystemEnum"}

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

    def __init__(self, *args, **kwargs) -> None:
        if args:
            if len(args) > 1:
                raise ValueError(
                    "If a position argument is used, only 1 is allowed to set `actual_instance`"
                )
            if kwargs:
                raise ValueError(
                    "If a position argument is used, keyword arguments cannot be used."
                )
            super().__init__(actual_instance=args[0])
        else:
            super().__init__(**kwargs)

    @field_validator("actual_instance")
    def actual_instance_must_validate_oneof(cls, v):
        instance = ExternalAPIWaybillTransportCostsPricingSystem.model_construct()
        error_messages = []
        match = 0
        # validate data type: PricingSystemEnum
        if not isinstance(v, PricingSystemEnum):
            error_messages.append(
                f"Error! Input type `{type(v)}` is not `PricingSystemEnum`"
            )
        else:
            match += 1
        # validate data type: BlankEnum
        if not isinstance(v, BlankEnum):
            error_messages.append(f"Error! Input type `{type(v)}` is not `BlankEnum`")
        else:
            match += 1
        if match > 1:
            # more than 1 match
            raise ValueError(
                "Multiple matches found when setting `actual_instance` in ExternalAPIWaybillTransportCostsPricingSystem with oneOf schemas: BlankEnum, PricingSystemEnum. Details: "
                + ", ".join(error_messages)
            )
        elif match == 0:
            # no match
            raise ValueError(
                "No match found when setting `actual_instance` in ExternalAPIWaybillTransportCostsPricingSystem with oneOf schemas: BlankEnum, PricingSystemEnum. Details: "
                + ", ".join(error_messages)
            )
        else:
            return v

    @classmethod
    def from_dict(cls, obj: Union[str, Dict[str, Any]]) -> Self:
        return cls.from_json(json.dumps(obj))

    @classmethod
    def from_json(cls, json_str: str) -> Self:
        """Returns the object represented by the json string"""
        instance = cls.model_construct()
        error_messages = []
        match = 0

        # deserialize data into PricingSystemEnum
        try:
            instance.actual_instance = PricingSystemEnum.from_json(json_str)
            match += 1
        except (ValidationError, ValueError) as e:
            error_messages.append(str(e))
        # deserialize data into BlankEnum
        try:
            instance.actual_instance = BlankEnum.from_json(json_str)
            match += 1
        except (ValidationError, ValueError) as e:
            error_messages.append(str(e))

        if match > 1:
            # more than 1 match
            raise ValueError(
                "Multiple matches found when deserializing the JSON string into ExternalAPIWaybillTransportCostsPricingSystem with oneOf schemas: BlankEnum, PricingSystemEnum. Details: "
                + ", ".join(error_messages)
            )
        elif match == 0:
            # no match
            raise ValueError(
                "No match found when deserializing the JSON string into ExternalAPIWaybillTransportCostsPricingSystem with oneOf schemas: BlankEnum, PricingSystemEnum. Details: "
                + ", ".join(error_messages)
            )
        else:
            return instance

    def to_json(self) -> str:
        """Returns the JSON representation of the actual instance"""
        if self.actual_instance is None:
            return "null"

        if hasattr(self.actual_instance, "to_json") and callable(
            self.actual_instance.to_json
        ):
            return self.actual_instance.to_json()
        else:
            return json.dumps(self.actual_instance)

    def to_dict(self) -> Optional[Union[Dict[str, Any], BlankEnum, PricingSystemEnum]]:
        """Returns the dict representation of the actual instance"""
        if self.actual_instance is None:
            return None

        if hasattr(self.actual_instance, "to_dict") and callable(
            self.actual_instance.to_dict
        ):
            return self.actual_instance.to_dict()
        else:
            # primitive type
            return self.actual_instance

    def to_str(self) -> str:
        """Returns the string representation of the actual instance"""
        return pprint.pformat(self.model_dump())
