<?php

namespace Square\Types;

use Square\Core\Json\JsonSerializableType;
use Square\Core\Json\JsonProperty;

/**
 * Represents the payment details of a card to be used for payments. These
 * details are determined by the payment token generated by Web Payments SDK.
 */
class Card extends JsonSerializableType
{
    /**
     * @var ?string $id Unique ID for this card. Generated by Square.
     */
    #[JsonProperty('id')]
    private ?string $id;

    /**
     * The card's brand.
     * See [CardBrand](#type-cardbrand) for possible values
     *
     * @var ?value-of<CardBrand> $cardBrand
     */
    #[JsonProperty('card_brand')]
    private ?string $cardBrand;

    /**
     * @var ?string $last4 The last 4 digits of the card number.
     */
    #[JsonProperty('last_4')]
    private ?string $last4;

    /**
     * @var ?int $expMonth The expiration month of the associated card as an integer between 1 and 12.
     */
    #[JsonProperty('exp_month')]
    private ?int $expMonth;

    /**
     * @var ?int $expYear The four-digit year of the card's expiration date.
     */
    #[JsonProperty('exp_year')]
    private ?int $expYear;

    /**
     * @var ?string $cardholderName The name of the cardholder.
     */
    #[JsonProperty('cardholder_name')]
    private ?string $cardholderName;

    /**
     * The billing address for this card. `US` postal codes can be provided as a 5-digit zip code
     * or 9-digit ZIP+4 (example: `12345-6789`). For a full list of field meanings by country, see
     * [Working with Addresses](https://developer.squareup.com/docs/build-basics/common-data-types/working-with-addresses).
     *
     * @var ?Address $billingAddress
     */
    #[JsonProperty('billing_address')]
    private ?Address $billingAddress;

    /**
     * Intended as a Square-assigned identifier, based
     * on the card number, to identify the card across multiple locations within a
     * single application.
     *
     * @var ?string $fingerprint
     */
    #[JsonProperty('fingerprint')]
    private ?string $fingerprint;

    /**
     * @var ?string $customerId **Required** The ID of a [customer](entity:Customer) to be associated with the card.
     */
    #[JsonProperty('customer_id')]
    private ?string $customerId;

    /**
     * @var ?string $merchantId The ID of the merchant associated with the card.
     */
    #[JsonProperty('merchant_id')]
    private ?string $merchantId;

    /**
     * An optional user-defined reference ID that associates this card with
     * another entity in an external system. For example, a customer ID from an
     * external customer management system.
     *
     * @var ?string $referenceId
     */
    #[JsonProperty('reference_id')]
    private ?string $referenceId;

    /**
     * @var ?bool $enabled Indicates whether or not a card can be used for payments.
     */
    #[JsonProperty('enabled')]
    private ?bool $enabled;

    /**
     * The type of the card.
     * The Card object includes this field only in response to Payments API calls.
     * See [CardType](#type-cardtype) for possible values
     *
     * @var ?value-of<CardType> $cardType
     */
    #[JsonProperty('card_type')]
    private ?string $cardType;

    /**
     * Indicates whether the card is prepaid or not.
     * See [CardPrepaidType](#type-cardprepaidtype) for possible values
     *
     * @var ?value-of<CardPrepaidType> $prepaidType
     */
    #[JsonProperty('prepaid_type')]
    private ?string $prepaidType;

    /**
     * The first six digits of the card number, known as the Bank Identification Number (BIN). Only the Payments API
     * returns this field.
     *
     * @var ?string $bin
     */
    #[JsonProperty('bin')]
    private ?string $bin;

    /**
     * Current version number of the card. Increments with each card update. Requests to update an
     * existing Card object will be rejected unless the version in the request matches the current
     * version for the Card.
     *
     * @var ?int $version
     */
    #[JsonProperty('version')]
    private ?int $version;

    /**
     * The card's co-brand if available. For example, an Afterpay virtual card would have a
     * co-brand of AFTERPAY.
     * See [CardCoBrand](#type-cardcobrand) for possible values
     *
     * @var ?value-of<CardCoBrand> $cardCoBrand
     */
    #[JsonProperty('card_co_brand')]
    private ?string $cardCoBrand;

    /**
     * An alert from the issuing bank about the card status. Alerts can indicate whether
     * future charges to the card are likely to fail. For more information, see
     * [Manage Card on File Declines](https://developer.squareup.com/docs/cards-api/manage-card-on-file-declines).
     *
     * This field is present only if there's an active issuer alert.
     * See [IssuerAlert](#type-issueralert) for possible values
     *
     * @var ?'ISSUER_ALERT_CARD_CLOSED' $issuerAlert
     */
    #[JsonProperty('issuer_alert')]
    private ?string $issuerAlert;

