<?php

namespace Easymailing\App\Core\Provider\Woocommerce\Hooks;

use Easymailing\App\Api\Client;
use Easymailing\App\Core\Log\LogManager;
use Easymailing\App\Core\Provider\Woocommerce\Model\LogType;
use Easymailing\App\Core\Provider\Woocommerce\Service\CustomerService;
use Easymailing\App\Core\Provider\Woocommerce\Service\MetadataHelper;
use Easymailing\App\Core\Transient\FlashBag;
use Easymailing\App\Repository\ConfigRepository;
use Easymailing\App\Utils\Api;


class CartHooks
{
    private $config;
    private $apiClient;
    private $productHooks;
    private $logManager;
    private $customerService;

	const SESSION_ORDER_RESOURCE_ID_NAME = '_easymailing_session_order_resource_id';
	const SESSION_HASH_NAME = '_easymailing_session_hash';
	const SESSION_CART_CUSTOMER_RESOURCE_ID_NAME = '_easymailing_session_cart_customer_resource_id';

	private $cartUpdatedCalled = false;
	private $blockCheckoutSyncedInRequest = false;
	private $classicCheckoutSyncedInRequest = false;
	private $cartCustomerSyncedInRequest = false;


    public function __construct(
		ConfigRepository $configRepository,
		Client $apiClient,
		ProductHooks $productHooks,
		LogManager $logManager,
		CustomerService $customerService
    )
    {
        $this->config = $configRepository->getSynchronizationConfig();
        $this->apiClient = $apiClient;
        $this->productHooks = $productHooks;
        $this->logManager = $logManager;
        $this->customerService = $customerService;
    }



    public function cartUpdated(): void
    {
        if ($this->shouldSkipProcessing()) {
            return;
        }

		if($this->cartUpdatedCalled){
			return;
		}

        $customerResourceId = $this->resolveCustomerFromCart();

        if (!$customerResourceId) {
            return;
        }

        $cart = $this->getCart($customerResourceId);
        $customOrderId = WC()->session->get(self::SESSION_ORDER_RESOURCE_ID_NAME);

        if(empty($cart)) return;

        if (!$customOrderId) {
            $this->createEasyMailingOrderFromCart($cart);
        } else {
            $this->updateEasyMailingOrderFromCart($cart);
        }

		$this->cartUpdatedCalled = true;

    }

	/**
	 * Listener para el Checkout de Bloques de WooCommerce.
	 *
	 * Se dispara desde la Store API (`woocommerce_store_api_checkout_update_order_from_request`)
	 * cada vez que el front actualiza el borrador (`wc-checkout-draft`) con nuevos
	 * datos (email, direcciones, etc.). En ese punto el $order ya tiene billing_email
	 * y line items, por lo que es suficiente para crear/actualizar el cart en Easymailing
	 * tanto para guest como para logueado.
	 */
	public function blockCheckoutUpdated(\WC_Order $order): void
	{
		$this->logManager->createLog(LogType::INFO, sprintf("[EM-DEBUG] blockCheckoutUpdated ENTER order=%d status=%s", $order->get_id(), $order->get_status()));

		// No usar is_admin(): este hook se dispara desde la Store API (REST).
		if ($this->isCurrentUserAdmin() || CartRebuildHook::isRebuildUrl()) {
			$this->logManager->createLog(LogType::INFO, "[EM-DEBUG] blockCheckoutUpdated SKIP admin/rebuild");
			return;
		}

		if ($this->blockCheckoutSyncedInRequest) {
			$this->logManager->createLog(LogType::INFO, "[EM-DEBUG] blockCheckoutUpdated SKIP already synced in request");
			return;
		}

		if ($order->get_status() !== 'checkout-draft') {
			$this->logManager->createLog(LogType::INFO, sprintf("[EM-DEBUG] blockCheckoutUpdated SKIP status=%s (not checkout-draft)", $order->get_status()));
			return;
		}

		$email = $order->get_billing_email();
		$this->logManager->createLog(LogType::INFO, sprintf("[EM-DEBUG] blockCheckoutUpdated email=%s", $email));

		if (empty($email) || !is_email($email)) {
			$this->logManager->createLog(LogType::INFO, "[EM-DEBUG] blockCheckoutUpdated SKIP no valid email");
			return;
		}

		$customerResourceId = $this->customerService->resolveByEmail($email, $order);
		if (!$customerResourceId) {
			return;
		}

		$cart = $this->getCart($customerResourceId);
		if (empty($cart)) {
			return;
		}

		$customOrderId = WC()->session ? WC()->session->get(self::SESSION_ORDER_RESOURCE_ID_NAME) : null;

		if (!$customOrderId) {
			$this->createEasyMailingOrderFromCart($cart);
		} else {
			$this->updateEasyMailingOrderFromCart($cart);
		}

		$this->blockCheckoutSyncedInRequest = true;
	}

