<?php

declare(strict_types=1);

namespace Square\Models;

use stdClass;

/**
 * Reflects the current status of a card payment. Contains only non-confidential information.
 */
class CardPaymentDetails implements \JsonSerializable
{
    /**
     * @var array
     */
    private $status = [];

    /**
     * @var Card|null
     */
    private $card;

    /**
     * @var array
     */
    private $entryMethod = [];

    /**
     * @var array
     */
    private $cvvStatus = [];

    /**
     * @var array
     */
    private $avsStatus = [];

    /**
     * @var array
     */
    private $authResultCode = [];

    /**
     * @var array
     */
    private $applicationIdentifier = [];

    /**
     * @var array
     */
    private $applicationName = [];

    /**
     * @var array
     */
    private $applicationCryptogram = [];

    /**
     * @var array
     */
    private $verificationMethod = [];

    /**
     * @var array
     */
    private $verificationResults = [];

    /**
     * @var array
     */
    private $statementDescription = [];

    /**
     * @var DeviceDetails|null
     */
    private $deviceDetails;

    /**
     * @var CardPaymentTimeline|null
     */
    private $cardPaymentTimeline;

    /**
     * @var array
     */
    private $refundRequiresCardPresence = [];

    /**
     * @var array
     */
    private $errors = [];

    /**
     * Returns Status.
     * The card payment's current state. The state can be AUTHORIZED, CAPTURED, VOIDED, or
     * FAILED.
     */
    public function getStatus(): ?string
    {
        if (count($this->status) == 0) {
            return null;
        }
        return $this->status['value'];
    }

    /**
     * Sets Status.
     * The card payment's current state. The state can be AUTHORIZED, CAPTURED, VOIDED, or
     * FAILED.
     *
     * @maps status
     */
    public function setStatus(?string $status): void
    {
        $this->status['value'] = $status;
    }

    /**
     * Unsets Status.
     * The card payment's current state. The state can be AUTHORIZED, CAPTURED, VOIDED, or
     * FAILED.
     */
    public function unsetStatus(): void
    {
        $this->status = [];
    }

    /**
     * Returns Card.
     * 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.
     */
    public function getCard(): ?Card
    {
        return $this->card;
    }

    /**
     * Sets Card.
     * 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.
     *
     * @maps card
     */
    public function setCard(?Card $card): void
    {
        $this->card = $card;
    }

    /**
     * Returns Entry Method.
     * The method used to enter the card's details for the payment. The method can be
     * `KEYED`, `SWIPED`, `EMV`, `ON_FILE`, or `CONTACTLESS`.
     */
    public function getEntryMethod(): ?string
    {
        if (count($this->entryMethod) == 0) {
            return null;
        }
        return $this->entryMethod['value'];
    }

    /**
     * Sets Entry Method.
     * The method used to enter the card's details for the payment. The method can be
     * `KEYED`, `SWIPED`, `EMV`, `ON_FILE`, or `CONTACTLESS`.
     *
     * @maps entry_method
     */
    public function setEntryMethod(?string $entryMethod): void
    {
        $this->entryMethod['value'] = $entryMethod;
    }

    /**
     * Unsets Entry Method.
     * The method used to enter the card's details for the payment. The method can be
     * `KEYED`, `SWIPED`, `EMV`, `ON_FILE`, or `CONTACTLESS`.
     */
    public function unsetEntryMethod(): void
    {
        $this->entryMethod = [];
    }

    /**
     * Returns Cvv Status.
     * The status code returned from the Card Verification Value (CVV) check. The code can be
     * `CVV_ACCEPTED`, `CVV_REJECTED`, or `CVV_NOT_CHECKED`.
     */
    public function getCvvStatus(): ?string
    {
        if (count($this->cvvStatus) == 0) {
            return null;
        }
        return $this->cvvStatus['value'];
    }

    /**
     * Sets Cvv Status.
     * The status code returned from the Card Verification Value (CVV) check. The code can be
     * `CVV_ACCEPTED`, `CVV_REJECTED`, or `CVV_NOT_CHECKED`.
     *
     * @maps cvv_status
     */
    public function setCvvStatus(?string $cvvStatus): void
    {
        $this->cvvStatus['value'] = $cvvStatus;
    }

