class IdentifierError(RequestSetupError):
    """Errors related to invalid resource identifiers that will be requested from the API."""

    pass class Capture(ObjectBase):
    @classmethod
    def get_resource_class(cls, client):
        from ..resources.captures import Captures

        return Captures(client)

    @property
    def id(self):
        return self._get_property("id")

    @property
    def mode(self):
        return self._get_property("mode")

    @property
    def amount(self):
        return self._get_property("amount")

    @property
    def settlement_amount(self):
        return self._get_property("settlementAmount")

    @property
    def payment_id(self):
        return self._get_property("paymentId")

    @property
    def shipment_id(self):
        return self._get_property("shipmentId")

    @property
    def settlement_id(self):
        return self._get_property("settlementId")

    @property
    def created_at(self):
        return self._get_property("createdAt")

    @property
    def payment(self):
        """Return the payment for this capture."""
        # TODO Use the embedded payment data, if avalable.
        return self.client.payments.get(self.payment_id)

    @property
    def shipment(self):
        """Return the shipment for this capture."""
        url = self._get_link("shipment")
        if url:
            return self.client.shipments.from_url(url)

    @property
    def settlement(self):
        """Return the settlement for this capture."""
        return self.client.settlements.get(self.settlement_id) class Chargeback(ObjectBase):
    @classmethod
    def get_resource_class(cls, client):
        from ..resources.chargebacks import Chargebacks

        return Chargebacks(client)

    @property
    def id(self):
        return self._get_property("id")

    @property
    def amount(self):
        return self._get_property("amount")

    @property
    def settlement_amount(self):
        return self._get_property("settlementAmount")

    @property
    def created_at(self):
        return self._get_property("createdAt")

    @property
    def reason(self):
        return self._get_property("reason")

    @property
    def reversed_at(self):
        return self._get_property("reversedAt")

    @property
    def payment_id(self):
        return self._get_property("paymentId")

    @property
    def payment(self):
        """Return the Payment object related to this chargeback."""
        # TODO Use the embedded payment data, if available.
        return self.client.payments.get(self.payment_id)

    @property
    def settlement(self):
        """Return the Settlement object related to this chargeback, if available."""
        url = self._get_link("settlement")
        if not url:
            return None

        match = re.search(r"settlements/(stl_[a-zA-Z0-9]+)$", url)
        if not match:
            # This should never happen
            raise DataConsistencyError("Unable to extract the settlementId from settlement URL.")  # pragma: no cover

        settlement_id = match.group(1)
        return self.client.settlements.get(settlement_id) class Customer(ObjectBase):
    @classmethod
    def get_resource_class(cls, client):
        from ..resources.customers import Customers

        return Customers(client)

    @property
    def id(self):
        return self._get_property("id")

    @property
    def name(self):
        return self._get_property("name")

    @property
    def email(self):
        return self._get_property("email")

    @property
    def locale(self):
        return self._get_property("locale")

    @property
    def metadata(self):
        return self._get_property("metadata")

    @property
    def mode(self):
        return self._get_property("mode")

    @property
    def resource(self):
        return self._get_property("resource")

    @property
    def created_at(self):
        return self._get_property("createdAt")

    @property
    def subscriptions(self):
        """Return the subscription list for the customer."""
        if not self._get_link("subscriptions"):
            return ObjectList({}, None)
        return self.client.customer_subscriptions.on(self).list()

    @property
    def mandates(self):
        """Return the mandate list for the customer."""
        if not self._get_link("mandates"):
            return ObjectList({}, None)
        return self.client.customer_mandates.on(self).list()

    @property
    def payments(self):
        """Return the payment list for the customer."""
        if not self._get_link("payments"):
            return ObjectList({}, None)
        return self.client.customer_payments.on(self).list() class Mandate(ObjectBase):
    @classmethod
    def get_resource_class(cls, client):
        from ..resources.customer_mandates import CustomerMandates

        return CustomerMandates(client)

    STATUS_PENDING = "pending"
    STATUS_VALID = "valid"
    STATUS_INVALID = "invalid"

    @property
    def id(self):
        return self._get_property("id")

    @property
    def resource(self):
        return self._get_property("resource")

    @property
    def status(self):
        return self._get_property("status")

    @property
    def method(self):
        return self._get_property("method")

    @property
    def details(self):
        return self._get_property("details")

    @property
    def mandate_reference(self):
        return self._get_property("mandateReference")

    @property
    def signature_date(self):
        return self._get_property("signatureDate")

    @property
    def created_at(self):
        return self._get_property("createdAt")

    def is_pending(self):
        """Check if the mandate is pending."""
        return self.status == self.STATUS_PENDING

    def is_valid(self):
        """Check if the mandate is valid."""
        return self.status == self.STATUS_VALID

    def is_invalid(self):
        """Check if the mandate is invalid."""
        return self.status == self.STATUS_INVALID

    @property
    def customer(self):
        """Return the customer for this mandate."""
        url = self._get_link("customer")
        if url:
            return self.client.customers.from_url(url) class Method(ObjectBase):
    @classmethod
    def get_resource_class(cls, client):
        from ..resources.methods import Methods

        return Methods(client)

    BANCONTACT = "bancontact"
    BANKTRANSFER = "banktransfer"
    BELFIUS = "belfius"
    CREDITCARD = "creditcard"
    DIRECTDEBIT = "directdebit"
    EPS = "eps"
    GIFTCARD = "giftcard"
    GIROPAY = "giropay"
    IDEAL = "ideal"
    KBC = "kbc"
    KLARNAPAYLATER = "klarnapaylater"
    KLARNAPAYNOW = "klarnapaynow"
    KLARNASLICEIT = "klarnasliceit"
    MEALVOUCHER = "mealvoucher"
    MISTERCASH = "mistercash"
    MYBANK = "mybank"
    PAYPAL = "paypal"
    PAYSAFECARD = "paysafecard"
    PODIUMCADEAUKAART = "podiumcadeaukaart"
    PRZELEWY24 = "przelewy24"
    SOFORT = "sofort"

    @property
    def description(self):
        return self._get_property("description")

    @property
    def id(self):
        return self._get_property("id")

    @property
    def minimum_amount(self):
        return self._get_property("minimumAmount")

    @property
    def maximum_amount(self):
        return self._get_property("maximumAmount")

    @property
    def pricing(self):
        return self._get_property("pricing")

    @property
    def image_svg(self):
        images = self._get_property("image")
        return images["svg"]

    @property
    def image_size1x(self):
        images = self._get_property("image")
        return images["size1x"]

    @property
    def image_size2x(self):
        images = self._get_property("image")
        return images["size2x"]

    @property
    def issuers(self):
        """Return the list of available issuers for this payment method."""
        issuers = self._get_property("issuers") or []
        result = {
            "_embedded": {
                "issuers": issuers,
            },
            "count": len(issuers),
        }
        return ObjectList(result, Issuer) class Order(ObjectBase):
    requested_embeds = None

    def __init__(self, data, client=None, requested_embeds=None):
        super().__init__(data, client)
        self.requested_embeds = requested_embeds

    def _has_embed(self, embed_name):
        if self.requested_embeds and embed_name in self.requested_embeds:
            return True
        return False

    @classmethod
    def get_resource_class(cls, client):
        from ..resources.orders import Orders

        return Orders(client)

    STATUS_CREATED = "created"
    STATUS_PAID = "paid"
    STATUS_AUTHORIZED = "authorized"
    STATUS_CANCELED = "canceled"
    STATUS_SHIPPING = "shipping"
    STATUS_COMPLETED = "completed"
    STATUS_EXPIRED = "expired"

    @property
    def id(self):
        return self._get_property("id")

    @property
    def resource(self):
        return self._get_property("resource")

    @property
    def profile_id(self):
        return self._get_property("profileId")

    @property
    def method(self):
        return self._get_property("method")

    @property
    def mode(self):
        return self._get_property("mode")

    @property
    def amount(self):
        return self._get_property("amount")

    @property
    def amount_captured(self):
        return self._get_property("amountCaptured")

    @property
    def amount_refunded(self):
        return self._get_property("amountRefunded")

    @property
    def status(self):
        return self._get_property("status")

    @property
    def is_cancelable(self):
        return self._get_property("isCancelable")

    @property
    def billing_address(self):
        return self._get_property("billingAddress")

    @property
    def consumer_date_of_birth(self):
        return self._get_property("consumerDateOfBirth")

    @property
    def order_number(self):
        return self._get_property("orderNumber")

    @property
    def shipping_address(self):
        return self._get_property("shippingAddress")

    @property
    def locale(self):
        return self._get_property("locale")

    @property
    def metadata(self):
        return self._get_property("metadata")

    @property
    def redirect_url(self):
        return self._get_property("redirectUrl")

    @property
    def webhook_url(self):
        return self._get_property("webhookUrl")

    @property
    def created_at(self):
        return self._get_property("createdAt")

    @property
    def expires_at(self):
        return self._get_property("expiresAt")

    @property
    def expired_at(self):
        return self._get_property("expiredAt")

    @property
    def paid_at(self):
        return self._get_property("paidAt")

    @property
    def authorized_at(self):
        return self._get_property("authorizedAt")

    @property
    def canceled_at(self):
        return self._get_property("canceledAt")

    @property
    def completed_at(self):
        return self._get_property("completedAt")

    # documented _links

    @property
    def checkout_url(self):
        return self._get_link("checkout")

    # additional methods

    def is_created(self):
        return self._get_property("status") == self.STATUS_CREATED

    def is_paid(self):
        return self._get_property("status") == self.STATUS_PAID

    def is_authorized(self):
        return self._get_property("status") == self.STATUS_AUTHORIZED

    def is_canceled(self):
        return self._get_property("status") == self.STATUS_CANCELED

    def is_shipping(self):
        return self._get_property("status") == self.STATUS_SHIPPING

    def is_completed(self):
        return self._get_property("status") == self.STATUS_COMPLETED

    def is_expired(self):
        return self._get_property("status") == self.STATUS_EXPIRED

    def has_refunds(self):
        return self.amount_refunded is not None

    def create_refund(self, data=None, **params):
        """Create a refund for the order. When no data arg is given, a refund for all order lines is assumed."""
        if data is None:
            data = {"lines": []}
        refund = OrderRefunds(self.client).on(self).create(data, **params)
        return refund

    def cancel_lines(self, data=None):
        """Cancel the lines given. When no lines are given, cancel all the lines.

        Canceling an order line causes the order line status to change to canceled.
        An empty dictionary will be returned.
        """
        from ..resources.order_lines import OrderLines

        if data is None:
            data = {"lines": []}
        canceled = OrderLines(self.client).on(self).delete(data)
        return canceled

    @property
    def refunds(self):
        if not self.has_refunds():
            return ObjectList({}, None)
        return OrderRefunds(self.client).on(self).list()

    @property
    def lines(self):
        lines = self._get_property("lines") or []
        result = {
            "_embedded": {
                "lines": lines,
            },
            "count": len(lines),
        }
        return ObjectList(result, OrderLine, self.client)

    def update_line(self, resource_id, data):
        """Update a line for an order."""
        return OrderLines(self.client).on(self).update(resource_id, data)

    @property
    def shipments(self):
        """Retrieve all shipments for an order."""
        return self.client.shipments.on(self).list()

    def create_shipment(self, data=None):
        """Create a shipment for an order. When no data arg is given, a shipment for all order lines is assumed."""
        if data is None:
            data = {"lines": []}
        return self.client.shipments.on(self).create(data)

    def get_shipment(self, resource_id):
        """Retrieve a single shipment by a shipment's ID."""
        return self.client.shipments.on(self).get(resource_id)

    def update_shipment(self, resource_id, data):
        """Update the tracking information of a shipment."""
        return self.client.shipments.on(self).update(resource_id, data)

    @property
    def payments(self):
        if not self._has_embed("payments"):
            raise EmbedNotFound("payments")

        try:
            payments = self["_embedded"]["payments"]
        except KeyError:
            # No data available at API
            payments = []

        result = {
            "_embedded": {
                "payments": payments,
            },
            "count": len(payments),
        }
        return ObjectList(result, Payment, self.client)

    def create_payment(self, data):
        """Creates a new payment object for an order."""
        return OrderPayments(self.client).on(self).create(data) class Payment(ObjectBase):
    @classmethod
    def get_resource_class(cls, client):
        from ..resources.payments import Payments

        return Payments(client)

    STATUS_OPEN = "open"
    STATUS_PENDING = "pending"
    STATUS_CANCELED = "canceled"
    STATUS_EXPIRED = "expired"
    STATUS_FAILED = "failed"
    STATUS_PAID = "paid"
    STATUS_AUTHORIZED = "authorized"

    SEQUENCETYPE_ONEOFF = "oneoff"
    SEQUENCETYPE_FIRST = "first"
    SEQUENCETYPE_RECURRING = "recurring"

    # Documented properties

    @property
    def resource(self):
        return self._get_property("resource")

    @property
    def id(self):
        return self._get_property("id")

    @property
    def mode(self):
        return self._get_property("mode")

    @property
    def created_at(self):
        return self._get_property("createdAt")

    @property
    def status(self):
        return self._get_property("status")

    @property
    def is_cancelable(self):
        return self._get_property("isCancelable")

    @property
    def authorized_at(self):
        return self._get_property("authorizedAt")

    @property
    def paid_at(self):
        return self._get_property("paidAt")

    @property
    def canceled_at(self):
        return self._get_property("canceledAt")

    @property
    def expires_at(self):
        return self._get_property("expiresAt")

    @property
    def expired_at(self):
        return self._get_property("expiredAt")

    @property
    def failed_at(self):
        return self._get_property("failedAt")

    @property
    def amount(self):
        return self._get_property("amount")

    @property
    def amount_refunded(self):
        return self._get_property("amountRefunded")

    @property
    def amount_remaining(self):
        return self._get_property("amountRemaining")

    @property
    def amount_captured(self):
        return self._get_property("amountCaptured")

    @property
    def amount_chargedback(self):
        return self._get_property("amountChargedBack")

    @property
    def description(self):
        return self._get_property("description")

    @property
    def redirect_url(self):
        return self._get_property("redirectUrl")

    @property
    def webhook_url(self):
        return self._get_property("webhookUrl")

    @property
    def method(self):
        return self._get_property("method")

    @property
    def metadata(self):
        return self._get_property("metadata")

    @property
    def locale(self):
        return self._get_property("locale")

    @property
    def country_code(self):
        return self._get_property("countryCode")

    @property
    def profile_id(self):
        return self._get_property("profileId")

    @property
    def settlement_amount(self):
        return self._get_property("settlementAmount")

    @property
    def settlement_id(self):
        return self._get_property("settlementId")

    @property
    def customer_id(self):
        return self._get_property("customerId")

    @property
    def sequence_type(self):
        return self._get_property("sequenceType")

    @property
    def mandate_id(self):
        return self._get_property("mandateId")

    @property
    def subscription_id(self):
        return self._get_property("subscriptionId")

    @property
    def order_id(self):
        return self._get_property("orderId")

    @property
    def application_fee(self):
        return self._get_property("applicationFee")

    @property
    def details(self):
        return self._get_property("details")

    @property
    def routing(self):
        return self._get_property("routing")

    # documented _links

    @property
    def checkout_url(self):
        return self._get_link("checkout")

    @property
    def changepaymentstate_url(self):
        return self._get_link("changePaymentState")

    @property
    def payonline_url(self):
        return self._get_link("payOnline")

    @property
    def refunds(self):
        """Return the refunds related to this payment."""
        if not self.has_refunds():
            return ObjectList({}, None)
        return self.client.payment_refunds.on(self).list()

    @property
    def chargebacks(self):
        """Return the chargebacks related to this payment."""
        if not self.has_chargebacks():
            return ObjectList({}, None)
        return self.client.payment_chargebacks.on(self).list()

    @property
    def captures(self):
        """Return the captures related to this payment"""
        if not self.has_captures():
            return ObjectList({}, None)

        return self.client.captures.on(self).list()

    @property
    def settlement(self):
        """Return the settlement for this payment."""
        if self.settlement_id:
            return self.client.settlements.get(self.settlement_id)

    @property
    def mandate(self):
        """Return the mandate for this payment."""
        if self.customer_id and self.mandate_id:
            return self.client.customer_mandates.with_parent_id(self.customer_id).get(self.mandate_id)

    @property
    def subscription(self):
        """Return the subscription for this payment."""
        if self.customer_id and self.subscription_id:
            return self.client.customer_subscriptions.with_parent_id(self.customer_id).get(self.subscription_id)

    @property
    def customer(self):
        """Return the customer for this payment."""
        if self.customer_id:
            return self.client.customers.get(self.customer_id)

    @property
    def order(self):
        """Return the order for this payment."""
        url = self._get_link("order")
        if url:
            return self.client.orders.from_url(url)

    # additional methods

    def is_open(self):
        return self._get_property("status") == self.STATUS_OPEN

    def is_pending(self):
        return self._get_property("status") == self.STATUS_PENDING

    def is_canceled(self):
        return self._get_property("status") == self.STATUS_CANCELED

    def is_expired(self):
        return self._get_property("status") == self.STATUS_EXPIRED

    def is_failed(self):
        return self._get_property("status") == self.STATUS_FAILED

    def is_authorized(self):
        return self._get_property("status") == self.STATUS_AUTHORIZED

    def is_paid(self):
        return self._get_property("paidAt") is not None

    def has_refunds(self):
        return self._get_link("refunds") is not None

    def has_chargebacks(self):
        return self._get_link("chargebacks") is not None

    def has_captures(self):
        return self._get_link("captures") is not None

    def has_split_payments(self):
        return self._get_property("routing") is not None

    def can_be_refunded(self):
        return self._get_property("amountRemaining") is not None

    def has_sequence_type_first(self):
        return self._get_property("sequenceType") == self.SEQUENCETYPE_FIRST

    def has_sequence_type_recurring(self):
        return self._get_property("sequenceType") == self.SEQUENCETYPE_RECURRING class Refund(ObjectBase):
    @classmethod
    def get_resource_class(cls, client):
        from ..resources.refunds import Refunds

        return Refunds(client)

    STATUS_QUEUED = "queued"
    STATUS_PENDING = "pending"
    STATUS_PROCESSING = "processing"
    STATUS_REFUNDED = "refunded"

    # documented properties

    @property
    def resource(self):
        return self._get_property("resource")

    @property
    def id(self):
        return self._get_property("id")

    @property
    def amount(self):
        return self._get_property("amount")

    @property
    def settlement_id(self):
        return self._get_property("settlementId")

    @property
    def settlement_amount(self):
        return self._get_property("settlementAmount")

    @property
    def description(self):
        return self._get_property("description")

    @property
    def status(self):
        return self._get_property("status")

    @property
    def lines(self):
        """Return the lines for this refund."""
        lines = self._get_property("lines") or []
        result = {
            "_embedded": {
                "lines": lines,
            },
            "count": len(lines),
        }
        return ObjectList(result, OrderLine, self.client)

    @property
    def payment_id(self):
        return self._get_property("paymentId")

    @property
    def order_id(self):
        return self._get_property("orderId")

    @property
    def created_at(self):
        return self._get_property("createdAt")

    @property
    def metadata(self):
        return self._get_property("metadata")

    # documented _links

    @property
    def payment(self):
        """Return the payment for this refund."""
        return self.client.payments.get(self.payment_id)

    @property
    def settlement(self):
        """Return the settlement for this refund."""
        if self.settlement_id:
            return self.client.settlements.get(self.settlement_id)
        return None

    @property
    def order(self):
        """Return the order for this refund."""
        if self.order_id:
            return self.client.orders.get(self.order_id)
        return None

    # additional methods

    def is_queued(self):
        return self.status == self.STATUS_QUEUED

    def is_pending(self):
        return self.status == self.STATUS_PENDING

    def is_processing(self):
        return self.status == self.STATUS_PROCESSING

    def is_refunded(self):
        return self.status == self.STATUS_REFUNDED class Settlement(ObjectBase):
    STATUS_OPEN = "open"
    STATUS_PENDING = "pending"
    STATUS_PAIDOUT = "paidout"
    STATUS_FAILED = "failed"

    @classmethod
    def get_resource_class(cls, client):
        from ..resources.settlements import Settlements

        return Settlements(client)

    @property
    def id(self):
        return self._get_property("id")

    @property
    def reference(self):
        return self._get_property("reference")

    @property
    def created_at(self):
        return self._get_property("createdAt")

    @property
    def settled_at(self):
        return self._get_property("settledAt")

    @property
    def status(self):
        return self._get_property("status")

    @property
    def amount(self):
        return self._get_property("amount")

    @property
    def periods(self):
        return self._get_property("periods")

    @property
    def invoice_id(self):
        warnings.warn(
            "Using Settlement Invoice ID is deprecated, see "
            "https://docs.mollie.com/reference/v2/settlements-api/get-settlement",
            APIDeprecationWarning,
        )
        return self._get_property("invoiceId")

    # Additional methods

    def is_open(self):
        return self._get_property("status") == self.STATUS_OPEN

    def is_pending(self):
        return self._get_property("status") == self.STATUS_PENDING

    def is_canceled(self):
        return self._get_property("status") == self.STATUS_PAIDOUT

    def is_failed(self):
        return self._get_property("status") == self.STATUS_FAILED

    @property
    def payments(self):
        """Return the payments related to this settlement."""
        return self.client.settlement_payments.on(self).list()

    @property
    def refunds(self):
        """Return the refunds related to this settlement."""
        return self.client.settlement_refunds.on(self).list()

    @property
    def chargebacks(self):
        """Return the chargebacks related to this settlement."""
        return self.client.settlement_chargebacks.on(self).list()

    @property
    def captures(self):
        """Return the captures related to this settlement."""
        return self.client.settlement_captures.on(self).list()

    @property
    def invoice(self):
        """Return the invoice related to this settlement."""
        url = self._get_link("invoice")
        return self.client.invoices.from_url(url) class Subscription(ObjectBase):
    @classmethod
    def get_resource_class(cls, client):
        from ..resources.customer_subscriptions import CustomerSubscriptions

        return CustomerSubscriptions(client)

    STATUS_ACTIVE = "active"
    STATUS_PENDING = "pending"  # Waiting for a valid mandate.
    STATUS_CANCELED = "canceled"
    STATUS_SUSPENDED = "suspended"  # Active, but mandate became invalid.
    STATUS_COMPLETED = "completed"

    @property
    def status(self):
        return self._get_property("status")

    def is_active(self):
        return self.status == self.STATUS_ACTIVE

    def is_pending(self):
        return self.status == self.STATUS_PENDING

    def is_canceled(self):
        return self.status == self.STATUS_CANCELED

    def is_suspended(self):
        return self.status == self.STATUS_SUSPENDED

    def is_completed(self):
        return self.status == self.STATUS_COMPLETED

    @property
    def resource(self):
        return self._get_property("resource")

    @property
    def id(self):
        return self._get_property("id")

    @property
    def mode(self):
        return self._get_property("mode")

    @property
    def created_at(self):
        return self._get_property("createdAt")

    @property
    def amount(self):
        return self._get_property("amount")

    @property
    def times(self):
        return int(self._get_property("times"))

    @property
    def times_remaining(self):
        return int(self._get_property("timesRemaining"))

    @property
    def interval(self):
        return self._get_property("interval")

    @property
    def start_date(self):
        return self._get_property("startDate")

    @property
    def next_payment_date(self):
        return self._get_property("nextPaymentDate")

    @property
    def description(self):
        return self._get_property("description")

    @property
    def method(self):
        return self._get_property("method")

    @property
    def mandate_id(self):
        return self._get_property("mandateId")

    @property
    def canceled_at(self):
        return self._get_property("canceledAt")

    @property
    def webhook_url(self):
        return self._get_property("webhookUrl")

    @property
    def metadata(self):
        return self._get_property("metadata")

    @property
    def application_fee(self):
        return self._get_property("applicationFee")

    @property
    def customer(self):
        """Return the customer for this subscription."""
        url = self._get_link("customer")
        return self.client.customers.from_url(url)

    @property
    def profile(self):
        """Return the profile related to this subscription."""
        url = self._get_link("profile")
        if not url:
            return None
        return self.client.profiles.from_url(url)

    @property
    def payments(self):
        """Return a list of payments for this subscription."""
        payments = self.client.subscription_payments.on(self).list()
        return payments

    # TODO: Implement this property.
    # Payload from API is missing customerId or a _links['mandate'] field to do this efficiently.
    # @property
    # def mandate(self):
    #     pass def assert_list_object(obj, object_type, count=None):
    """Assert that a List object is correctly working, and has sane contents."""
    assert isinstance(obj, ObjectList), f"Object {obj} is not a ObjectList instance."
    assert isinstance(obj.count, int), "ObjectList count is not an integer."
    if count is not None:
        assert obj.count == count, "ObjectList does not contain the expected number of items."
    else:
        assert obj.count > 0, "ObjectList has no items."

    # verify items in list
    items = []
    for item in obj:
        assert isinstance(item, object_type)
        assert item.id is not None
        items.append(item.id)

    assert len(items) == obj.count, "Items in ObjectList don't match list count."
    assert len(set(items)) == obj.count, "Not all object ids in the ObjectList are unique."