	/**
	 * Listener temprano para el Checkout de Bloques.
	 *
	 * `woocommerce_store_api_cart_update_customer_from_request` se dispara cada vez
	 * que el Block Checkout llama a `/wc/store/v1/cart/update-customer`, que es en
	 * cuanto el usuario cambia cualquier campo de billing (incluido el email) tras
	 * ~1 s de debounce. Esto nos permite sincronizar el cart en Easymailing tan pronto
	 * como haya un email, sin esperar a que el usuario rellene country/postcode que
	 * es lo que requiere el hook posterior `...checkout_update_order_from_request`.
	 */
	public function cartCustomerUpdated(\WC_Customer $customer): void
	{
		$this->logManager->createLog(LogType::INFO, "[EM-DEBUG] cartCustomerUpdated ENTER");

		// No usar is_admin(): este hook se dispara desde la Store API (REST)
		// y desde admin-ajax.php en algunos setups. is_admin() devuelve true en
		// admin-ajax y bloquearía indebidamente el flujo.
		if ($this->isCurrentUserAdmin() || CartRebuildHook::isRebuildUrl()) {
			$this->logManager->createLog(LogType::INFO, "[EM-DEBUG] cartCustomerUpdated SKIP admin/rebuild");
			return;
		}

		if ($this->cartCustomerSyncedInRequest) {
			$this->logManager->createLog(LogType::INFO, "[EM-DEBUG] cartCustomerUpdated SKIP already synced in request");
			return;
		}

		$email = $customer->get_billing_email();
		$this->logManager->createLog(LogType::INFO, sprintf("[EM-DEBUG] cartCustomerUpdated email from customer=%s", $email));

		if (empty($email) || !is_email($email)) {
			$this->logManager->createLog(LogType::INFO, "[EM-DEBUG] cartCustomerUpdated SKIP no valid email");
			return;
		}

		if (!WC()->cart || WC()->cart->is_empty()) {
			return;
		}

		$customerData = [
			'firstname' => (string) $customer->get_billing_first_name(),
			'lastname'  => (string) $customer->get_billing_last_name(),
			'company'   => (string) $customer->get_billing_company(),
			'phone'     => (string) $customer->get_billing_phone(),
			'country'   => (string) $customer->get_billing_country(),
		];

		$customerResourceId = $this->customerService->resolveByEmail($email, null, $customerData);
		if (!$customerResourceId) {
			return;
		}

		$cart = $this->getCart($customerResourceId);
		if (empty($cart)) {
			return;
		}

		$customOrderId = WC()->session ? WC()->session->get(self::SESSION_ORDER_RESOURCE_ID_NAME) : null;

		if (!$customOrderId) {
			$this->createEasyMailingOrderFromCart($cart);
		} else {
			$this->updateEasyMailingOrderFromCart($cart);
		}

		$this->cartCustomerSyncedInRequest = true;
	}

