<?php

/**
 * The purchase unit object.
 *
 * @package WooCommerce\PayPalCommerce\ApiClient\Entity
 */
declare (strict_types=1);
namespace WooCommerce\PayPalCommerce\ApiClient\Entity;

use WooCommerce\PayPalCommerce\ApiClient\Helper\PurchaseUnitSanitizer;
/**
 * Class PurchaseUnit
 */
class PurchaseUnit
{
    /**
     * The amount.
     *
     * @var Amount
     */
    private $amount;
    /**
     * The Items.
     *
     * @var Item[]
     */
    private $items;
    /**
     * The shipping.
     *
     * @var Shipping|null
     */
    private $shipping;
    /**
     * The reference id.
     *
     * @var string
     */
    private $reference_id;
    /**
     * The description.
     *
     * @var string
     */
    private $description;
    /**
     * The custom id.
     *
     * @var string
     */
    private $custom_id;
    /**
     * The invoice id.
     *
     * @var string
     */
    private $invoice_id;
    /**
     * The soft descriptor.
     *
     * @var string
     */
    private $soft_descriptor;
    /**
     * The Payments.
     *
     * @var Payments|null
     */
    private $payments;
    /**
     * The supplementary data (Level 2/3 card processing).
     *
     * @var array|null
     */
    private $supplementary_data;
    /**
     * Whether the unit contains physical goods.
     *
     * @var bool
     */
    private $contains_physical_goods = \false;
    /**
     * The sanitizer for this purchase unit output.
     *
     * @var PurchaseUnitSanitizer|null
     */
    private $sanitizer;
    /**
     * PurchaseUnit constructor.
     *
     * @param Amount        $amount The Amount.
     * @param Item[]        $items The Items.
     * @param Shipping|null $shipping The Shipping.
     * @param string        $reference_id The reference ID.
     * @param string        $description The description.
     * @param string        $custom_id The custom ID.
     * @param string        $invoice_id The invoice ID.
     * @param string        $soft_descriptor The soft descriptor.
     * @param Payments|null $payments The Payments.
     */
    public function __construct(\WooCommerce\PayPalCommerce\ApiClient\Entity\Amount $amount, array $items = array(), ?\WooCommerce\PayPalCommerce\ApiClient\Entity\Shipping $shipping = null, string $reference_id = 'default', string $description = '', string $custom_id = '', string $invoice_id = '', string $soft_descriptor = '', ?\WooCommerce\PayPalCommerce\ApiClient\Entity\Payments $payments = null, ?array $supplementary_data = null)
    {
        $this->amount = $amount;
        $this->shipping = $shipping;
        $this->reference_id = $reference_id;
        $this->description = $description;
        //phpcs:disable Inpsyde.CodeQuality.ArgumentTypeDeclaration.NoArgumentType
        $this->items = array_values(array_filter($items, function ($item): bool {
            $is_item = $item instanceof \WooCommerce\PayPalCommerce\ApiClient\Entity\Item;
            // @phpstan-ignore instanceof.alwaysTrue
            if ($is_item && \WooCommerce\PayPalCommerce\ApiClient\Entity\Item::PHYSICAL_GOODS === $item->category()) {
                // @phpstan-ignore booleanAnd.leftAlwaysTrue
                $this->contains_physical_goods = \true;
            }
            return $is_item;
        }));
        $this->custom_id = $custom_id;
        $this->invoice_id = $invoice_id;
        $this->soft_descriptor = $soft_descriptor;
        $this->payments = $payments;
        $this->supplementary_data = $supplementary_data;
    }
    /**
     * Returns the amount.
     *
     * @return Amount
     */
    public function amount(): \WooCommerce\PayPalCommerce\ApiClient\Entity\Amount
    {
        return $this->amount;
    }
    /**
     * Sets the amount.
     *
     * @param Amount $amount The value to set.
     */
    public function set_amount(\WooCommerce\PayPalCommerce\ApiClient\Entity\Amount $amount): void
    {
        $this->amount = $amount;
    }
    /**
     * Returns the shipping.
     *
     * @return Shipping|null
     */
    public function shipping()
    {
        return $this->shipping;
    }
    /**
     * Sets shipping info.
     *
     * @param Shipping|null $shipping The value to set.
     */
    public function set_shipping(?\WooCommerce\PayPalCommerce\ApiClient\Entity\Shipping $shipping): void
    {
        $this->shipping = $shipping;
    }
    /**
     * Returns the reference id.
     *
     * @return string
     */
    public function reference_id(): string
    {
        return $this->reference_id;
    }
    /**
     * Returns the description.
     *
     * @return string
     */
    public function description(): string
    {
        return $this->description;
    }
    /**
     * Returns the custom id.
     *
     * @return string
     */
    public function custom_id(): string
    {
        return $this->custom_id;
    }
    /**
     * Sets the custom ID.
     *
     * @param string $custom_id The value to set.
     */
    public function set_custom_id(string $custom_id): void
    {
        $this->custom_id = $custom_id;
    }
    /**
     * Sets the sanitizer for this purchase unit output.
     *
     * @param PurchaseUnitSanitizer|null $sanitizer The sanitizer.
     * @return void
     */
    public function set_sanitizer(?PurchaseUnitSanitizer $sanitizer)
    {
        $this->sanitizer = $sanitizer;
    }
    /**
     * Returns the invoice id.
     *
     * @return string
     */
    public function invoice_id(): string
    {
        return $this->invoice_id;
    }
    /**
     * Returns the soft descriptor.
     *
     * @return string
     */
    public function soft_descriptor(): string
    {
        return $this->soft_descriptor;
    }
    /**
     * Returns the Payments.
     *
     * @return Payments|null
     */
    public function payments()
    {
        return $this->payments;
    }
    /**
     * Returns the supplementary data.
     *
     * @return array|null
     */
    public function supplementary_data(): ?array
    {
        return $this->supplementary_data;
    }
    /**
     * Returns the Items.
     *
     * @return Item[]
     */
    public function items(): array
    {
        return $this->items;
    }
    /**
     * Whether the unit contains physical goods.
     *
     * @return bool
     */
    public function contains_physical_goods(): bool
    {
        return $this->contains_physical_goods;
    }
    /**
     * Returns the object as array.
     *
     * @param bool $sanitize_output Whether output should be sanitized for PayPal consumption.
     * @param bool $allow_ditch_items Whether to allow items to be ditched.
     *
     * @return array
     */
    public function to_array(bool $sanitize_output = \true, bool $allow_ditch_items = \true): array
    {
        $purchase_unit = array('reference_id' => $this->reference_id(), 'amount' => $this->amount()->to_array(), 'description' => $this->description(), 'items' => array_map(static function (\WooCommerce\PayPalCommerce\ApiClient\Entity\Item $item): array {
            return $item->to_array();
        }, $this->items()));
        if ($this->payments()) {
            $purchase_unit['payments'] = $this->payments()->to_array();
        }
        if ($this->shipping()) {
            $purchase_unit['shipping'] = $this->shipping()->to_array();
        }
        if ($this->custom_id()) {
            $purchase_unit['custom_id'] = $this->custom_id();
        }
        if ($this->invoice_id()) {
            $purchase_unit['invoice_id'] = $this->invoice_id();
        }
        if ($this->soft_descriptor()) {
            $purchase_unit['soft_descriptor'] = $this->soft_descriptor();
        }
        if ($this->supplementary_data()) {
            $purchase_unit['supplementary_data'] = $this->supplementary_data();
        }
        $has_ditched_items_breakdown = \false;
        if ($sanitize_output && isset($this->sanitizer)) {
            $purchase_unit = $this->sanitizer->sanitize($purchase_unit, $allow_ditch_items);
            $has_ditched_items_breakdown = $this->sanitizer->has_ditched_items_breakdown();
        }
        return $this->apply_ditch_items_mismatch_filter($has_ditched_items_breakdown, $purchase_unit);
    }
    /**
     * Applies the ppcp_ditch_items_breakdown filter.
     * If true purchase_unit items and breakdown are ditched from PayPal.
     *
     * @param bool  $ditched_items_breakdown If the breakdown and items were already ditched.
     * @param array $purchase_unit The purchase_unit array.
     * @return array
     */
    public function apply_ditch_items_mismatch_filter(bool $ditched_items_breakdown, array $purchase_unit): array
    {
        /**
         * The filter can be used to control when the items and totals breakdown are removed from PayPal order info.
         */
        $ditch = apply_filters('ppcp_ditch_items_breakdown', $ditched_items_breakdown, $this);
        if ($ditch) {
            unset($purchase_unit['items']);
            unset($purchase_unit['amount']['breakdown']);
            if (isset($this->sanitizer) && $ditch !== $ditched_items_breakdown) {
                $this->sanitizer->set_last_message(__('Ditch items breakdown filter. Items and breakdown ditched.', 'woocommerce-paypal-payments'));
            }
        }
        return $purchase_unit;
    }
}
