<?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\Templating\Templating;
use Easymailing\App\Core\Transient\FlashBag;
use Easymailing\App\Repository\ConfigRepository;

class CustomerHooks
{

	private $config;
	private $audience;
	private $customerService;
	private $flashBag;
	private $logManager;

	public function __construct(ConfigRepository $configRepository, CustomerService $customerService, FlashBag $flashBag, LogManager $logManager)
	{
		$this->config          = $configRepository->getSynchronizationConfig();
		$this->audience        = $configRepository->getAudienceFromSynchronizationConfig();
		$this->customerService = $customerService;
		$this->flashBag        = $flashBag;
		$this->logManager      = $logManager;
	}


	public function synchronizeCustomerAdmin(int $userId): void
	{
		$this->logManager->createLog(LogType::INFO, sprintf("synchronizeCustomerAdmin USER ID: %s", $userId));
		try{
			$this->customerService->processCustomer($userId);
			$this->flashBag->add('success', __("Cliente sincronizado en Easymailing correctamente", 'easymailing'));
		}catch(\Exception $e){
			$this->flashBag->add('error', __("Ocurrió un error al sincronizar el cliente", 'easymailing'));
			$this->logManager->createLog(LogType::ERROR, sprintf("Error in create customer: %s", $e->getMessage()));

		}

	}

	/**
	 * Añade los campos visibles al checkout de WooCommerce.
	 */
	public function registerCheckoutFields(array $checkoutFields): array
	{
		if( ! $this->config->getAudience()){
			return $checkoutFields;
		}

		try{
			$fields = $this->getVisibleFields();
			if(empty($fields)){
				return $checkoutFields;
			}

			$userId = get_current_user_id();

			foreach($fields as $field){
				$fieldId = MetadataHelper::SYNCHRO_META_PREFIX . $field['id'];

				if($userId){
					$json = get_user_meta($userId, MetadataHelper::getTreatmentPurposes(), true);
					$data = $this->getSavedDataFromFieldId($json, $field['id']);

					$isChecked = $data ? $data['value'] : false;
				}else{
					$isChecked = $field['status'] === 'checked';
				}

				$checkoutFields['order'][$fieldId] = [
					'type'     => 'checkbox',
					'label'    => $field['title'],
					'required' => false,
					'default'  => $isChecked,
					'class'    => ['form-row-wide'],
				];
			}
		}catch(\Exception $e){
			$this->logManager->createLog(LogType::ERROR, sprintf("Error in register checkout fields: %s", $e->getMessage()));
		}

		return $checkoutFields;
	}

	/**
	 * Añade los mismos campos en el formulario de registro (Mi Cuenta).
	 */
	public function addFieldsToRegistrationForm()
	{
		if( ! $this->config->getAudience()){
			return;
		}

		try{
			$fields = $this->getVisibleFields();
			if(empty($fields)){
				return;
			}

			foreach($fields as $field){
				$fieldId = MetadataHelper::SYNCHRO_META_PREFIX . $field['id'];
				$isChecked = $field['status'] === 'checked';

				woocommerce_form_field(
					$fieldId,
					[
						'type'        => 'checkbox',
						'required'    => false,
						'label'       => wp_kses_post($field['title']),
						'custom_attributes' => array(
							'value' => '1', // Establece el valor del checkbox.
						),
						'default'           => $isChecked ? '1' : '',
					]
				);

			}
		}catch(\Exception $e){
			$this->logManager->createLog(LogType::ERROR, sprintf("Error in add fields to registration form: %s", $e->getMessage()));
		}
	}

	/**
	 * Añade campos al formulario de editar cuenta
	 */
	public function addFieldsToEditAccountForm(): void
	{
		if( ! $this->config->getAudience()){
			return;
		}

		try{
			$fields = $this->getVisibleFields();
			if(empty($fields)){
				return;
			}

			$userId = get_current_user_id();
			$json   = get_user_meta($userId, MetadataHelper::getTreatmentPurposes(), true);

			foreach($fields as $field){
				$fieldId   = MetadataHelper::SYNCHRO_META_PREFIX . $field['id'];
				$data      = $this->getSavedDataFromFieldId($json, $field['id']);
				$isChecked = $data ? $data['value'] : false;

				woocommerce_form_field(
					$fieldId,
					[
						'type'        => 'checkbox',
						'required'    => false,
						'label'       => wp_kses_post($field['title']),
						'custom_attributes' => array(
							'value' => '1', // Establece el valor del checkbox.
						),
						'default'           => $isChecked ? '1' : '',
					]
				);

			}
		}catch(\Exception $e){
			$this->logManager->createLog(LogType::ERROR, sprintf("Error adding fields to account form: %s", $e->getMessage()));
		}
	}