	/**
	 * Listener para el Checkout clásico (shortcode) de WooCommerce.
	 *
	 * `woocommerce_checkout_update_order_review` se dispara en cada AJAX del checkout
	 * clásico, con el contenido del form serializado. Parseamos para obtener
	 * billing_email y, si está, creamos/actualizamos el cart en Easymailing para
	 * guests o logueados que aún no tenían sync.
	 */
	public function classicCheckoutUpdated($postedData): void
	{
		$this->logManager->createLog(LogType::INFO, "[EM-DEBUG] classicCheckoutUpdated ENTER");

		// No usar is_admin(): este hook se dispara dentro de un AJAX call de
		// WooCommerce (admin-ajax.php), donde is_admin() devuelve siempre true.
		if ($this->isCurrentUserAdmin() || CartRebuildHook::isRebuildUrl()) {
			$this->logManager->createLog(LogType::INFO, "[EM-DEBUG] classicCheckoutUpdated SKIP admin");
			return;
		}

		if ($this->classicCheckoutSyncedInRequest) {
			$this->logManager->createLog(LogType::INFO, "[EM-DEBUG] classicCheckoutUpdated SKIP already synced in request");
			return;
		}

		if (!is_string($postedData) || empty($postedData)) {
			return;
		}

		$fields = [];
		parse_str($postedData, $fields);

		$email = isset($fields['billing_email']) ? sanitize_email($fields['billing_email']) : '';
		if (empty($email) || !is_email($email)) {
			return;
		}

		if (!WC()->cart || WC()->cart->is_empty()) {
			return;
		}

		$customerData = [
			'firstname' => isset($fields['billing_first_name']) ? sanitize_text_field($fields['billing_first_name']) : '',
			'lastname'  => isset($fields['billing_last_name'])  ? sanitize_text_field($fields['billing_last_name'])  : '',
			'company'   => isset($fields['billing_company'])    ? sanitize_text_field($fields['billing_company'])    : '',
			'phone'     => isset($fields['billing_phone'])      ? sanitize_text_field($fields['billing_phone'])      : '',
			'country'   => isset($fields['billing_country'])    ? sanitize_text_field($fields['billing_country'])    : '',
		];

		$customerResourceId = $this->customerService->resolveByEmail($email, null, $customerData);
		if (!$customerResourceId) {
			return;
		}

		$cart = $this->getCart($customerResourceId);
		if (empty($cart)) {
			return;
		}

		$customOrderId = WC()->session ? WC()->session->get(self::SESSION_ORDER_RESOURCE_ID_NAME) : null;

		if (!$customOrderId) {
			$this->createEasyMailingOrderFromCart($cart);
		} else {
			$this->updateEasyMailingOrderFromCart($cart);
		}

		$this->classicCheckoutSyncedInRequest = true;
	}

	/**
	 * Handler AJAX que dispara el JS de checkout (easymailing_checkout_script.js)
	 * en cuanto detecta un email válido en el input. Se llama desde
	 * `wp_ajax[_nopriv]_easymailing_track_checkout_email`.
	 *
	 * Resuelve el customer por email y sincroniza el cart actual de WooCommerce
	 * con Easymailing. Es redundante con los hooks de Store API y
	 * `woocommerce_checkout_update_order_review`, pero permite capturar el email
	 * en cuanto el campo pierde foco sin esperar al debounce interno del Block
	 * Checkout. El primer canal que llegue crea el cart; los siguientes
	 * actualizan.
	 *
	 * Mutex anti-duplicados: usamos un transient como lock por email. Si dos
	 * requests llegan en paralelo (autofill, doble pestaña, refresh), solo la
	 * primera ejecuta el create/update en Easymailing y las demás salen con
	 * skipped=lock_held. El TTL es corto (10s) para que un fallo del proceso
	 * que no llegue a delete_transient no deje el lock huérfano para siempre.
	 */
	public function ajaxTrackCheckoutEmail(): void
	{
		$this->logManager->createLog(LogType::INFO, "[EM-DEBUG] ajaxTrackCheckoutEmail ENTER");

		check_ajax_referer('easymailing-checkout-tracker');

		// No usar shouldSkipProcessing() aquí: incluye is_admin() y todo AJAX
		// hacia admin-ajax.php ejecuta con is_admin()=true aunque venga del front.
		if ($this->isCurrentUserAdmin()) {
			$this->logManager->createLog(LogType::INFO, "[EM-DEBUG] ajaxTrackCheckoutEmail SKIP admin user");
			wp_send_json_success(['skipped' => 'admin_user']);
		}

		$email = !empty($_GET['email']) ? sanitize_email(wp_unslash($_GET['email'])) : '';
		if (empty($email) || !is_email($email)) {
			$this->logManager->createLog(LogType::WARNING, sprintf("[EM-DEBUG] ajaxTrackCheckoutEmail INVALID email: %s", $email));
			wp_send_json_error(['error' => 'invalid_email'], 400);
		}

		$this->logManager->createLog(LogType::INFO, sprintf("[EM-DEBUG] ajaxTrackCheckoutEmail email=%s", $email));

		if (!function_exists('WC') || !WC()->cart || WC()->cart->is_empty()) {
			$this->logManager->createLog(LogType::INFO, "[EM-DEBUG] ajaxTrackCheckoutEmail SKIP cart empty or WC unavailable");
			wp_send_json_success(['skipped' => 'empty_cart']);
		}

		$lockKey = 'em_cart_lock_' . md5(strtolower($email));
		if (get_transient($lockKey) !== false) {
			$this->logManager->createLog(LogType::INFO, sprintf("[EM-DEBUG] ajaxTrackCheckoutEmail SKIP lock held for %s", $email));
			wp_send_json_success(['skipped' => 'lock_held']);
		}
		set_transient($lockKey, 1, 10);

		try {
			$customerResourceId = $this->customerService->resolveByEmail($email);
			if (!$customerResourceId) {
				$this->logManager->createLog(LogType::ERROR, sprintf("[EM-DEBUG] ajaxTrackCheckoutEmail customer resolve FAILED for %s", $email));
				wp_send_json_error(['error' => 'customer_resolve_failed'], 502);
			}

			$this->logManager->createLog(LogType::INFO, sprintf("[EM-DEBUG] ajaxTrackCheckoutEmail customerResourceId=%s", $customerResourceId));

			$cart = $this->getCart($customerResourceId);
			if (empty($cart)) {
				$this->logManager->createLog(LogType::INFO, "[EM-DEBUG] ajaxTrackCheckoutEmail SKIP getCart returned empty");
				wp_send_json_success(['skipped' => 'empty_body']);
			}

			$customOrderId = WC()->session ? WC()->session->get(self::SESSION_ORDER_RESOURCE_ID_NAME) : null;

			if (!$customOrderId) {
				$this->logManager->createLog(LogType::INFO, "[EM-DEBUG] ajaxTrackCheckoutEmail CREATE cart in Easymailing");
				$this->createEasyMailingOrderFromCart($cart);
			} else {
				$this->logManager->createLog(LogType::INFO, sprintf("[EM-DEBUG] ajaxTrackCheckoutEmail UPDATE cart %s in Easymailing", $customOrderId));
				$this->updateEasyMailingOrderFromCart($cart);
			}

			wp_send_json_success(['ok' => true]);
		} finally {
			delete_transient($lockKey);
		}
	}