    /**
     * Unsets Cvv Status.
     * The status code returned from the Card Verification Value (CVV) check. The code can be
     * `CVV_ACCEPTED`, `CVV_REJECTED`, or `CVV_NOT_CHECKED`.
     */
    public function unsetCvvStatus(): void
    {
        $this->cvvStatus = [];
    }

    /**
     * Returns Avs Status.
     * The status code returned from the Address Verification System (AVS) check. The code can be
     * `AVS_ACCEPTED`, `AVS_REJECTED`, or `AVS_NOT_CHECKED`.
     */
    public function getAvsStatus(): ?string
    {
        if (count($this->avsStatus) == 0) {
            return null;
        }
        return $this->avsStatus['value'];
    }

    /**
     * Sets Avs Status.
     * The status code returned from the Address Verification System (AVS) check. The code can be
     * `AVS_ACCEPTED`, `AVS_REJECTED`, or `AVS_NOT_CHECKED`.
     *
     * @maps avs_status
     */
    public function setAvsStatus(?string $avsStatus): void
    {
        $this->avsStatus['value'] = $avsStatus;
    }

    /**
     * Unsets Avs Status.
     * The status code returned from the Address Verification System (AVS) check. The code can be
     * `AVS_ACCEPTED`, `AVS_REJECTED`, or `AVS_NOT_CHECKED`.
     */
    public function unsetAvsStatus(): void
    {
        $this->avsStatus = [];
    }

    /**
     * Returns Auth Result Code.
     * The status code returned by the card issuer that describes the payment's
     * authorization status.
     */
    public function getAuthResultCode(): ?string
    {
        if (count($this->authResultCode) == 0) {
            return null;
        }
        return $this->authResultCode['value'];
    }

    /**
     * Sets Auth Result Code.
     * The status code returned by the card issuer that describes the payment's
     * authorization status.
     *
     * @maps auth_result_code
     */
    public function setAuthResultCode(?string $authResultCode): void
    {
        $this->authResultCode['value'] = $authResultCode;
    }

    /**
     * Unsets Auth Result Code.
     * The status code returned by the card issuer that describes the payment's
     * authorization status.
     */
    public function unsetAuthResultCode(): void
    {
        $this->authResultCode = [];
    }

    /**
     * Returns Application Identifier.
     * For EMV payments, the application ID identifies the EMV application used for the payment.
     */
    public function getApplicationIdentifier(): ?string
    {
        if (count($this->applicationIdentifier) == 0) {
            return null;
        }
        return $this->applicationIdentifier['value'];
    }

    /**
     * Sets Application Identifier.
     * For EMV payments, the application ID identifies the EMV application used for the payment.
     *
     * @maps application_identifier
     */
    public function setApplicationIdentifier(?string $applicationIdentifier): void
    {
        $this->applicationIdentifier['value'] = $applicationIdentifier;
    }

    /**
     * Unsets Application Identifier.
     * For EMV payments, the application ID identifies the EMV application used for the payment.
     */
    public function unsetApplicationIdentifier(): void
    {
        $this->applicationIdentifier = [];
    }

    /**
     * Returns Application Name.
     * For EMV payments, the human-readable name of the EMV application used for the payment.
     */
    public function getApplicationName(): ?string
    {
        if (count($this->applicationName) == 0) {
            return null;
        }
        return $this->applicationName['value'];
    }

    /**
     * Sets Application Name.
     * For EMV payments, the human-readable name of the EMV application used for the payment.
     *
     * @maps application_name
     */
    public function setApplicationName(?string $applicationName): void
    {
        $this->applicationName['value'] = $applicationName;
    }

    /**
     * Unsets Application Name.
     * For EMV payments, the human-readable name of the EMV application used for the payment.
     */
    public function unsetApplicationName(): void
    {
        $this->applicationName = [];
    }

    /**
     * Returns Application Cryptogram.
     * For EMV payments, the cryptogram generated for the payment.
     */
    public function getApplicationCryptogram(): ?string
    {
        if (count($this->applicationCryptogram) == 0) {
            return null;
        }
        return $this->applicationCryptogram['value'];
    }

    /**
     * Sets Application Cryptogram.
     * For EMV payments, the cryptogram generated for the payment.
     *
     * @maps application_cryptogram
     */
    public function setApplicationCryptogram(?string $applicationCryptogram): void
    {
        $this->applicationCryptogram['value'] = $applicationCryptogram;
    }