	/**
	 * Recopila los campos que están visibles y han sido marcados (o no) en $_POST.
	 * Devuelve un array con la estructura [ [type, id, title, value], ... ].
	 */
	private function collectCheckedFields(): array
	{
		// 1) Obtener la lista de campos visibles
		$fields        = $this->getVisibleFields();
		$collectedData = [];

		// 2) Para cada campo visible, revisamos si el usuario lo marcó
		foreach($fields as $field){
			$fieldKey = MetadataHelper::SYNCHRO_META_PREFIX . $field['id'];

			// Está marcado si está en $_POST y es "checked"
			$isChecked = (
				isset($_POST[$fieldKey])
				&& sanitize_text_field($_POST[$fieldKey]) === '1'
			);

			$collectedData[] = [
				'type'  => $field['type'], // 'treatment_purpose' o 'custom_field'
				'id'    => $field['id'],
				'title' => $field['title'],
				'value' => $isChecked,
			];
		}

		return $collectedData;
	}

	/**
	 * Guarda los campos seleccionados en el Checkout.
	 */
	public function saveCheckoutFields($orderId)
	{

		try {
			$order  = wc_get_order($orderId);
			$userId = $order ? $order->get_user_id() : 0; // 0 si invitado

			$this->logManager->createLog(LogType::INFO, sprintf("saveCheckoutFields USER ID: %s", $userId));

			// 1) Recopilar campos que el usuario marcó
			$collectedData = $this->collectCheckedFields();

			// 2) Guardamos todo en un solo campo JSON en el pedido
			update_post_meta(
				$orderId,
				MetadataHelper::getTreatmentPurposes(),
				json_encode($collectedData,  JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_HEX_APOS | JSON_UNESCAPED_UNICODE)
			);

			// 3) Si el usuario está logueado, guardamos también en su perfil
			if($userId){
				update_user_meta(
					$userId,
					MetadataHelper::getTreatmentPurposes(),
					json_encode($collectedData,  JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_HEX_APOS | JSON_UNESCAPED_UNICODE)
				);

				$this->customerService->processCustomer($userId);
			}
		}catch(\Exception $e){
			$this->logManager->createLog(LogType::ERROR, sprintf("Error in save checkout fields: %s", $e->getMessage()));
		}

	}

	/**
	 * Guarda los campos seleccionados en el registro
	 */
	public function saveRegistrationFields($userId)
	{
		try {
			$collectedData = $this->collectCheckedFields();
			update_user_meta(
				$userId,
				MetadataHelper::getTreatmentPurposes(),
				json_encode($collectedData,  JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_HEX_APOS | JSON_UNESCAPED_UNICODE)
			);

			$this->customerService->processCustomer($userId);
		}catch(\Exception $e){
			$this->logManager->createLog(LogType::ERROR, sprintf("Error in save registration fields: %s", $e->getMessage()));
		}
	}

	/**
	 * Guarda los campos seleccionados en editar cuenta
	 */
	public function saveAccountEditFields(int $userId): void
	{

		try{
			$collectedData = $this->collectCheckedFields();
			update_user_meta(
				$userId,
				MetadataHelper::getTreatmentPurposes(),
				json_encode($collectedData,  JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_HEX_APOS | JSON_UNESCAPED_UNICODE)
			);

			$this->customerService->processCustomer($userId);
		}catch(\Exception $e){
			$this->logManager->createLog(LogType::ERROR, sprintf("Error in save account edit fields: %s", $e->getMessage()));
		}

	}