	/**
	 * Usado solo por `cartUpdated()`, que se engancha a hooks del cart que sí
	 * pueden dispararse desde admin real (p. ej. añadir al cart desde la UI
	 * de admin). Los flujos nuevos (cartCustomerUpdated / blockCheckoutUpdated /
	 * classicCheckoutUpdated / ajaxTrackCheckoutEmail) NO usan este método
	 * porque se ejecutan en contextos donde is_admin() devuelve true de forma
	 * engañosa (AJAX / REST).
	 */
    private function shouldSkipProcessing(): bool
    {
        return is_admin() || $this->isCurrentUserAdmin() || CartRebuildHook::isRebuildUrl();
    }

    private function isCurrentUserAdmin(): bool
    {
        if (!is_user_logged_in()) {
            return false;
        }
        $currentUser = wp_get_current_user();
        return in_array('administrator', $currentUser->roles);
    }

	/**
	 * Resuelve el customer resource id desde el contexto del carrito.
	 *
	 * Para logueados sincronizados: usa el meta `_easymailing_resource_id` (ruta rápida,
	 * idéntica al comportamiento previo). Si no lo tiene, intenta resolver por email.
	 *
	 * Para guests: intenta obtener el email desde `WC()->customer->get_billing_email()`
	 * (que sí se rellena cuando el front Block Checkout actualiza la billing address
	 * vía Store API) y lo resuelve contra Easymailing.
	 */
	private function resolveCustomerFromCart(): ?string
	{
		if (is_user_logged_in()) {
			$currentUser = wp_get_current_user();
			$customerResourceId = get_user_meta($currentUser->ID, MetadataHelper::getResourceId(), true);
			if ($customerResourceId) {
				return $customerResourceId;
			}

			if (!empty($currentUser->user_email)) {
				return $this->customerService->resolveByEmail($currentUser->user_email);
			}

			return null;
		}

		$email = '';
		if (function_exists('WC') && WC()->customer) {
			$email = WC()->customer->get_billing_email();
		}

		if (empty($email) || !is_email($email)) {
			return null;
		}

		return $this->customerService->resolveByEmail($email);
	}


