<?php

namespace Square\Types;

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

/**
 * Represents a refund of a payment made using Square. Contains information about
 * the original payment and the amount of money refunded.
 */
class PaymentRefund extends JsonSerializableType
{
    /**
     * @var string $id The unique ID for this refund, generated by Square.
     */
    #[JsonProperty('id')]
    private string $id;

    /**
     * The refund's status:
     * - `PENDING` - Awaiting approval.
     * - `COMPLETED` - Successfully completed.
     * - `REJECTED` - The refund was rejected.
     * - `FAILED` - An error occurred.
     *
     * @var ?string $status
     */
    #[JsonProperty('status')]
    private ?string $status;

    /**
     * @var ?string $locationId The location ID associated with the payment this refund is attached to.
     */
    #[JsonProperty('location_id')]
    private ?string $locationId;

    /**
     * @var ?bool $unlinked Flag indicating whether or not the refund is linked to an existing payment in Square.
     */
    #[JsonProperty('unlinked')]
    private ?bool $unlinked;

    /**
     * The destination type for this refund.
     *
     * Current values include `CARD`, `BANK_ACCOUNT`, `WALLET`, `BUY_NOW_PAY_LATER`, `CASH`,
     * `EXTERNAL`, and `SQUARE_ACCOUNT`.
     *
     * @var ?string $destinationType
     */
    #[JsonProperty('destination_type')]
    private ?string $destinationType;

    /**
     * Contains information about the refund destination. This field is populated only if
     * `destination_id` is defined in the `RefundPayment` request.
     *
     * @var ?DestinationDetails $destinationDetails
     */
    #[JsonProperty('destination_details')]
    private ?DestinationDetails $destinationDetails;

    /**
     * The amount of money refunded. This amount is specified in the smallest denomination
     * of the applicable currency (for example, US dollar amounts are specified in cents).
     *
     * @var Money $amountMoney
     */
    #[JsonProperty('amount_money')]
    private Money $amountMoney;

    /**
     * The amount of money the application developer contributed to help cover the refunded amount.
     * This amount is specified in the smallest denomination of the applicable currency (for example,
     * US dollar amounts are specified in cents). For more information, see
     * [Working with Monetary Amounts](https://developer.squareup.com/docs/build-basics/working-with-monetary-amounts).
     *
     * @var ?Money $appFeeMoney
     */
    #[JsonProperty('app_fee_money')]
    private ?Money $appFeeMoney;

    /**
     * @var ?array<ProcessingFee> $processingFee Processing fees and fee adjustments assessed by Square for this refund.
     */
    #[JsonProperty('processing_fee'), ArrayType([ProcessingFee::class])]
    private ?array $processingFee;

    /**
     * @var ?string $paymentId The ID of the payment associated with this refund.
     */
    #[JsonProperty('payment_id')]
    private ?string $paymentId;

    /**
     * @var ?string $orderId The ID of the order associated with the refund.
     */
    #[JsonProperty('order_id')]
    private ?string $orderId;

    /**
     * @var ?string $reason The reason for the refund.
     */
    #[JsonProperty('reason')]
    private ?string $reason;

    /**
     * @var ?string $createdAt The timestamp of when the refund was created, in RFC 3339 format.
     */
    #[JsonProperty('created_at')]
    private ?string $createdAt;

    /**
     * @var ?string $updatedAt The timestamp of when the refund was last updated, in RFC 3339 format.
     */
    #[JsonProperty('updated_at')]
    private ?string $updatedAt;

    /**
     * @var ?string $teamMemberId An optional ID of the team member associated with taking the payment.
     */
    #[JsonProperty('team_member_id')]
    private ?string $teamMemberId;

    /**
     * @var ?string $terminalRefundId An optional ID for a Terminal refund.
     */
    #[JsonProperty('terminal_refund_id')]
    private ?string $terminalRefundId;

    /**
     * @param array{
     *   id: string,
     *   amountMoney: Money,
     *   status?: ?string,
     *   locationId?: ?string,
     *   unlinked?: ?bool,
     *   destinationType?: ?string,
     *   destinationDetails?: ?DestinationDetails,
     *   appFeeMoney?: ?Money,
     *   processingFee?: ?array<ProcessingFee>,
     *   paymentId?: ?string,
     *   orderId?: ?string,
     *   reason?: ?string,
     *   createdAt?: ?string,
     *   updatedAt?: ?string,
     *   teamMemberId?: ?string,
     *   terminalRefundId?: ?string,
     * } $values
     */
    public function __construct(
        array $values,
    ) {
        $this->id = $values['id'];
        $this->status = $values['status'] ?? null;
        $this->locationId = $values['locationId'] ?? null;
        $this->unlinked = $values['unlinked'] ?? null;
        $this->destinationType = $values['destinationType'] ?? null;
        $this->destinationDetails = $values['destinationDetails'] ?? null;
        $this->amountMoney = $values['amountMoney'];
        $this->appFeeMoney = $values['appFeeMoney'] ?? null;
        $this->processingFee = $values['processingFee'] ?? null;
        $this->paymentId = $values['paymentId'] ?? null;
        $this->orderId = $values['orderId'] ?? null;
        $this->reason = $values['reason'] ?? null;
        $this->createdAt = $values['createdAt'] ?? null;
        $this->updatedAt = $values['updatedAt'] ?? null;
        $this->teamMemberId = $values['teamMemberId'] ?? null;
        $this->terminalRefundId = $values['terminalRefundId'] ?? null;
    }

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

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

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

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

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

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

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

    /**
     * @param ?bool $value
     */
    public function setUnlinked(?bool $value = null): self
    {
        $this->unlinked = $value;
        $this->_setField('unlinked');
        return $this;
    }

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

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

    /**
     * @return ?DestinationDetails
     */
    public function getDestinationDetails(): ?DestinationDetails
    {
        return $this->destinationDetails;
    }

    /**
     * @param ?DestinationDetails $value
     */
    public function setDestinationDetails(?DestinationDetails $value = null): self
    {
        $this->destinationDetails = $value;
        $this->_setField('destinationDetails');
        return $this;
    }

    /**
     * @return Money
     */
    public function getAmountMoney(): Money
    {
        return $this->amountMoney;
    }

    /**
     * @param Money $value
     */
    public function setAmountMoney(Money $value): self
    {
        $this->amountMoney = $value;
        $this->_setField('amountMoney');
        return $this;
    }

    /**
     * @return ?Money
     */
    public function getAppFeeMoney(): ?Money
    {
        return $this->appFeeMoney;
    }

    /**
     * @param ?Money $value
     */
    public function setAppFeeMoney(?Money $value = null): self
    {
        $this->appFeeMoney = $value;
        $this->_setField('appFeeMoney');
        return $this;
    }

    /**
     * @return ?array<ProcessingFee>
     */
    public function getProcessingFee(): ?array
    {
        return $this->processingFee;
    }

    /**
     * @param ?array<ProcessingFee> $value
     */
    public function setProcessingFee(?array $value = null): self
    {
        $this->processingFee = $value;
        $this->_setField('processingFee');
        return $this;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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