	private function getSavedDataFromFieldId(string $json, string $resourceId): ?array
	{
		$data = json_decode($json, true);

		if(empty($data)){
			return null;
		}

		foreach($data as $item){
			if($item['id'] === $resourceId){
				return $item;
			}
		}

		return null;

	}


	/**
	 * Devuelve la lista de campos "visibles" (excluyendo hidden) según la
	 * config y la API.
	 *
	 * Preferencia: Treatment Purposes. Si hay TPs en la config + API, usamos esos.
	 * Si no, hacemos fallback a listFields (custom fields).
	 *
	 * Es público porque la extensión de Block Checkout
	 * (BlockCheckoutFieldsExtension) reutiliza esta misma lista para registrar
	 * los mismos checkboxes en el Checkout de Bloques vía
	 * `woocommerce_register_additional_checkout_field`.
	 */
	public function getVisibleFields(): array
	{
		$tpConfig   = $this->config->getTreatmentPurposes() ?: [];
		$listConfig = $this->config->getBooleanListFields() ?: [];

		// 1) Preferencia TPs
		if( ! empty($tpConfig)){
			$tpFields = $this->buildTreatmentPurposes($tpConfig);
			if( ! empty($tpFields)){
				return $tpFields;
			}
		}

		// 2) Fallback Custom Fields
		if( ! empty($listConfig)){
			$cfFields = $this->buildCustomFields($listConfig);

			return $cfFields;
		}

		// 3) Nada
		return [];
	}

	/**
	 * Crea la lista de Treatment Purposes desde la API filtrando:
	 * - Solo IDs presentes en la config
	 * - Excluimos hidden
	 */
	private function buildTreatmentPurposes(array $tpConfig): array
	{
		try{

			if(empty($this->audience->listGdpr->treatmentPurposes)){
				return [];
			}

			$apiTPs = $this->audience->listGdpr->treatmentPurposes;
			$locale = $this->config->getLanguage();

			$fields = [];

			foreach($tpConfig as $tpId => $status){
				// Saltamos si es 'hidden'
				if($status === 'hidden'){
					continue;
				}

				// Buscar el TP en la respuesta de la API
				$found  = array_filter($apiTPs, function ($tp) use ($tpId){
					return isset($tp->id) && $tp->id === $tpId;
				});
				$tpItem = reset($found);

				if($tpItem){
					// Buscar traducción
					$translation = $this->getTranslation($tpItem->translations, $locale);

					$fields[] = [
						'type'   => 'treatment_purpose',
						'id'     => $tpId,
						'title'  => $translation->title,
						'status' => $status, // 'checked' / 'unchecked'
					];
				}
			}

			return $fields;
		}catch(\Exception $e){
			$this->logManager->createLog(LogType::ERROR, sprintf("Error building TPs: %s", $e->getMessage()));
			return [];
		}
	}

	/**
	 * Crea la lista de Custom Fields desde la API filtrando:
	 * - Solo IDs presentes en la config
	 * - Excluimos hidden
	 */
	private function buildCustomFields(array $listConfig): array
	{
		try{
			$listFields = $this->audience->listFields;
			$locale     = $this->config->getLanguage();

			if(empty($listFields)){
				return [];
			}

			$fields = [];
			foreach($listConfig as $fieldId => $status){
				if($status === 'hidden'){
					continue;
				}
				$found = array_filter($listFields, function ($item) use ($fieldId){
					return isset($item->id) && $item->id === $fieldId;
				});
				$cf    = reset($found);

				if($cf){
					$translation = $this->getTranslation($cf->translations, $locale);

					$fields[] = [
						'type'   => 'custom_field',
						'id'     => $fieldId,
						'title'  => $translation->label,
						'status' => $status,
					];
				}
			}

			return $fields;
		}catch(\Exception $e){
			$this->logManager->createLog(LogType::ERROR, sprintf("Error building custom fields: %s", $e->getMessage()));

			return [];
		}
	}

	/**
	 * Busca la traducción para el locale actual.
	 * Si no la encuentra, lanza excepción.
	 */
	private function getTranslation(array $translations, $locale)
	{
		foreach($translations as $t){
			if(isset($t->locale) && $t->locale === $locale){
				return $t;
			}
		}
		throw new \Exception("No translation found for locale: $locale");
	}


}