    private function createEasyMailingOrderFromCart($cart): void
    {
	    $campaignHash = isset($_COOKIE[CampaignHashHook::CAMPAIGN_HASH_COOKIE])
		    ? sanitize_text_field($_COOKIE[CampaignHashHook::CAMPAIGN_HASH_COOKIE])
		    : null;

        try {
	        $url = sprintf("/stores/%s/orders", $this->config->getShopId());
            $this->apiClient->createOrder($url, $cart);
            WC()->session->set(self::SESSION_ORDER_RESOURCE_ID_NAME, $cart['resource_id']);
            WC()->session->set(self::SESSION_CART_CUSTOMER_RESOURCE_ID_NAME, Api::extractUuid($cart['customer']));

			if($campaignHash){
				WC()->session->set(self::SESSION_HASH_NAME, $campaignHash);
			}

        } catch (\Exception $e) {
            WC()->session->__unset(self::SESSION_ORDER_RESOURCE_ID_NAME);
            WC()->session->__unset(self::SESSION_CART_CUSTOMER_RESOURCE_ID_NAME);

	        if($campaignHash){
		        WC()->session->__unset(self::SESSION_HASH_NAME, $campaignHash);
	        }
			$this->logManager->createLog(LogType::ERROR, sprintf("Error in create order: %s", $e->getMessage()));
        }
    }

    private function updateEasyMailingOrderFromCart($cart) : void
    {
	    $campaignHash = isset($_COOKIE[CampaignHashHook::CAMPAIGN_HASH_COOKIE])
		    ? sanitize_text_field($_COOKIE[CampaignHashHook::CAMPAIGN_HASH_COOKIE])
		    : null;

        try {
            $url = "/stores/" . $this->config->getShopId() . "/orders/" . $cart['resource_id'];
            $this->apiClient->updateOrder($url, $cart);
            WC()->session->set(self::SESSION_ORDER_RESOURCE_ID_NAME, $cart['resource_id']);
            WC()->session->set(self::SESSION_CART_CUSTOMER_RESOURCE_ID_NAME, Api::extractUuid($cart['customer']));
	        if($campaignHash){
		        WC()->session->set(self::SESSION_HASH_NAME, $campaignHash);
	        }
        } catch (\Exception $e) {
            WC()->session->__unset(self::SESSION_ORDER_RESOURCE_ID_NAME);
            WC()->session->__unset(self::SESSION_CART_CUSTOMER_RESOURCE_ID_NAME);
	        if($campaignHash){
		        WC()->session->__unset(self::SESSION_HASH_NAME, $campaignHash);
	        }
			$this->logManager->createLog(LogType::ERROR, sprintf("Error in update order: %s", $e->getMessage()));
        }
    }

    private function getCart($customerResourceId): array
    {
        // Obtener el carrito completo
        if (WC()->cart->is_empty())
            return [];

        // Si el customer asociado al cart en sesión cambió (típicamente cambio
        // de email en el checkout), descartamos el order_resource_id previo para
        // forzar la creación de un cart nuevo en lugar de reasignar el existente
        // al nuevo customer en Easymailing.
        $lastCartCustomerResourceId = WC()->session->get(self::SESSION_CART_CUSTOMER_RESOURCE_ID_NAME);
        if ($lastCartCustomerResourceId && $lastCartCustomerResourceId !== $customerResourceId) {
            WC()->session->__unset(self::SESSION_ORDER_RESOURCE_ID_NAME);
            WC()->session->__unset(self::SESSION_HASH_NAME);
        }

        $emSessionOrderId = WC()->session->get(self::SESSION_ORDER_RESOURCE_ID_NAME);
        $resourceId = $emSessionOrderId ? $emSessionOrderId : wp_generate_uuid4();
        $checkoutUrl = $this->buildRecoveryCheckoutUrl();
        WC()->cart->calculate_totals();
        $orderTotal = Api::convertEurToCents(WC()->cart->get_cart_contents_total());
        $currencyCode = get_woocommerce_currency();

        $cartItems = $this->getCartItems();

        $cartBody = [
            'resource_id' =>  $resourceId,
            'currency' => $currencyCode,
            'order_total' => $orderTotal,
            'status' => "cart",
            'checkout_url' => $checkoutUrl,
            'order_items' => $cartItems,
            'customer' =>   "/stores" . "/" . $this->config->getShopId() . "/customers" . "/" . $customerResourceId,
        ];

	    $campaignHash = isset($_COOKIE[CampaignHashHook::CAMPAIGN_HASH_COOKIE])
		    ? sanitize_text_field($_COOKIE[CampaignHashHook::CAMPAIGN_HASH_COOKIE])
		    : null;
	    if($campaignHash){
		    $url = sprintf("/campaigns?hash=%s", $campaignHash);
			$campaign = $this->apiClient->getCampaignByHash($url);
			if($campaign){
				$cartBody['campaign_hash'] = $campaignHash;
			}
	    }

        return $cartBody;
    }



