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

import attr
from dateutil.parser import isoparse

from ..models.voucher_status import VoucherStatus
from ..models.voucher_value_type import VoucherValueType
from ..types import UNSET, Unset

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


@attr.s(auto_attribs=True)
class Voucher:
    """A Voucher is a gift card that can be used to pay for a booking.<br>It can also be generated by a booking when a
    customer buys a Gift Card.<br>This is not a "confirmation voucher", you should use Booking.orderNumber as a
    confirmation code to show to customers.

        Attributes:
            code (Union[Unset, str]): Unique voucher code
            expiry_date (Union[Unset, datetime.datetime]): Date this voucher will expire
            internal_notes (Union[Unset, str]): Internal notes only visible by the supplier of this voucher
            internal_reference (Union[Unset, str]): Agent code attached to this vouche
            issue_date (Union[Unset, datetime.datetime]): Date this voucher was created
            source_order (Union[Unset, str]): If the voucher was generated from an order - by purchasing a gift card or
                product as a gift card, it will contain the orderNumber which created the voucher. Null for vouchers manually
                created by user.
            status (Union[Unset, VoucherStatus]): Current voucher status
            value (Union[Unset, float]): The value of the voucher. There are different representations of the value -
                nominal, percentage or empty - in case of the payment for the whole product, see valueType
            value_type (Union[Unset, VoucherValueType]): <dl><dt>VALUE_LIMITPRODUCT</dt><dd>Voucher nominal value discount,
                limited to a certain product</dd><dt>VALUE</dt><dd>Voucher nominal value discount for any
                product</dd><dt>VALUE_LIMITCATALOG</dt><dd>Voucher nominal value discount, limited to a certain product
                category</dd><dt>PERCENT_LIMITPRODUCT</dt><dd>Voucher percentage value discount, limited to a certain
                product</dd><dt>PERCENT</dt><dd>Voucher percentage value discount for any
                product</dd><dt>PERCENT_LIMITCATALOG</dt><dd>Voucher percentage value discount, limited to a certain product
                category</dd><dt>PRODUCT</dt><dd>Voucher can be used as a payment method for a specific product</dd></dl>
    """

    code: Union[Unset, str] = UNSET
    expiry_date: Union[Unset, datetime.datetime] = UNSET
    internal_notes: Union[Unset, str] = UNSET
    internal_reference: Union[Unset, str] = UNSET
    issue_date: Union[Unset, datetime.datetime] = UNSET
    source_order: Union[Unset, str] = UNSET
    status: Union[Unset, VoucherStatus] = UNSET
    value: Union[Unset, float] = UNSET
    value_type: Union[Unset, VoucherValueType] = UNSET
    additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)

    def to_dict(self) -> Dict[str, Any]:
        code = self.code
        expiry_date: Union[Unset, str] = UNSET
        if not isinstance(self.expiry_date, Unset):
            expiry_date = self.expiry_date.isoformat()

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

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

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

        field_dict: Dict[str, Any] = {}
        field_dict.update(self.additional_properties)
        field_dict.update({})
        if code is not UNSET:
            field_dict["code"] = code
        if expiry_date is not UNSET:
            field_dict["expiryDate"] = expiry_date
        if internal_notes is not UNSET:
            field_dict["internalNotes"] = internal_notes
        if internal_reference is not UNSET:
            field_dict["internalReference"] = internal_reference
        if issue_date is not UNSET:
            field_dict["issueDate"] = issue_date
        if source_order is not UNSET:
            field_dict["sourceOrder"] = source_order
        if status is not UNSET:
            field_dict["status"] = status
        if value is not UNSET:
            field_dict["value"] = value
        if value_type is not UNSET:
            field_dict["valueType"] = value_type

        return field_dict

    @classmethod
    def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
        d = src_dict.copy()
        code = d.pop("code", UNSET)

        _expiry_date = d.pop("expiryDate", UNSET)
        expiry_date: Union[Unset, datetime.datetime]
        if isinstance(_expiry_date, Unset):
            expiry_date = UNSET
        else:
            expiry_date = isoparse(_expiry_date)

        internal_notes = d.pop("internalNotes", UNSET)

        internal_reference = d.pop("internalReference", UNSET)

        _issue_date = d.pop("issueDate", UNSET)
        issue_date: Union[Unset, datetime.datetime]
        if isinstance(_issue_date, Unset):
            issue_date = UNSET
        else:
            issue_date = isoparse(_issue_date)

        source_order = d.pop("sourceOrder", UNSET)

        _status = d.pop("status", UNSET)
        status: Union[Unset, VoucherStatus]
        if isinstance(_status, Unset):
            status = UNSET
        else:
            status = VoucherStatus(_status)

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

        _value_type = d.pop("valueType", UNSET)
        value_type: Union[Unset, VoucherValueType]
        if isinstance(_value_type, Unset):
            value_type = UNSET
        else:
            value_type = VoucherValueType(_value_type)

        voucher = cls(
            code=code,
            expiry_date=expiry_date,
            internal_notes=internal_notes,
            internal_reference=internal_reference,
            issue_date=issue_date,
            source_order=source_order,
            status=status,
            value=value,
            value_type=value_type,
        )

        voucher.additional_properties = d
        return voucher

    @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
