<?php

/**
 * Endpoint to update the cart.
 *
 * @package WooCommerce\PayPalCommerce\Button\Endpoint
 */
declare (strict_types=1);
namespace WooCommerce\PayPalCommerce\Button\Endpoint;

use Exception;
use WooCommerce\PayPalCommerce\Vendor\Psr\Log\LoggerInterface;
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
use WooCommerce\PayPalCommerce\Button\Exception\NonceValidationException;
use WooCommerce\PayPalCommerce\Button\Helper\CartProductsHelper;
/**
 * Class ChangeCartEndpoint
 */
class ChangeCartEndpoint extends \WooCommerce\PayPalCommerce\Button\Endpoint\AbstractCartEndpoint
{
    const ENDPOINT = 'ppc-change-cart';
    /**
     * The current shipping object.
     *
     * @var \WC_Shipping
     */
    private $shipping;
    /**
     * The PurchaseUnit factory.
     *
     * @var PurchaseUnitFactory
     */
    private $purchase_unit_factory;
    /**
     * ChangeCartEndpoint constructor.
     *
     * @param \WC_Cart            $cart The current WC cart object.
     * @param \WC_Shipping        $shipping The current WC shipping object.
     * @param RequestData         $request_data The request data helper.
     * @param PurchaseUnitFactory $purchase_unit_factory The PurchaseUnit factory.
     * @param CartProductsHelper  $cart_products The cart products helper.
     * @param LoggerInterface     $logger The logger.
     */
    public function __construct(\WC_Cart $cart, \WC_Shipping $shipping, \WooCommerce\PayPalCommerce\Button\Endpoint\RequestData $request_data, PurchaseUnitFactory $purchase_unit_factory, CartProductsHelper $cart_products, LoggerInterface $logger)
    {
        $this->cart = $cart;
        $this->shipping = $shipping;
        $this->request_data = $request_data;
        $this->purchase_unit_factory = $purchase_unit_factory;
        $this->cart_products = $cart_products;
        $this->logger = $logger;
        $this->logger_tag = 'updating';
    }
    /**
     * Handles the request data.
     *
     * @throws Exception On error.
     */
    protected function handle_data(): void
    {
        try {
            $data = $this->request_data->read_request($this->nonce());
        } catch (NonceValidationException $error) {
            wp_send_json_error(array('message' => $error->getMessage()), 400);
        }
        $this->cart_products->set_cart($this->cart);
        $products = $this->products_from_request();
        if (!$products) {
            return;
        }
        if (!($data['keepShipping'] ?? \false)) {
            $this->shipping->reset_shipping();
        }
        if (!$this->add_products($products)) {
            return;
        }
        wp_send_json_success($this->generate_purchase_units());
    }
    /**
     * Based on the cart contents, the purchase units are created.
     *
     * @return array
     */
    private function generate_purchase_units(): array
    {
        $pu = $this->purchase_unit_factory->from_wc_cart();
        return array($pu->to_array());
    }
    /**
     * Adds products to cart with shipping data preservation.
     *
     * @param array $products Array of products to be added to cart.
     * @return bool
     * @throws Exception Add to cart methods throw an exception on fail.
     */
    protected function add_products(array $products): bool
    {
        // Preserve shipping data before emptying cart.
        $chosen_shipping_methods = WC()->session->get('chosen_shipping_methods');
        $this->cart->empty_cart(\false);
        try {
            $this->cart_products->add_products($products);
            if ($chosen_shipping_methods) {
                WC()->session->set('chosen_shipping_methods', $chosen_shipping_methods);
                $this->cart->calculate_shipping();
                $this->cart->calculate_fees();
                $this->cart->calculate_totals();
            }
        } catch (Exception $e) {
            $this->handle_error();
        }
        return \true;
    }
}