    /**
     * The timestamp of when the current issuer alert was received and processed, in
     * RFC 3339 format.
     *
     * This field is present only if there's an active issuer alert.
     *
     * @var ?string $issuerAlertAt
     */
    #[JsonProperty('issuer_alert_at')]
    private ?string $issuerAlertAt;

    /**
     * Indicates whether the card is linked to a Health Savings Account (HSA) or Flexible
     * Spending Account (FSA), based on the card BIN.
     *
     * @var ?bool $hsaFsa
     */
    #[JsonProperty('hsa_fsa')]
    private ?bool $hsaFsa;

    /**
     * @param array{
     *   id?: ?string,
     *   cardBrand?: ?value-of<CardBrand>,
     *   last4?: ?string,
     *   expMonth?: ?int,
     *   expYear?: ?int,
     *   cardholderName?: ?string,
     *   billingAddress?: ?Address,
     *   fingerprint?: ?string,
     *   customerId?: ?string,
     *   merchantId?: ?string,
     *   referenceId?: ?string,
     *   enabled?: ?bool,
     *   cardType?: ?value-of<CardType>,
     *   prepaidType?: ?value-of<CardPrepaidType>,
     *   bin?: ?string,
     *   version?: ?int,
     *   cardCoBrand?: ?value-of<CardCoBrand>,
     *   issuerAlert?: ?'ISSUER_ALERT_CARD_CLOSED',
     *   issuerAlertAt?: ?string,
     *   hsaFsa?: ?bool,
     * } $values
     */
    public function __construct(
        array $values = [],
    ) {
        $this->id = $values['id'] ?? null;
        $this->cardBrand = $values['cardBrand'] ?? null;
        $this->last4 = $values['last4'] ?? null;
        $this->expMonth = $values['expMonth'] ?? null;
        $this->expYear = $values['expYear'] ?? null;
        $this->cardholderName = $values['cardholderName'] ?? null;
        $this->billingAddress = $values['billingAddress'] ?? null;
        $this->fingerprint = $values['fingerprint'] ?? null;
        $this->customerId = $values['customerId'] ?? null;
        $this->merchantId = $values['merchantId'] ?? null;
        $this->referenceId = $values['referenceId'] ?? null;
        $this->enabled = $values['enabled'] ?? null;
        $this->cardType = $values['cardType'] ?? null;
        $this->prepaidType = $values['prepaidType'] ?? null;
        $this->bin = $values['bin'] ?? null;
        $this->version = $values['version'] ?? null;
        $this->cardCoBrand = $values['cardCoBrand'] ?? null;
        $this->issuerAlert = $values['issuerAlert'] ?? null;
        $this->issuerAlertAt = $values['issuerAlertAt'] ?? null;
        $this->hsaFsa = $values['hsaFsa'] ?? null;
    }

    /**
     * @return ?string
     */
    public function getId(): ?string
    {
        return $this->id;
    }

    /**
     * @param ?string $value
     */
    public function setId(?string $value = null): self
    {
        $this->id = $value;
        return $this;
    }

    /**
     * @return ?value-of<CardBrand>
     */
    public function getCardBrand(): ?string
    {
        return $this->cardBrand;
    }

    /**
     * @param ?value-of<CardBrand> $value
     */
    public function setCardBrand(?string $value = null): self
    {
        $this->cardBrand = $value;
        return $this;
    }

    /**
     * @return ?string
     */
    public function getLast4(): ?string
    {
        return $this->last4;
    }

    /**
     * @param ?string $value
     */
    public function setLast4(?string $value = null): self
    {
        $this->last4 = $value;
        return $this;
    }

    /**
     * @return ?int
     */
    public function getExpMonth(): ?int
    {
        return $this->expMonth;
    }

    /**
     * @param ?int $value
     */
    public function setExpMonth(?int $value = null): self
    {
        $this->expMonth = $value;
        return $this;
    }

    /**
     * @return ?int
     */
    public function getExpYear(): ?int
    {
        return $this->expYear;
    }

    /**
     * @param ?int $value
     */
    public function setExpYear(?int $value = null): self
    {
        $this->expYear = $value;
        return $this;
    }

