import datetime
from typing import Any, Dict, List, Type, TypeVar, Union, cast

import attr
from dateutil.parser import isoparse

from ..models.address import Address
from ..models.booking_field import BookingField
from ..models.extra import Extra
from ..models.image import Image
from ..models.price_option import PriceOption
from ..models.product_agent_payment_type import ProductAgentPaymentType
from ..models.product_barcode_output_type import ProductBarcodeOutputType
from ..models.product_booking_mode import ProductBookingMode
from ..models.product_confirm_mode import ProductConfirmMode
from ..models.product_currency import ProductCurrency
from ..models.product_product_type import ProductProductType
from ..models.product_qr_code_type import ProductQrCodeType
from ..models.product_seo_tag import ProductSeoTag
from ..models.tax import Tax
from ..models.video import Video
from ..types import UNSET, Unset

T = TypeVar("T", bound="Product")


@attr.s(auto_attribs=True)
class Product:
    """Product object. Holds general details and settings of a specific tour, activity or event.

    Attributes:
        booking_fields (List[BookingField]): List of booking fields required for this product
        booking_mode (ProductBookingMode): Booking mode. Determines if this product needs availability or can be booked
            for any date.
        confirm_mode (ProductConfirmMode): Confirmation mode. Determines if bookings are automatically confirmed or it
            they are pending
        description (str): Long product description, is between 100 and 15000 characters
        price_options (List[PriceOption]): List of price options belonging to this product.
        product_code (str): Rezdy-generated unique Product code. Used by agents and for API calls
        quantity_required (bool): Does this product require a quantity to be booked? True for most products. Can be
            false if the supplier can only provide one quantity at any single time. (I.e. private charters)
        short_description (str): Product description is between 15 and 240 characters
        supplier_id (int): Rezdy internal ID of the company supplying this product
        supplier_name (str): Name of the company supplying this product
        timezone (str): Timezone used by this product and supplier. All Times must be converted to this timezone before
            being displayed to customers
        unit_label (str): What a quantity for this product is. It can be people (I.e. participant, passenger, diver) or
            objects (Kayak, Helicopter, etc.)
        unit_label_plural (str): Plural version of unitLabel
        additional_information (Union[Unset, str]): Additional information for the product, that should be sent after a
            booking is completed (i.e. by email) to the customer. Useful for integration, when manual control of the entire
            customer booking experience is wanted, and the automatic confirmation e-mail from Rezdy had been suppressed.
        advertised_price (Union[Unset, float]): General price indication for this product. It represents a display price
            only, therefore it does not affect a real booking price, which is calculated based on the price options.
        agent_payment_type (Union[Unset, ProductAgentPaymentType]): If you are an agent, payment rules setup by the
            supplier for you to book this product
        api_booking_supported (Union[Unset, bool]):
        barcode_output_type (Union[Unset, ProductBarcodeOutputType]): Specifies how to output the barcodes when this
            product is booked. Valid types are:<br><li>PARTICIPANT: Barcodes will be generated by rezdy for each participant
            when an booking is created for this product</li><li>ORDER: Barcodes will be generated by rezdy per booking</li>
        cancellation_policy_days (Union[Unset, int]):  Supplier's Cancellation policy. Number of days before the tour a
            cancellation is allowed with full refund.<br>This is only used for automated payments (PAYOUTS) bookings
        charter (Union[Unset, bool]): A charter product means each session can only have a single booking, whatever the
            number of seats booked.
        commission_includes_extras (Union[Unset, bool]): True if agent receive commission from extras, false otherwise.
        confirm_mode_min_participants (Union[Unset, int]): If confirmMode is MANUAL_THEN_AUTO or AUTO_THEN_MANUAL,
            determines the minimum number of participants per booking to trigger the change
        currency (Union[Unset, ProductCurrency]): Product prices Currency
        date_created (Union[Unset, datetime.datetime]): The product creation date
        date_updated (Union[Unset, datetime.datetime]): * The date of the last product update
        duration_minutes (Union[Unset, int]): * Duration of the product in minutes.
        extras (Union[Unset, List[Extra]]): List of extras that can be booked with this product
        general_terms (Union[Unset, str]): General terms and conditions for all products from this supplier
        images (Union[Unset, List[Image]]): List of images showcasing this product
        internal_code (Union[Unset, str]): Supplier-defined product code, used internally by the ther supplier
        languages (Union[Unset, List[str]]): List of product languages. The format of the language is ISO 639 two-letter
            code with BCP 47 language variants, separated by underscore e.g. en_au.
        location_address (Union[Unset, Address]): Address of a company, customer or product location.
        max_commission_net_rate (Union[Unset, float]): Maximum commission amount you can receive as an agent, when the
            supplier setup a net rate (Automated payments Rezdy fee is not included in the amount)
        max_commission_percent (Union[Unset, float]): Maximum commission % you can receive as an agent, when the
            supplier setup a percentage (Automated payments Rezdy fee is not included in the amount)
        minimum_notice_minutes (Union[Unset, int]): * Minimum book ahead internal before session start time in minutes.
        multi_product_booking_supported (Union[Unset, bool]):
        name (Union[Unset, str]): Product name
        pickup_id (Union[Unset, int]): * If pickups are configured for this product, the field will contain the id of
            the pickup location list created by the supplier.
        product_seo_tags (Union[Unset, List[ProductSeoTag]]): This will store product meta data such as title and
            description
        product_type (Union[Unset, ProductProductType]): Type of this product
        qr_code_type (Union[Unset, ProductQrCodeType]): Specifies the method how QR Codes will be generated for this
            product. Valid types are:<br><li>INTERNAL: QR Codes will be generated by rezdy for each participant when an
            order is created for this product</li><li>EXTERNAL: QR Codes will be randomly taken from a list of imported QR
            Codes</li><p>If nothing is specified, then no QR Codes will be generated when an order is created for this
            product
        quantity_required_max (Union[Unset, int]): Represent the max booking quantity for the product. It can be setup
            for a supplier product. For a successful booking of the product, the total number of participants (regardless of
            pricing options), per booking item in the booking request, have to be lesser or equal than this value.
        quantity_required_min (Union[Unset, int]): Represent the min booking quantity for the product. It can be setup
            for a supplier product. For a successful booking of the product, the total number of participants (regardless of
            pricing options), per booking item in the booking request, have to be greater or equal than this value.
        supplier_alias (Union[Unset, str]): Alias of the company supplying this product. Company alias is a unique key
            and should be used to retrieve company details or in filters
        tags (Union[Unset, List[str]]): List of tags related to the product. The format is [TAG_TYPE]:[TAG_VALUE] e.g.
            TYPE:ACTIVITY, CATEGORY:ABSEILING, INTENSITY:RELAXED, ACCESSIBILITY:VISION_IMPAIRED
        taxes (Union[Unset, List[Tax]]): List of taxes/fees associated with the product
        terms (Union[Unset, str]): Specific terms and conditions for this product
        videos (Union[Unset, List[Video]]): <p>List of videos showcasing this product <br/>Videos will only be returned
            when a single product is loaded.</p>
        wait_listing_enabled (Union[Unset, bool]): Signifies that customers will still be able to book this product even
            when there is not enough availability. Orders will have "On Hold" status, and no payment will be processed
        xero_account (Union[Unset, str]): Supplier Xero account for this product
    """

    booking_fields: List[BookingField]
    booking_mode: ProductBookingMode
    confirm_mode: ProductConfirmMode
    description: str
    price_options: List[PriceOption]
    product_code: str
    quantity_required: bool
    short_description: str
    supplier_id: int
    supplier_name: str
    timezone: str
    unit_label: str
    unit_label_plural: str
    additional_information: Union[Unset, str] = UNSET
    advertised_price: Union[Unset, float] = UNSET
    agent_payment_type: Union[Unset, ProductAgentPaymentType] = UNSET
    api_booking_supported: Union[Unset, bool] = UNSET
    barcode_output_type: Union[Unset, ProductBarcodeOutputType] = UNSET
    cancellation_policy_days: Union[Unset, int] = UNSET
    charter: Union[Unset, bool] = UNSET
    commission_includes_extras: Union[Unset, bool] = UNSET
    confirm_mode_min_participants: Union[Unset, int] = UNSET
    currency: Union[Unset, ProductCurrency] = UNSET
    date_created: Union[Unset, datetime.datetime] = UNSET
    date_updated: Union[Unset, datetime.datetime] = UNSET
    duration_minutes: Union[Unset, int] = UNSET
    extras: Union[Unset, List[Extra]] = UNSET
    general_terms: Union[Unset, str] = UNSET
    images: Union[Unset, List[Image]] = UNSET
    internal_code: Union[Unset, str] = UNSET
    languages: Union[Unset, List[str]] = UNSET
    location_address: Union[Unset, Address] = UNSET
    max_commission_net_rate: Union[Unset, float] = UNSET
    max_commission_percent: Union[Unset, float] = UNSET
    minimum_notice_minutes: Union[Unset, int] = UNSET
    multi_product_booking_supported: Union[Unset, bool] = UNSET
    name: Union[Unset, str] = UNSET
    pickup_id: Union[Unset, int] = UNSET
    product_seo_tags: Union[Unset, List[ProductSeoTag]] = UNSET
    product_type: Union[Unset, ProductProductType] = UNSET
    qr_code_type: Union[Unset, ProductQrCodeType] = UNSET
    quantity_required_max: Union[Unset, int] = UNSET
    quantity_required_min: Union[Unset, int] = UNSET
    supplier_alias: Union[Unset, str] = UNSET
    tags: Union[Unset, List[str]] = UNSET
    taxes: Union[Unset, List[Tax]] = UNSET
    terms: Union[Unset, str] = UNSET
    videos: Union[Unset, List[Video]] = UNSET
    wait_listing_enabled: Union[Unset, bool] = UNSET
    xero_account: Union[Unset, str] = UNSET
    additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)

    def to_dict(self) -> Dict[str, Any]:
        booking_fields = []
        for booking_fields_item_data in self.booking_fields:
            booking_fields_item = booking_fields_item_data.to_dict()

            booking_fields.append(booking_fields_item)

        booking_mode = self.booking_mode.value

        confirm_mode = self.confirm_mode.value

        description = self.description
        price_options = []
        for price_options_item_data in self.price_options:
            price_options_item = price_options_item_data.to_dict()

            price_options.append(price_options_item)

        product_code = self.product_code
        quantity_required = self.quantity_required
        short_description = self.short_description
        supplier_id = self.supplier_id
        supplier_name = self.supplier_name
        timezone = self.timezone
        unit_label = self.unit_label
        unit_label_plural = self.unit_label_plural
        additional_information = self.additional_information
        advertised_price = self.advertised_price
        agent_payment_type: Union[Unset, str] = UNSET
        if not isinstance(self.agent_payment_type, Unset):
            agent_payment_type = self.agent_payment_type.value

        api_booking_supported = self.api_booking_supported
        barcode_output_type: Union[Unset, str] = UNSET
        if not isinstance(self.barcode_output_type, Unset):
            barcode_output_type = self.barcode_output_type.value

        cancellation_policy_days = self.cancellation_policy_days
        charter = self.charter
        commission_includes_extras = self.commission_includes_extras
        confirm_mode_min_participants = self.confirm_mode_min_participants
        currency: Union[Unset, str] = UNSET
        if not isinstance(self.currency, Unset):
            currency = self.currency.value

        date_created: Union[Unset, str] = UNSET
        if not isinstance(self.date_created, Unset):
            date_created = self.date_created.isoformat()

        date_updated: Union[Unset, str] = UNSET
        if not isinstance(self.date_updated, Unset):
            date_updated = self.date_updated.isoformat()

        duration_minutes = self.duration_minutes
        extras: Union[Unset, List[Dict[str, Any]]] = UNSET
        if not isinstance(self.extras, Unset):
            extras = []
            for extras_item_data in self.extras:
                extras_item = extras_item_data.to_dict()

                extras.append(extras_item)

        general_terms = self.general_terms
        images: Union[Unset, List[Dict[str, Any]]] = UNSET
        if not isinstance(self.images, Unset):
            images = []
            for images_item_data in self.images:
                images_item = images_item_data.to_dict()

                images.append(images_item)

        internal_code = self.internal_code
        languages: Union[Unset, List[str]] = UNSET
        if not isinstance(self.languages, Unset):
            languages = self.languages

        location_address: Union[Unset, Dict[str, Any]] = UNSET
        if not isinstance(self.location_address, Unset):
            location_address = self.location_address.to_dict()

        max_commission_net_rate = self.max_commission_net_rate
        max_commission_percent = self.max_commission_percent
        minimum_notice_minutes = self.minimum_notice_minutes
        multi_product_booking_supported = self.multi_product_booking_supported
        name = self.name
        pickup_id = self.pickup_id
        product_seo_tags: Union[Unset, List[Dict[str, Any]]] = UNSET
        if not isinstance(self.product_seo_tags, Unset):
            product_seo_tags = []
            for product_seo_tags_item_data in self.product_seo_tags:
                product_seo_tags_item = product_seo_tags_item_data.to_dict()

                product_seo_tags.append(product_seo_tags_item)

        product_type: Union[Unset, str] = UNSET
        if not isinstance(self.product_type, Unset):
            product_type = self.product_type.value

        qr_code_type: Union[Unset, str] = UNSET
        if not isinstance(self.qr_code_type, Unset):
            qr_code_type = self.qr_code_type.value

        quantity_required_max = self.quantity_required_max
        quantity_required_min = self.quantity_required_min
        supplier_alias = self.supplier_alias
        tags: Union[Unset, List[str]] = UNSET
        if not isinstance(self.tags, Unset):
            tags = self.tags

        taxes: Union[Unset, List[Dict[str, Any]]] = UNSET
        if not isinstance(self.taxes, Unset):
            taxes = []
            for taxes_item_data in self.taxes:
                taxes_item = taxes_item_data.to_dict()

                taxes.append(taxes_item)

        terms = self.terms
        videos: Union[Unset, List[Dict[str, Any]]] = UNSET
        if not isinstance(self.videos, Unset):
            videos = []
            for videos_item_data in self.videos:
                videos_item = videos_item_data.to_dict()

                videos.append(videos_item)

        wait_listing_enabled = self.wait_listing_enabled
        xero_account = self.xero_account

        field_dict: Dict[str, Any] = {}
        field_dict.update(self.additional_properties)
        field_dict.update(
            {
                "bookingFields": booking_fields,
                "bookingMode": booking_mode,
                "confirmMode": confirm_mode,
                "description": description,
                "priceOptions": price_options,
                "productCode": product_code,
                "quantityRequired": quantity_required,
                "shortDescription": short_description,
                "supplierId": supplier_id,
                "supplierName": supplier_name,
                "timezone": timezone,
                "unitLabel": unit_label,
                "unitLabelPlural": unit_label_plural,
            }
        )
        if additional_information is not UNSET:
            field_dict["additionalInformation"] = additional_information
        if advertised_price is not UNSET:
            field_dict["advertisedPrice"] = advertised_price
        if agent_payment_type is not UNSET:
            field_dict["agentPaymentType"] = agent_payment_type
        if api_booking_supported is not UNSET:
            field_dict["apiBookingSupported"] = api_booking_supported
        if barcode_output_type is not UNSET:
            field_dict["barcodeOutputType"] = barcode_output_type
        if cancellation_policy_days is not UNSET:
            field_dict["cancellationPolicyDays"] = cancellation_policy_days
        if charter is not UNSET:
            field_dict["charter"] = charter
        if commission_includes_extras is not UNSET:
            field_dict["commissionIncludesExtras"] = commission_includes_extras
        if confirm_mode_min_participants is not UNSET:
            field_dict["confirmModeMinParticipants"] = confirm_mode_min_participants
        if currency is not UNSET:
            field_dict["currency"] = currency
        if date_created is not UNSET:
            field_dict["dateCreated"] = date_created
        if date_updated is not UNSET:
            field_dict["dateUpdated"] = date_updated
        if duration_minutes is not UNSET:
            field_dict["durationMinutes"] = duration_minutes
        if extras is not UNSET:
            field_dict["extras"] = extras
        if general_terms is not UNSET:
            field_dict["generalTerms"] = general_terms
        if images is not UNSET:
            field_dict["images"] = images
        if internal_code is not UNSET:
            field_dict["internalCode"] = internal_code
        if languages is not UNSET:
            field_dict["languages"] = languages
        if location_address is not UNSET:
            field_dict["locationAddress"] = location_address
        if max_commission_net_rate is not UNSET:
            field_dict["maxCommissionNetRate"] = max_commission_net_rate
        if max_commission_percent is not UNSET:
            field_dict["maxCommissionPercent"] = max_commission_percent
        if minimum_notice_minutes is not UNSET:
            field_dict["minimumNoticeMinutes"] = minimum_notice_minutes
        if multi_product_booking_supported is not UNSET:
            field_dict["multiProductBookingSupported"] = multi_product_booking_supported
        if name is not UNSET:
            field_dict["name"] = name
        if pickup_id is not UNSET:
            field_dict["pickupId"] = pickup_id
        if product_seo_tags is not UNSET:
            field_dict["productSeoTags"] = product_seo_tags
        if product_type is not UNSET:
            field_dict["productType"] = product_type
        if qr_code_type is not UNSET:
            field_dict["qrCodeType"] = qr_code_type
        if quantity_required_max is not UNSET:
            field_dict["quantityRequiredMax"] = quantity_required_max
        if quantity_required_min is not UNSET:
            field_dict["quantityRequiredMin"] = quantity_required_min
        if supplier_alias is not UNSET:
            field_dict["supplierAlias"] = supplier_alias
        if tags is not UNSET:
            field_dict["tags"] = tags
        if taxes is not UNSET:
            field_dict["taxes"] = taxes
        if terms is not UNSET:
            field_dict["terms"] = terms
        if videos is not UNSET:
            field_dict["videos"] = videos
        if wait_listing_enabled is not UNSET:
            field_dict["waitListingEnabled"] = wait_listing_enabled
        if xero_account is not UNSET:
            field_dict["xeroAccount"] = xero_account

        return field_dict

    @classmethod
    def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
        d = src_dict.copy()
        booking_fields = []
        _booking_fields = d.pop("bookingFields")
        for booking_fields_item_data in _booking_fields:
            booking_fields_item = BookingField.from_dict(booking_fields_item_data)

            booking_fields.append(booking_fields_item)

        booking_mode = ProductBookingMode(d.pop("bookingMode"))

        confirm_mode = ProductConfirmMode(d.pop("confirmMode"))

        description = d.pop("description")

        price_options = []
        _price_options = d.pop("priceOptions")
        for price_options_item_data in _price_options:
            price_options_item = PriceOption.from_dict(price_options_item_data)

            price_options.append(price_options_item)

        product_code = d.pop("productCode")

        quantity_required = d.pop("quantityRequired")

        short_description = d.pop("shortDescription")

        supplier_id = d.pop("supplierId")

        supplier_name = d.pop("supplierName")

        timezone = d.pop("timezone")

        unit_label = d.pop("unitLabel")

        unit_label_plural = d.pop("unitLabelPlural")

        additional_information = d.pop("additionalInformation", UNSET)

        advertised_price = d.pop("advertisedPrice", UNSET)

        _agent_payment_type = d.pop("agentPaymentType", UNSET)
        agent_payment_type: Union[Unset, ProductAgentPaymentType]
        if isinstance(_agent_payment_type, Unset):
            agent_payment_type = UNSET
        else:
            agent_payment_type = ProductAgentPaymentType(_agent_payment_type)

        api_booking_supported = d.pop("apiBookingSupported", UNSET)

        _barcode_output_type = d.pop("barcodeOutputType", UNSET)
        barcode_output_type: Union[Unset, ProductBarcodeOutputType]
        if isinstance(_barcode_output_type, Unset):
            barcode_output_type = UNSET
        else:
            barcode_output_type = ProductBarcodeOutputType(_barcode_output_type)

        cancellation_policy_days = d.pop("cancellationPolicyDays", UNSET)

        charter = d.pop("charter", UNSET)

        commission_includes_extras = d.pop("commissionIncludesExtras", UNSET)

        confirm_mode_min_participants = d.pop("confirmModeMinParticipants", UNSET)

        _currency = d.pop("currency", UNSET)
        currency: Union[Unset, ProductCurrency]
        if isinstance(_currency, Unset):
            currency = UNSET
        else:
            currency = ProductCurrency(_currency)

        _date_created = d.pop("dateCreated", UNSET)
        date_created: Union[Unset, datetime.datetime]
        if isinstance(_date_created, Unset):
            date_created = UNSET
        else:
            date_created = isoparse(_date_created)

        _date_updated = d.pop("dateUpdated", UNSET)
        date_updated: Union[Unset, datetime.datetime]
        if isinstance(_date_updated, Unset):
            date_updated = UNSET
        else:
            date_updated = isoparse(_date_updated)

        duration_minutes = d.pop("durationMinutes", UNSET)

        extras = []
        _extras = d.pop("extras", UNSET)
        for extras_item_data in _extras or []:
            extras_item = Extra.from_dict(extras_item_data)

            extras.append(extras_item)

        general_terms = d.pop("generalTerms", UNSET)

        images = []
        _images = d.pop("images", UNSET)
        for images_item_data in _images or []:
            images_item = Image.from_dict(images_item_data)

            images.append(images_item)

        internal_code = d.pop("internalCode", UNSET)

        languages = cast(List[str], d.pop("languages", UNSET))

        _location_address = d.pop("locationAddress", UNSET)
        location_address: Union[Unset, Address]
        if isinstance(_location_address, Unset):
            location_address = UNSET
        else:
            location_address = Address.from_dict(_location_address)

        max_commission_net_rate = d.pop("maxCommissionNetRate", UNSET)

        max_commission_percent = d.pop("maxCommissionPercent", UNSET)

        minimum_notice_minutes = d.pop("minimumNoticeMinutes", UNSET)

        multi_product_booking_supported = d.pop("multiProductBookingSupported", UNSET)

        name = d.pop("name", UNSET)

        pickup_id = d.pop("pickupId", UNSET)

        product_seo_tags = []
        _product_seo_tags = d.pop("productSeoTags", UNSET)
        for product_seo_tags_item_data in _product_seo_tags or []:
            product_seo_tags_item = ProductSeoTag.from_dict(product_seo_tags_item_data)

            product_seo_tags.append(product_seo_tags_item)

        _product_type = d.pop("productType", UNSET)
        product_type: Union[Unset, ProductProductType]
        if isinstance(_product_type, Unset):
            product_type = UNSET
        else:
            product_type = ProductProductType(_product_type)

        _qr_code_type = d.pop("qrCodeType", UNSET)
        qr_code_type: Union[Unset, ProductQrCodeType]
        if isinstance(_qr_code_type, Unset):
            qr_code_type = UNSET
        else:
            qr_code_type = ProductQrCodeType(_qr_code_type)

        quantity_required_max = d.pop("quantityRequiredMax", UNSET)

        quantity_required_min = d.pop("quantityRequiredMin", UNSET)

        supplier_alias = d.pop("supplierAlias", UNSET)

        tags = cast(List[str], d.pop("tags", UNSET))

        taxes = []
        _taxes = d.pop("taxes", UNSET)
        for taxes_item_data in _taxes or []:
            taxes_item = Tax.from_dict(taxes_item_data)

            taxes.append(taxes_item)

        terms = d.pop("terms", UNSET)

        videos = []
        _videos = d.pop("videos", UNSET)
        for videos_item_data in _videos or []:
            videos_item = Video.from_dict(videos_item_data)

            videos.append(videos_item)

        wait_listing_enabled = d.pop("waitListingEnabled", UNSET)

        xero_account = d.pop("xeroAccount", UNSET)

        product = cls(
            booking_fields=booking_fields,
            booking_mode=booking_mode,
            confirm_mode=confirm_mode,
            description=description,
            price_options=price_options,
            product_code=product_code,
            quantity_required=quantity_required,
            short_description=short_description,
            supplier_id=supplier_id,
            supplier_name=supplier_name,
            timezone=timezone,
            unit_label=unit_label,
            unit_label_plural=unit_label_plural,
            additional_information=additional_information,
            advertised_price=advertised_price,
            agent_payment_type=agent_payment_type,
            api_booking_supported=api_booking_supported,
            barcode_output_type=barcode_output_type,
            cancellation_policy_days=cancellation_policy_days,
            charter=charter,
            commission_includes_extras=commission_includes_extras,
            confirm_mode_min_participants=confirm_mode_min_participants,
            currency=currency,
            date_created=date_created,
            date_updated=date_updated,
            duration_minutes=duration_minutes,
            extras=extras,
            general_terms=general_terms,
            images=images,
            internal_code=internal_code,
            languages=languages,
            location_address=location_address,
            max_commission_net_rate=max_commission_net_rate,
            max_commission_percent=max_commission_percent,
            minimum_notice_minutes=minimum_notice_minutes,
            multi_product_booking_supported=multi_product_booking_supported,
            name=name,
            pickup_id=pickup_id,
            product_seo_tags=product_seo_tags,
            product_type=product_type,
            qr_code_type=qr_code_type,
            quantity_required_max=quantity_required_max,
            quantity_required_min=quantity_required_min,
            supplier_alias=supplier_alias,
            tags=tags,
            taxes=taxes,
            terms=terms,
            videos=videos,
            wait_listing_enabled=wait_listing_enabled,
            xero_account=xero_account,
        )

        product.additional_properties = d
        return product

    @property
    def additional_keys(self) -> List[str]:
        return list(self.additional_properties.keys())

    def __getitem__(self, key: str) -> Any:
        return self.additional_properties[key]

    def __setitem__(self, key: str, value: Any) -> None:
        self.additional_properties[key] = value

    def __delitem__(self, key: str) -> None:
        del self.additional_properties[key]

    def __contains__(self, key: str) -> bool:
        return key in self.additional_properties