    /**
     * Unsets Application Cryptogram.
     * For EMV payments, the cryptogram generated for the payment.
     */
    public function unsetApplicationCryptogram(): void
    {
        $this->applicationCryptogram = [];
    }

    /**
     * Returns Verification Method.
     * For EMV payments, the method used to verify the cardholder's identity. The method can be
     * `PIN`, `SIGNATURE`, `PIN_AND_SIGNATURE`, `ON_DEVICE`, or `NONE`.
     */
    public function getVerificationMethod(): ?string
    {
        if (count($this->verificationMethod) == 0) {
            return null;
        }
        return $this->verificationMethod['value'];
    }

    /**
     * Sets Verification Method.
     * For EMV payments, the method used to verify the cardholder's identity. The method can be
     * `PIN`, `SIGNATURE`, `PIN_AND_SIGNATURE`, `ON_DEVICE`, or `NONE`.
     *
     * @maps verification_method
     */
    public function setVerificationMethod(?string $verificationMethod): void
    {
        $this->verificationMethod['value'] = $verificationMethod;
    }

    /**
     * Unsets Verification Method.
     * For EMV payments, the method used to verify the cardholder's identity. The method can be
     * `PIN`, `SIGNATURE`, `PIN_AND_SIGNATURE`, `ON_DEVICE`, or `NONE`.
     */
    public function unsetVerificationMethod(): void
    {
        $this->verificationMethod = [];
    }

    /**
     * Returns Verification Results.
     * For EMV payments, the results of the cardholder verification. The result can be
     * `SUCCESS`, `FAILURE`, or `UNKNOWN`.
     */
    public function getVerificationResults(): ?string
    {
        if (count($this->verificationResults) == 0) {
            return null;
        }
        return $this->verificationResults['value'];
    }

    /**
     * Sets Verification Results.
     * For EMV payments, the results of the cardholder verification. The result can be
     * `SUCCESS`, `FAILURE`, or `UNKNOWN`.
     *
     * @maps verification_results
     */
    public function setVerificationResults(?string $verificationResults): void
    {
        $this->verificationResults['value'] = $verificationResults;
    }

    /**
     * Unsets Verification Results.
     * For EMV payments, the results of the cardholder verification. The result can be
     * `SUCCESS`, `FAILURE`, or `UNKNOWN`.
     */
    public function unsetVerificationResults(): void
    {
        $this->verificationResults = [];
    }

    /**
     * Returns Statement Description.
     * The statement description sent to the card networks.
     *
     * Note: The actual statement description varies and is likely to be truncated and appended with
     * additional information on a per issuer basis.
     */
    public function getStatementDescription(): ?string
    {
        if (count($this->statementDescription) == 0) {
            return null;
        }
        return $this->statementDescription['value'];
    }

    /**
     * Sets Statement Description.
     * The statement description sent to the card networks.
     *
     * Note: The actual statement description varies and is likely to be truncated and appended with
     * additional information on a per issuer basis.
     *
     * @maps statement_description
     */
    public function setStatementDescription(?string $statementDescription): void
    {
        $this->statementDescription['value'] = $statementDescription;
    }

    /**
     * Unsets Statement Description.
     * The statement description sent to the card networks.
     *
     * Note: The actual statement description varies and is likely to be truncated and appended with
     * additional information on a per issuer basis.
     */
    public function unsetStatementDescription(): void
    {
        $this->statementDescription = [];
    }

    /**
     * Returns Device Details.
     * Details about the device that took the payment.
     */
    public function getDeviceDetails(): ?DeviceDetails
    {
        return $this->deviceDetails;
    }

    /**
     * Sets Device Details.
     * Details about the device that took the payment.
     *
     * @maps device_details
     */
    public function setDeviceDetails(?DeviceDetails $deviceDetails): void
    {
        $this->deviceDetails = $deviceDetails;
    }

    /**
     * Returns Card Payment Timeline.
     * The timeline for card payments.
     */
    public function getCardPaymentTimeline(): ?CardPaymentTimeline
    {
        return $this->cardPaymentTimeline;
    }

    /**
     * Sets Card Payment Timeline.
     * The timeline for card payments.
     *
     * @maps card_payment_timeline
     */
    public function setCardPaymentTimeline(?CardPaymentTimeline $cardPaymentTimeline): void
    {
        $this->cardPaymentTimeline = $cardPaymentTimeline;
    }

