<?php

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

use Easymailing\App\Core\Log\LogManager;
use Easymailing\App\Core\Provider\Woocommerce\Hooks\CustomerHooks;
use Easymailing\App\Core\Provider\Woocommerce\Model\LogType;
use Easymailing\App\Core\Provider\Woocommerce\Service\CustomerService;
use Easymailing\App\Core\Provider\Woocommerce\Service\MetadataHelper;

/**
 * Integra los treatment purposes / custom fields de Easymailing dentro del
 * Checkout de Bloques de WooCommerce usando la Additional Checkout Fields API
 * (`woocommerce_register_additional_checkout_field`, disponible desde WC 8.9).
 *
 * El Classic Checkout ya pinta los checkboxes vía el filter
 * `woocommerce_checkout_fields` en CustomerHooks::registerCheckoutFields(). Ese
 * filter no se dispara en el Block Checkout, así que aquí replicamos la misma
 * lista de campos usando la API específica de bloques. Los valores marcados
 * por el usuario se convierten al mismo formato JSON que usa el resto del
 * plugin (MetadataHelper::getTreatmentPurposes), para que OrderHooks y
 * CustomerService los lean sin cambios.
 */
class BlockCheckoutFieldsExtension
{
	const FIELD_NAMESPACE = 'easymailing';
	const META_PREFIX = '_wc_other/';

	private $customerHooks;
	private $customerService;
	private $logManager;

	public function __construct(
		CustomerHooks $customerHooks,
		CustomerService $customerService,
		LogManager $logManager
	) {
		$this->customerHooks = $customerHooks;
		$this->customerService = $customerService;
		$this->logManager = $logManager;
	}

	public function register(): void
	{
		add_action('woocommerce_blocks_loaded', [$this, 'registerFields']);
		add_action('woocommerce_store_api_checkout_update_order_from_request', [$this, 'persistValues'], 30, 2);
	}

	public function registerFields(): void
	{
		if (!function_exists('woocommerce_register_additional_checkout_field')) {
			return;
		}

		try {
			$fields = $this->customerHooks->getVisibleFields();
		} catch (\Exception $e) {
			$this->logManager->createLog(LogType::ERROR, sprintf("BlockCheckoutFieldsExtension: cannot resolve fields: %s", $e->getMessage()));
			return;
		}

		if (empty($fields)) {
			return;
		}

		foreach ($fields as $field) {
			try {
				$fieldId = self::FIELD_NAMESPACE . '/' . $this->sanitizeFieldKey($field['id']);
				woocommerce_register_additional_checkout_field([
					'id'       => $fieldId,
					'label'    => wp_strip_all_tags($field['title']),
					'location' => 'contact',
					'type'     => 'checkbox',
					'required' => false,
				]);
			} catch (\Exception $e) {
				$this->logManager->createLog(LogType::WARNING, sprintf("BlockCheckoutFieldsExtension: cannot register field %s: %s", $field['id'] ?? '', $e->getMessage()));
			}
		}
	}

	/**
	 * Se engancha a `woocommerce_store_api_checkout_update_order_from_request`
	 * con prioridad 30 (posterior a CartHooks::blockCheckoutUpdated). En ese
	 * punto WC Blocks ya ha persistido los valores de los checkboxes como meta
	 * del order con clave `_wc_other/easymailing/<field_id>`. Los leemos, los
	 * convertimos al formato JSON esperado por el plugin y actualizamos
	 * `MetadataHelper::getTreatmentPurposes()` tanto en post_meta como en
	 * user_meta (si hay user asociado).
	 */
	public function persistValues(\WC_Order $order, \WP_REST_Request $request): void
	{
		try {
			$fields = $this->customerHooks->getVisibleFields();
		} catch (\Exception $e) {
			return;
		}

		if (empty($fields)) {
			return;
		}

		$collected = [];
		foreach ($fields as $field) {
			$metaKey = self::META_PREFIX . self::FIELD_NAMESPACE . '/' . $this->sanitizeFieldKey($field['id']);
			$raw = $order->get_meta($metaKey);
			$value = ($raw === '1' || $raw === 1 || $raw === true);

			$collected[] = [
				'type'  => $field['type'],
				'id'    => $field['id'],
				'title' => $field['title'],
				'value' => $value,
			];
		}

		$json = json_encode(
			$collected,
			JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_HEX_APOS | JSON_UNESCAPED_UNICODE
		);

		update_post_meta($order->get_id(), MetadataHelper::getTreatmentPurposes(), $json);

		$userId = $order->get_user_id();
		if ($userId) {
			update_user_meta($userId, MetadataHelper::getTreatmentPurposes(), $json);

			try {
				$this->customerService->processCustomer($userId);
			} catch (\Exception $e) {
				$this->logManager->createLog(LogType::ERROR, sprintf("BlockCheckoutFieldsExtension: cannot process customer: %s", $e->getMessage()));
			}
		}
	}

	/**
	 * WooCommerce exige que tanto namespace como key del id sigan el patrón
	 * `[a-z][a-z0-9_\-]*`. Los UUIDs de los treatment purposes son minúsculas
	 * con guiones, así que suelen pasar tal cual, pero saneamos por seguridad.
	 */
	private function sanitizeFieldKey(string $id): string
	{
		$sanitized = strtolower($id);
		$sanitized = preg_replace('/[^a-z0-9_\-]/', '_', $sanitized);
		if (!preg_match('/^[a-z]/', $sanitized)) {
			$sanitized = 'f_' . $sanitized;
		}
		return $sanitized;
	}
}