    /**
     * @return ?string
     */
    public function getCardholderName(): ?string
    {
        return $this->cardholderName;
    }

    /**
     * @param ?string $value
     */
    public function setCardholderName(?string $value = null): self
    {
        $this->cardholderName = $value;
        return $this;
    }

    /**
     * @return ?Address
     */
    public function getBillingAddress(): ?Address
    {
        return $this->billingAddress;
    }

    /**
     * @param ?Address $value
     */
    public function setBillingAddress(?Address $value = null): self
    {
        $this->billingAddress = $value;
        return $this;
    }

    /**
     * @return ?string
     */
    public function getFingerprint(): ?string
    {
        return $this->fingerprint;
    }

    /**
     * @param ?string $value
     */
    public function setFingerprint(?string $value = null): self
    {
        $this->fingerprint = $value;
        return $this;
    }

    /**
     * @return ?string
     */
    public function getCustomerId(): ?string
    {
        return $this->customerId;
    }

    /**
     * @param ?string $value
     */
    public function setCustomerId(?string $value = null): self
    {
        $this->customerId = $value;
        return $this;
    }

    /**
     * @return ?string
     */
    public function getMerchantId(): ?string
    {
        return $this->merchantId;
    }

    /**
     * @param ?string $value
     */
    public function setMerchantId(?string $value = null): self
    {
        $this->merchantId = $value;
        return $this;
    }

    /**
     * @return ?string
     */
    public function getReferenceId(): ?string
    {
        return $this->referenceId;
    }

    /**
     * @param ?string $value
     */
    public function setReferenceId(?string $value = null): self
    {
        $this->referenceId = $value;
        return $this;
    }

    /**
     * @return ?bool
     */
    public function getEnabled(): ?bool
    {
        return $this->enabled;
    }

    /**
     * @param ?bool $value
     */
    public function setEnabled(?bool $value = null): self
    {
        $this->enabled = $value;
        return $this;
    }

    /**
     * @return ?value-of<CardType>
     */
    public function getCardType(): ?string
    {
        return $this->cardType;
    }

    /**
     * @param ?value-of<CardType> $value
     */
    public function setCardType(?string $value = null): self
    {
        $this->cardType = $value;
        return $this;
    }

    /**
     * @return ?value-of<CardPrepaidType>
     */
    public function getPrepaidType(): ?string
    {
        return $this->prepaidType;
    }

    /**
     * @param ?value-of<CardPrepaidType> $value
     */
    public function setPrepaidType(?string $value = null): self
    {
        $this->prepaidType = $value;
        return $this;
    }

    /**
     * @return ?string
     */
    public function getBin(): ?string
    {
        return $this->bin;
    }

    /**
     * @param ?string $value
     */
    public function setBin(?string $value = null): self
    {
        $this->bin = $value;
        return $this;
    }

    /**
     * @return ?int
     */
    public function getVersion(): ?int
    {
        return $this->version;
    }

    /**
     * @param ?int $value
     */
    public function setVersion(?int $value = null): self
    {
        $this->version = $value;
        return $this;
    }

    /**
     * @return ?value-of<CardCoBrand>
     */
    public function getCardCoBrand(): ?string
    {
        return $this->cardCoBrand;
    }

    /**
     * @param ?value-of<CardCoBrand> $value
     */
    public function setCardCoBrand(?string $value = null): self
    {
        $this->cardCoBrand = $value;
        return $this;
    }

    /**
     * @return ?'ISSUER_ALERT_CARD_CLOSED'
     */
    public function getIssuerAlert(): ?string
    {
        return $this->issuerAlert;
    }

    /**
     * @param ?'ISSUER_ALERT_CARD_CLOSED' $value
     */
    public function setIssuerAlert(?string $value = null): self
    {
        $this->issuerAlert = $value;
        return $this;
    }

    /**
     * @return ?string
     */
    public function getIssuerAlertAt(): ?string
    {
        return $this->issuerAlertAt;
    }

    /**
     * @param ?string $value
     */
    public function setIssuerAlertAt(?string $value = null): self
    {
        $this->issuerAlertAt = $value;
        return $this;
    }

    /**
     * @return ?bool
     */
    public function getHsaFsa(): ?bool
    {
        return $this->hsaFsa;
    }

    /**
     * @param ?bool $value
     */
    public function setHsaFsa(?bool $value = null): self
    {
        $this->hsaFsa = $value;
        return $this;
    }

    /**
     * @return string
     */
    public function __toString(): string
    {
        return $this->toJson();
    }
}