    /**
     * Returns Refund Requires Card Presence.
     * Whether the card must be physically present for the payment to
     * be refunded.  If set to `true`, the card must be present.
     */
    public function getRefundRequiresCardPresence(): ?bool
    {
        if (count($this->refundRequiresCardPresence) == 0) {
            return null;
        }
        return $this->refundRequiresCardPresence['value'];
    }

    /**
     * Sets Refund Requires Card Presence.
     * Whether the card must be physically present for the payment to
     * be refunded.  If set to `true`, the card must be present.
     *
     * @maps refund_requires_card_presence
     */
    public function setRefundRequiresCardPresence(?bool $refundRequiresCardPresence): void
    {
        $this->refundRequiresCardPresence['value'] = $refundRequiresCardPresence;
    }

    /**
     * Unsets Refund Requires Card Presence.
     * Whether the card must be physically present for the payment to
     * be refunded.  If set to `true`, the card must be present.
     */
    public function unsetRefundRequiresCardPresence(): void
    {
        $this->refundRequiresCardPresence = [];
    }

    /**
     * Returns Errors.
     * Information about errors encountered during the request.
     *
     * @return Error[]|null
     */
    public function getErrors(): ?array
    {
        if (count($this->errors) == 0) {
            return null;
        }
        return $this->errors['value'];
    }

    /**
     * Sets Errors.
     * Information about errors encountered during the request.
     *
     * @maps errors
     *
     * @param Error[]|null $errors
     */
    public function setErrors(?array $errors): void
    {
        $this->errors['value'] = $errors;
    }

    /**
     * Unsets Errors.
     * Information about errors encountered during the request.
     */
    public function unsetErrors(): void
    {
        $this->errors = [];
    }

    /**
     * Encode this object to JSON
     *
     * @param bool $asArrayWhenEmpty Whether to serialize this model as an array whenever no fields
     *        are set. (default: false)
     *
     * @return array|stdClass
     */
    #[\ReturnTypeWillChange] // @phan-suppress-current-line PhanUndeclaredClassAttribute for (php < 8.1)
    public function jsonSerialize(bool $asArrayWhenEmpty = false)
    {
        $json = [];
        if (!empty($this->status)) {
            $json['status']                        = $this->status['value'];
        }
        if (isset($this->card)) {
            $json['card']                          = $this->card;
        }
        if (!empty($this->entryMethod)) {
            $json['entry_method']                  = $this->entryMethod['value'];
        }
        if (!empty($this->cvvStatus)) {
            $json['cvv_status']                    = $this->cvvStatus['value'];
        }
        if (!empty($this->avsStatus)) {
            $json['avs_status']                    = $this->avsStatus['value'];
        }
        if (!empty($this->authResultCode)) {
            $json['auth_result_code']              = $this->authResultCode['value'];
        }
        if (!empty($this->applicationIdentifier)) {
            $json['application_identifier']        = $this->applicationIdentifier['value'];
        }
        if (!empty($this->applicationName)) {
            $json['application_name']              = $this->applicationName['value'];
        }
        if (!empty($this->applicationCryptogram)) {
            $json['application_cryptogram']        = $this->applicationCryptogram['value'];
        }
        if (!empty($this->verificationMethod)) {
            $json['verification_method']           = $this->verificationMethod['value'];
        }
        if (!empty($this->verificationResults)) {
            $json['verification_results']          = $this->verificationResults['value'];
        }
        if (!empty($this->statementDescription)) {
            $json['statement_description']         = $this->statementDescription['value'];
        }
        if (isset($this->deviceDetails)) {
            $json['device_details']                = $this->deviceDetails;
        }
        if (isset($this->cardPaymentTimeline)) {
            $json['card_payment_timeline']         = $this->cardPaymentTimeline;
        }
        if (!empty($this->refundRequiresCardPresence)) {
            $json['refund_requires_card_presence'] = $this->refundRequiresCardPresence['value'];
        }
        if (!empty($this->errors)) {
            $json['errors']                        = $this->errors['value'];
        }
        $json = array_filter($json, function ($val) {
            return $val !== null;
        });

        return (!$asArrayWhenEmpty && empty($json)) ? new stdClass() : $json;
    }
}
