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

import attr

from ..models.address import Address
from ..models.booking_field_create import BookingFieldCreate
from ..models.extra import Extra
from ..models.price_option_create import PriceOptionCreate
from ..models.product_create_request_barcode_output_type import ProductCreateRequestBarcodeOutputType
from ..models.product_create_request_booking_mode import ProductCreateRequestBookingMode
from ..models.product_create_request_confirm_mode import ProductCreateRequestConfirmMode
from ..models.product_create_request_product_type import ProductCreateRequestProductType
from ..types import UNSET, Unset

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


@attr.s(auto_attribs=True)
class ProductCreateRequest:
    """Partial product model containing all fields which are currently supported in product create via API.

    Attributes:
        booking_fields (List[BookingFieldCreate]): List of booking fields required for this product.
        booking_mode (ProductCreateRequestBookingMode): Booking mode. Determines if this product needs availability or
            can be booked for any date.
        confirm_mode (ProductCreateRequestConfirmMode): Confirmation mode. Determines if bookings are automatically
            confirmed or it they are pending.
        description (str): Long product description, is between 100 and 15000 characters.
        duration_minutes (int): Duration of the product in minutes.
        name (str): Product name
        price_options (List[PriceOptionCreate]): List of price options belonging to this product.
        product_type (ProductCreateRequestProductType): Type of this product.
        short_description (str): Product description is between 15 and 240 characters.
        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.
        barcode_output_type (Union[Unset, ProductCreateRequestBarcodeOutputType]): 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>
        charter (Union[Unset, bool]): A charter product means each session can only have a single booking, whatever the
            number of seats booked.
        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.
        extras (Union[Unset, List[Extra]]): List of extras IDs.
        internal_code (Union[Unset, str]): Supplier-defined product code, used internally by the 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.
        minimum_notice_minutes (Union[Unset, int]): Minimum book ahead interval for he product in minutes.
        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.
        quantity_required (Union[Unset, 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)
            or a price of a booking is fixed regardless of quantity
        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.
        terms (Union[Unset, str]): Specific terms and conditions for this product.
        xero_account (Union[Unset, str]): Supplier Xero account for this product.
    """

    booking_fields: List[BookingFieldCreate]
    booking_mode: ProductCreateRequestBookingMode
    confirm_mode: ProductCreateRequestConfirmMode
    description: str
    duration_minutes: int
    name: str
    price_options: List[PriceOptionCreate]
    product_type: ProductCreateRequestProductType
    short_description: str
    unit_label: str
    unit_label_plural: str
    additional_information: Union[Unset, str] = UNSET
    advertised_price: Union[Unset, float] = UNSET
    barcode_output_type: Union[Unset, ProductCreateRequestBarcodeOutputType] = UNSET
    charter: Union[Unset, bool] = UNSET
    confirm_mode_min_participants: Union[Unset, int] = UNSET
    extras: Union[Unset, List[Extra]] = UNSET
    internal_code: Union[Unset, str] = UNSET
    languages: Union[Unset, List[str]] = UNSET
    location_address: Union[Unset, Address] = UNSET
    minimum_notice_minutes: Union[Unset, int] = UNSET
    pickup_id: Union[Unset, int] = UNSET
    quantity_required: Union[Unset, bool] = UNSET
    quantity_required_max: Union[Unset, int] = UNSET
    quantity_required_min: Union[Unset, int] = UNSET
    terms: Union[Unset, str] = 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
        duration_minutes = self.duration_minutes
        name = self.name
        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_type = self.product_type.value

        short_description = self.short_description
        unit_label = self.unit_label
        unit_label_plural = self.unit_label_plural
        additional_information = self.additional_information
        advertised_price = self.advertised_price
        barcode_output_type: Union[Unset, str] = UNSET
        if not isinstance(self.barcode_output_type, Unset):
            barcode_output_type = self.barcode_output_type.value

        charter = self.charter
        confirm_mode_min_participants = self.confirm_mode_min_participants
        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)

        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()

        minimum_notice_minutes = self.minimum_notice_minutes
        pickup_id = self.pickup_id
        quantity_required = self.quantity_required
        quantity_required_max = self.quantity_required_max
        quantity_required_min = self.quantity_required_min
        terms = self.terms
        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,
                "durationMinutes": duration_minutes,
                "name": name,
                "priceOptions": price_options,
                "productType": product_type,
                "shortDescription": short_description,
                "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 barcode_output_type is not UNSET:
            field_dict["barcodeOutputType"] = barcode_output_type
        if charter is not UNSET:
            field_dict["charter"] = charter
        if confirm_mode_min_participants is not UNSET:
            field_dict["confirmModeMinParticipants"] = confirm_mode_min_participants
        if extras is not UNSET:
            field_dict["extras"] = extras
        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 minimum_notice_minutes is not UNSET:
            field_dict["minimumNoticeMinutes"] = minimum_notice_minutes
        if pickup_id is not UNSET:
            field_dict["pickupId"] = pickup_id
        if quantity_required is not UNSET:
            field_dict["quantityRequired"] = quantity_required
        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 terms is not UNSET:
            field_dict["terms"] = terms
        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 = BookingFieldCreate.from_dict(booking_fields_item_data)

            booking_fields.append(booking_fields_item)

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

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

        description = d.pop("description")

        duration_minutes = d.pop("durationMinutes")

        name = d.pop("name")

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

            price_options.append(price_options_item)

        product_type = ProductCreateRequestProductType(d.pop("productType"))

        short_description = d.pop("shortDescription")

        unit_label = d.pop("unitLabel")

        unit_label_plural = d.pop("unitLabelPlural")

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

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

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

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

        confirm_mode_min_participants = d.pop("confirmModeMinParticipants", 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)

        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)

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

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

        quantity_required = d.pop("quantityRequired", UNSET)

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

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

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

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

        product_create_request = cls(
            booking_fields=booking_fields,
            booking_mode=booking_mode,
            confirm_mode=confirm_mode,
            description=description,
            duration_minutes=duration_minutes,
            name=name,
            price_options=price_options,
            product_type=product_type,
            short_description=short_description,
            unit_label=unit_label,
            unit_label_plural=unit_label_plural,
            additional_information=additional_information,
            advertised_price=advertised_price,
            barcode_output_type=barcode_output_type,
            charter=charter,
            confirm_mode_min_participants=confirm_mode_min_participants,
            extras=extras,
            internal_code=internal_code,
            languages=languages,
            location_address=location_address,
            minimum_notice_minutes=minimum_notice_minutes,
            pickup_id=pickup_id,
            quantity_required=quantity_required,
            quantity_required_max=quantity_required_max,
            quantity_required_min=quantity_required_min,
            terms=terms,
            xero_account=xero_account,
        )

        product_create_request.additional_properties = d
        return product_create_request

    @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