import pytest
from mollie.api.error import IdentifierError
from mollie.api.objects.capture import Capture
from mollie.api.objects.chargeback import Chargeback
from mollie.api.objects.customer import Customer
from mollie.api.objects.mandate import Mandate
from mollie.api.objects.method import Method
from mollie.api.objects.order import Order
from mollie.api.objects.payment import Payment
from mollie.api.objects.refund import Refund
from mollie.api.objects.settlement import Settlement
from mollie.api.objects.subscription import Subscription
from .utils import assert_list_object



PAYMENT_ID = "tr_7UhSN1zuXS"
REFUND_ID = "re_4qqhO89gsT"
CHARGEBACK_ID = "chb_n9z0tp"
CUSTOMER_ID = "cst_8wmqcHMN4U"
SETTLEMENT_ID = "stl_jDk30akdN"
MANDATE_ID = "mdt_h3gAaD5zP"
SUBSCRIPTION_ID = "sub_rVKGtNd6s3"
ORDER_ID = "ord_kEn1PlbGa"


def test_list_payments(client, response):
    """Retrieve a list of payments."""
    response.get("https://api.mollie.com/v2/payments", "payments_list")

    payments = client.payments.list()
    assert_list_object(payments, Payment)


def test_create_payment(client, response):
    """Create a new payment."""
    response.post("https://api.mollie.com/v2/payments", "payment_single")

    payment = client.payments.create(
        {
            "amount": {"currency": "EUR", "value": "10.00"},
            "description": "Order #12345",
            "redirectUrl": "https://webshop.example.org/order/12345/",
            "webhookUrl": "https://webshop.example.org/payments/webhook/",
            "method": "ideal",
        }
    )
    assert payment.id == PAYMENT_ID


