# coding: utf-8

"""
    Eazyrent products API

    EazyRent Products API ======================  Description ------------  The EazyRent Product API offers a comprehensive solution for managing rental and sale listings, including property details, media distribution, and data import capabilities. Designed for real estate professionals, this API allows users to create, update, and manage property listings efficiently while ensuring accurate data and broad market reach. With features to streamline listing distribution and import property data from other platforms, the Product API simplifies property management, helping agencies maintain up-to-date and comprehensive property portfolios.  Target Audience -----------------   * **Real Estate Agencies and Social Housing Providers:** Professionals who need a centralized system to manage property listings, including rental and sale offerings, media distribution, and data synchronization across various platforms.   * **Property Managers:** Organizations looking to efficiently organize and promote property listings, manage property details, and ensure accurate, consistent information across marketing channels.  Purpose ---------  The purpose of the EazyRent Product API is to enable streamlined property management within the EazyRent platform. By integrating this API, businesses can centralize their property data, automate distribution to marketing channels, and simplify the process of keeping listings updated. This provides agencies with a scalable, efficient way to manage property portfolios, ensuring quick, effective exposure to potential tenants and buyers.  How to use this API ---------------------  To get started with the EazyRent Product API, please refer to our comprehensive documentation for authentication details, endpoint descriptions, and integration guides. This resource will help you set up efficient property management workflows, from data import to listing updates and distribution, all accessible within your existing systems.

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

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


from __future__ import annotations
from inspect import getfullargspec
import json
import pprint
import re  # noqa: F401
from pydantic import (
    BaseModel,
    ConfigDict,
    Field,
    StrictStr,
    ValidationError,
    field_validator,
)
from typing import Optional
from eazyrent.products.v1.models.update_for_rent_product import UpdateForRentProduct
from eazyrent.products.v1.models.update_for_sale_product import UpdateForSaleProduct
from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict
from typing_extensions import Literal, Self
from pydantic import Field

UPDATEPRODUCT_ANY_OF_SCHEMAS = ["UpdateForRentProduct", "UpdateForSaleProduct"]


class UpdateProduct(BaseModel):
    """
    UpdateProduct
    """

    # data type: UpdateForRentProduct
    anyof_schema_1_validator: Optional[UpdateForRentProduct] = None
    # data type: UpdateForSaleProduct
    anyof_schema_2_validator: Optional[UpdateForSaleProduct] = None
    if TYPE_CHECKING:
        actual_instance: Optional[
            Union[UpdateForRentProduct, UpdateForSaleProduct]
        ] = None
    else:
        actual_instance: Any = None
    any_of_schemas: Set[str] = {"UpdateForRentProduct", "UpdateForSaleProduct"}

    model_config = {
        "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_anyof(cls, v):
        instance = UpdateProduct.model_construct()
        error_messages = []
        # validate data type: UpdateForRentProduct
        if not isinstance(v, UpdateForRentProduct):
            error_messages.append(
                f"Error! Input type `{type(v)}` is not `UpdateForRentProduct`"
            )
        else:
            return v

        # validate data type: UpdateForSaleProduct
        if not isinstance(v, UpdateForSaleProduct):
            error_messages.append(
                f"Error! Input type `{type(v)}` is not `UpdateForSaleProduct`"
            )
        else:
            return v

        if error_messages:
            # no match
            raise ValueError(
                "No match found when setting the actual_instance in UpdateProduct with anyOf schemas: UpdateForRentProduct, UpdateForSaleProduct. Details: "
                + ", ".join(error_messages)
            )
        else:
            return v

    @classmethod
    def from_dict(cls, obj: 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 = []
        # anyof_schema_1_validator: Optional[UpdateForRentProduct] = None
        try:
            instance.actual_instance = UpdateForRentProduct.from_json(json_str)
            return instance
        except (ValidationError, ValueError) as e:
            error_messages.append(str(e))
        # anyof_schema_2_validator: Optional[UpdateForSaleProduct] = None
        try:
            instance.actual_instance = UpdateForSaleProduct.from_json(json_str)
            return instance
        except (ValidationError, ValueError) as e:
            error_messages.append(str(e))

        if error_messages:
            # no match
            raise ValueError(
                "No match found when deserializing the JSON string into UpdateProduct with anyOf schemas: UpdateForRentProduct, UpdateForSaleProduct. 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], UpdateForRentProduct, UpdateForSaleProduct]]:
        """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:
            return self.actual_instance

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