	/**
	 * Genera un checkout URL de recovery con los productos del carrito embebidos
	 * en base64 como query param. Funciona cross-device: cuando el usuario clica
	 * el link desde el email de carrito abandonado, CartRebuildHook reconstruye
	 * los productos sin depender de la sesión de WooCommerce.
	 *
	 * Si por cualquier motivo no se puede generar el payload (carrito vacío,
	 * fallo de json_encode), devuelve el checkout URL estándar como fallback.
	 */
	private function buildRecoveryCheckoutUrl(): string
	{
		$fallback = wc_get_checkout_url();

		if (!WC()->cart || WC()->cart->is_empty()) {
			return $fallback;
		}

		$products = [];
		foreach (WC()->cart->get_cart() as $cart_item) {
			$products[] = [
				'product_id'   => (int) ($cart_item['product_id'] ?? 0),
				'quantity'     => (int) ($cart_item['quantity'] ?? 1),
				'variation_id' => (int) ($cart_item['variation_id'] ?? 0),
				'variation'    => is_array($cart_item['variation'] ?? null) ? $cart_item['variation'] : [],
			];
		}

		if (empty($products)) {
			return $fallback;
		}

		$encoded = wp_json_encode(['products' => $products]);
		if ($encoded === false) {
			return $fallback;
		}

		return add_query_arg([
			CartRebuildHook::ACTION_PARAM  => CartRebuildHook::ACTION_VALUE,
			CartRebuildHook::PAYLOAD_PARAM => base64_encode($encoded),
		], home_url('/'));
	}


	private function getCartItems(): array
	{
		$cartItems = [];
		// Verificar si el carrito no está vacío
		if (!WC()->cart->is_empty()) {
			// Obtener los artículos del carrito
			$cart = WC()->cart->get_cart();

			// Recorrer cada artículo en el carrito
			foreach ($cart as $cart_item) {
				// Obtener el ID del producto y los metadatos personalizados
				$productId = $cart_item['product_id'];
				$product = wc_get_product($productId);

				$emProductId = get_post_meta($productId, MetadataHelper::getResourceId(), true);

				try{
					$productIri = "/stores" . "/" . $this->config->getShopId() . "/products" . "/" . $emProductId;
					$this->apiClient->getProduct($productIri);
				}catch(\Exception $e){
					if ($e instanceof \Easymailing\App\Api\Exception\NotFoundException) {
						$this->productHooks->synchronizeProduct($productId);
					} else{
						throw new \Exception($e);
					}
				}

				// Validar que se haya obtenido el producto
				if (!$product || empty($emProductId)) {
					continue; // Si no existe el producto o emProductId, saltar al siguiente ítem
				}

				// Manejar productos variables y simples
				$price = (float) $product->get_price();
				$variationId = $cart_item['variation_id'];

				if ($product->is_type('variable') && !empty($variationId)) {
					// Producto variable: obtener ID de la variación
					$emVariationId = get_post_meta($variationId, MetadataHelper::getResourceId(), true) ?: $variationId;
				} else {
					// Producto simple o sin variación
					$emVariationId = get_post_meta($productId, MetadataHelper::getVariantResourceId(), true);
				}

				// Verificar que se haya obtenido la variación o el ID del producto
				if (empty($emVariationId)) {
					continue; // Saltar si no existe la variación
				}

				// Convertir el precio a céntimos y calcular el total por cantidad
				$totalPriceCents = Api::convertEurToCents($price * $cart_item['quantity']);

				// Crear el array de ítem del carrito
				$cartItems[] = [
					'quantity' => $cart_item['quantity'],
					'price' => $totalPriceCents,
					'variant' => "/stores/" . $this->config->getShopId() . "/products/" . $emProductId . "/variants/" . $emVariationId,
				];
			}
		}

		return $cartItems;
	}



}