def test_cancel_payment(client, response):
    """Cancel existing payment."""
    response.delete(f"https://api.mollie.com/v2/payments/{PAYMENT_ID}", "payment_canceled", 200)

    canceled_payment = client.payments.delete(PAYMENT_ID)
    assert isinstance(canceled_payment, Payment)
    assert canceled_payment.is_canceled() is True
    assert canceled_payment.canceled_at == "2018-03-20T09:28:37+00:00"
    assert canceled_payment.id == PAYMENT_ID


def test_cancel_payment_invalid_id(client):
    """Verify that an invalid payment id is validated and an error is raised."""
    with pytest.raises(IdentifierError):
        client.payments.delete("invalid")


def test_get_single_payment(client, response):
    """Retrieve a single payment by payment id."""
    response.get(f"https://api.mollie.com/v2/payments/{PAYMENT_ID}", "payment_single_no_links")
    response.get(f"https://api.mollie.com/v2/customers/{CUSTOMER_ID}", "customer_single")

    payment = client.payments.get(PAYMENT_ID)
    assert isinstance(payment, Payment)
    # properties
    assert payment.resource == "payment"
    assert payment.id == PAYMENT_ID
    assert payment.mode == "test"
    assert payment.created_at == "2018-03-20T09:13:37+00:00"
    assert payment.status == Payment.STATUS_OPEN
    assert payment.is_cancelable is False
    assert payment.paid_at is None
    assert payment.canceled_at is None
    assert payment.authorized_at is None
    assert payment.expires_at == "2018-03-20T09:28:37+00:00"
    assert payment.expired_at is None
    assert payment.failed_at is None
    assert payment.amount == {"value": "10.00", "currency": "EUR"}
    assert payment.amount_refunded is None
    assert payment.amount_remaining is None
    assert payment.amount_captured == {"currency": "EUR", "value": "1.00"}
    assert payment.amount_chargedback == {"value": "5.00", "currency": "EUR"}
    assert payment.description == "Order #12345"
    assert payment.redirect_url == "https://webshop.example.org/order/12345/"
    assert payment.webhook_url == "https://webshop.example.org/payments/webhook/"

    assert payment.method == Method.IDEAL