<?php

namespace Square\Types;

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

/**
 * Represents a transaction processed with Square, either with the
 * Connect API or with Square Point of Sale.
 *
 * The `tenders` field of this object lists all methods of payment used to pay in
 * the transaction.
 */
class Transaction extends JsonSerializableType
{
    /**
     * @var ?string $id The transaction's unique ID, issued by Square payments servers.
     */
    #[JsonProperty('id')]
    private ?string $id;

    /**
     * @var ?string $locationId The ID of the transaction's associated location.
     */
    #[JsonProperty('location_id')]
    private ?string $locationId;

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

    /**
     * @var ?array<Tender> $tenders The tenders used to pay in the transaction.
     */
    #[JsonProperty('tenders'), ArrayType([Tender::class])]
    private ?array $tenders;

    /**
     * @var ?array<Refund> $refunds Refunds that have been applied to any tender in the transaction.
     */
    #[JsonProperty('refunds'), ArrayType([Refund::class])]
    private ?array $refunds;

    /**
     * If the transaction was created with the [Charge](api-endpoint:Transactions-Charge)
     * endpoint, this value is the same as the value provided for the `reference_id`
     * parameter in the request to that endpoint. Otherwise, it is not set.
     *
     * @var ?string $referenceId
     */
    #[JsonProperty('reference_id')]
    private ?string $referenceId;

    /**
     * The Square product that processed the transaction.
     * See [TransactionProduct](#type-transactionproduct) for possible values
     *
     * @var ?value-of<TransactionProduct> $product
     */
    #[JsonProperty('product')]
    private ?string $product;

    /**
     * If the transaction was created in the Square Point of Sale app, this value
     * is the ID generated for the transaction by Square Point of Sale.
     *
     * This ID has no relationship to the transaction's canonical `id`, which is
     * generated by Square's backend servers. This value is generated for bookkeeping
     * purposes, in case the transaction cannot immediately be completed (for example,
     * if the transaction is processed in offline mode).
     *
     * It is not currently possible with the Connect API to perform a transaction
     * lookup by this value.
     *
     * @var ?string $clientId
     */
    #[JsonProperty('client_id')]
    private ?string $clientId;

    /**
     * @var ?Address $shippingAddress The shipping address provided in the request, if any.
     */
    #[JsonProperty('shipping_address')]
    private ?Address $shippingAddress;

    /**
     * @var ?string $orderId The order_id is an identifier for the order associated with this transaction, if any.
     */
    #[JsonProperty('order_id')]
    private ?string $orderId;

    /**
     * @param array{
     *   id?: ?string,
     *   locationId?: ?string,
     *   createdAt?: ?string,
     *   tenders?: ?array<Tender>,
     *   refunds?: ?array<Refund>,
     *   referenceId?: ?string,
     *   product?: ?value-of<TransactionProduct>,
     *   clientId?: ?string,
     *   shippingAddress?: ?Address,
     *   orderId?: ?string,
     * } $values
     */
    public function __construct(
        array $values = [],
    ) {
        $this->id = $values['id'] ?? null;
        $this->locationId = $values['locationId'] ?? null;
        $this->createdAt = $values['createdAt'] ?? null;
        $this->tenders = $values['tenders'] ?? null;
        $this->refunds = $values['refunds'] ?? null;
        $this->referenceId = $values['referenceId'] ?? null;
        $this->product = $values['product'] ?? null;
        $this->clientId = $values['clientId'] ?? null;
        $this->shippingAddress = $values['shippingAddress'] ?? null;
        $this->orderId = $values['orderId'] ?? 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 ?string
     */
    public function getLocationId(): ?string
    {
        return $this->locationId;
    }

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

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

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

    /**
     * @return ?array<Tender>
     */
    public function getTenders(): ?array
    {
        return $this->tenders;
    }

    /**
     * @param ?array<Tender> $value
     */
    public function setTenders(?array $value = null): self
    {
        $this->tenders = $value;
        return $this;
    }

    /**
     * @return ?array<Refund>
     */
    public function getRefunds(): ?array
    {
        return $this->refunds;
    }

    /**
     * @param ?array<Refund> $value
     */
    public function setRefunds(?array $value = null): self
    {
        $this->refunds = $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 ?value-of<TransactionProduct>
     */
    public function getProduct(): ?string
    {
        return $this->product;
    }

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

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

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

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

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

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

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

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