<?php
namespace Easymailing\App\Core\Provider;

use Easymailing\App\Core\Application;
use Easymailing\App\Core\Provider\Woocommerce\Hooks\CampaignHashHook;
use Easymailing\App\Core\Provider\Woocommerce\Hooks\CartHooks;
use Easymailing\App\Core\Provider\Woocommerce\Hooks\CartRebuildHook;
use Easymailing\App\Core\Provider\Woocommerce\Hooks\CategoryHooks;
use Easymailing\App\Core\Provider\Woocommerce\Hooks\CustomerHooks;
use Easymailing\App\Core\Provider\Woocommerce\Hooks\DeleteHook;
use Easymailing\App\Core\Provider\Woocommerce\Hooks\OrderHooks;
use Easymailing\App\Core\Provider\Woocommerce\Hooks\ProductHooks;
use Easymailing\App\Core\Provider\Woocommerce\Hooks\SynchronizationHook;
use Easymailing\App\Core\Provider\Woocommerce\Model\LogType;
use Easymailing\App\Core\Provider\Woocommerce\Service\BatchEnqueueManager;
use Easymailing\App\Core\Provider\Woocommerce\Widgets\CategoryWidgets;
use Easymailing\App\Core\Provider\Woocommerce\Widgets\CustomerWidgets;
use Easymailing\App\Core\Provider\Woocommerce\Widgets\OrderWidgets;
use Easymailing\App\Core\Provider\Woocommerce\Widgets\ProductWidgets;
use Easymailing\App\Core\Provider\Woocommerce\Widgets\SynchronizationAction;

class WoocommerceHooksProvider
{

	private $application;

	public function __construct(Application $application)
	{
		$this->application = $application;
	}

	public function register()
	{
		$synchronizationConfig = $this->application->getContainer()->get('config_repository')->getSynchronizationConfig();
		$config = $this->application->getContainer()->get('config_repository')->getConfig();

		if ($config && $synchronizationConfig->getAppDomain() !== $config->getMySuscription()->domain) {
			return;
		}

		if (is_null($synchronizationConfig)) {
			return;
		}

		if (!$synchronizationConfig->getShopId() || !$synchronizationConfig->getAudience()) {
			return;
		}

		/** @var SynchronizationHook $synchronizationHook */
		$synchronizationHook = $this->application->getContainer()->get("synchronization_hook");
		$this->addLoggedAction(BatchEnqueueManager::SYNCHRONIZATION_BACKGROUND_TASK, [$synchronizationHook, "startSynchronizationInBackground"], 10, 0);
		$this->addLoggedAction(BatchEnqueueManager::SYNCHRONIZATION_CHECK_BACKGROUND_TASK, [$synchronizationHook, "checkSynchronizationInBackground"], 10, 0);

		$flashBag = $this->application->getContainer()->get("flash_bag");
		add_action('admin_notices', [$flashBag, 'adminNotices']);

		/** @var CustomerHooks $customerHooks */
		$customerHooks = $this->application->getContainer()->get("customer_hooks");

		// Campos en el checkout
		$this->addLoggedFilter('woocommerce_checkout_fields', [$customerHooks, 'registerCheckoutFields'], 10, 1);
		$this->addLoggedAction('woocommerce_checkout_update_order_meta', [$customerHooks, 'saveCheckoutFields'], 10, 1);

		// Campos en el formulario de registro
		$this->addLoggedAction('woocommerce_register_form', [$customerHooks, 'addFieldsToRegistrationForm'], 10);
		$this->addLoggedAction('woocommerce_created_customer', [$customerHooks, 'saveRegistrationFields'], 10, 1);

		// Campos en editar cuenta
		$this->addLoggedAction('woocommerce_edit_account_form', [$customerHooks, 'addFieldsToEditAccountForm'], 10);
		$this->addLoggedAction('woocommerce_save_account_details', [$customerHooks, 'saveAccountEditFields'], 10);


		/** @var ProductHooks $productHooks */
		$productHooks = $this->application->getContainer()->get("product_hooks");
		$this->addLoggedAction("save_post", [$productHooks, 'productSaved'], 10, 1);

		/** @var CategoryHooks $categoryHooks */
		$categoryHooks = $this->application->getContainer()->get("category_hooks");
		$this->addLoggedAction("created_product_cat", [$categoryHooks, 'createCategory'], 10, 1);
		$this->addLoggedAction('edited_product_cat', [$categoryHooks, 'updateCategory'], 10, 1);

		/** @var CampaignHashHook $campaignHashHook */
		$campaignHashHook = $this->application->getContainer()->get("campaign_hash_hook");
		add_action('woocommerce_load_cart_from_session', [$campaignHashHook, 'saveCampaignHash'], 10, 2);

		/** @var CartRebuildHook $cartRebuildHook */
		$cartRebuildHook = $this->application->getContainer()->get("cart_rebuild_hook");
		add_action('wp_loaded', [$cartRebuildHook, 'rebuildCart']);

		/** @var \Easymailing\App\Core\Provider\Woocommerce\Blocks\BlockCheckoutFieldsExtension $blockCheckoutFieldsExtension */
		$blockCheckoutFieldsExtension = $this->application->getContainer()->get("block_checkout_fields_extension");
		$blockCheckoutFieldsExtension->register();

		/** @var CartHooks $cartHooks */
		$cartHooks = $this->application->getContainer()->get("cart_hooks");
		$this->addLoggedAction('woocommerce_add_to_cart', [$cartHooks, 'cartUpdated'], 10, 6);
		$this->addLoggedAction('woocommerce_remove_cart_item', [$cartHooks, 'cartUpdated'], 10, 2);
		$this->addLoggedAction('woocommerce_after_cart_item_quantity_update', [$cartHooks, 'cartUpdated'], 10, 4);
		$this->addLoggedAction('woocommerce_store_api_cart_update_customer_from_request', [$cartHooks, 'cartCustomerUpdated'], 20, 1);
		$this->addLoggedAction('woocommerce_store_api_checkout_update_order_from_request', [$cartHooks, 'blockCheckoutUpdated'], 20, 1);
		$this->addLoggedAction('woocommerce_checkout_update_order_review', [$cartHooks, 'classicCheckoutUpdated'], 20, 1);

		add_action('wp_enqueue_scripts', [$this, 'enqueueCheckoutTracker']);
		add_action('wp_enqueue_scripts', [$this, 'enqueueCheckoutPhoneValidator']);
		add_action('wp_ajax_easymailing_track_checkout_email', [$cartHooks, 'ajaxTrackCheckoutEmail']);
		add_action('wp_ajax_nopriv_easymailing_track_checkout_email', [$cartHooks, 'ajaxTrackCheckoutEmail']);

		/** @var OrderHooks $orderHooks */
		$orderHooks = $this->application->getContainer()->get("order_hooks");
		$this->addLoggedAction('woocommerce_checkout_order_created', [$orderHooks, 'orderCreated'], 10, 1);
//		$this->addLoggedAction('woocommerce_payment_complete', [$orderHooks, 'synchronizeStatus'], 10, 1);
		$this->addLoggedAction('woocommerce_order_status_changed', [$orderHooks, 'synchronizeStatus'], 10, 4);


		/** @var DeleteHook $deleteHook */
		$deleteHook = $this->application->getContainer()->get("delete_hook");
		$this->addLoggedAction('wp_trash_post', [$deleteHook, 'onDeletePost'], 1, 1);
		$this->addLoggedAction('woocommerce_trash_order', [$deleteHook, 'deleteOrder'], 1, 1);
		$this->addLoggedAction('delete_user', [$deleteHook, 'deleteUser'], 1, 1);

		/** @var SynchronizationAction $synchronizationAction */
		$synchronizationAction = $this->application->getContainer()->get('synchronization_action');
		add_action('post_row_actions', [$synchronizationAction, 'postActions'], 10, 2);
		add_action('user_row_actions', [$synchronizationAction, 'userActions'], 10, 2);
		add_action('product_cat_row_actions', [$synchronizationAction, 'categoryActions'], 10, 2);

		/** @var ProductWidgets $productWidgets */
		$productWidgets = $this->application->getContainer()->get('product_widgets');
		add_action('add_meta_boxes', [$productWidgets, 'addWidgets'], 10);
		add_filter('manage_edit-product_columns', [$productWidgets, 'addSynchronizationColumn'], 10, 1);
		add_action('manage_product_posts_custom_column', [$productWidgets, 'showCustomProductColumnData'], 10, 2);

		/** @var CategoryWidgets $categoryWidgets */
		$categoryWidgets = $this->application->getContainer()->get('category_widgets');
		add_action('product_cat_edit_form_fields', [$categoryWidgets, 'addWidgets'], 10, 1);
		add_filter('manage_edit-product_cat_columns', [$categoryWidgets, 'addSynchronizationColumn'], 10, 1);
		add_action('manage_product_cat_custom_column', [$categoryWidgets, 'showCustomCategoryColumnData'], 10, 3);

		/** @var OrderWidgets $orderWidgets */
		$orderWidgets = $this->application->getContainer()->get('order_widgets');
		add_action('add_meta_boxes', [$orderWidgets, 'addWidgets'], 10);
//		add_action('woocommerce_admin_order_data_after_order_details', [$orderWidgets, 'addWidgets'], 10);

		add_filter('manage_woocommerce_page_wc-orders_columns', [$orderWidgets, 'addSynchronizationColumn'], 10, 1);
		add_action('manage_woocommerce_page_wc-orders_custom_column', [$orderWidgets, 'showCustomOrderColumnData'], 10, 2);

		/** @var CustomerWidgets $customerWidgets */
		$customerWidgets = $this->application->getContainer()->get('customer_widgets');
		add_action('edit_user_profile', [$customerWidgets, 'addWidgets'], 1, 1);
		add_action('show_user_profile', [$customerWidgets, 'addWidgets'], 1, 1);
		add_filter('manage_users_columns', [$customerWidgets, 'addColumn'], 10, 1);
		add_action('manage_users_custom_column', [$customerWidgets, 'showCustomCustomerColumnData'], 10, 3);
	}

	/**
	 * Encola el script de tracking del checkout solo cuando estamos en una página
	 * de checkout (classic o Block Checkout). El JS escucha el input de email y
	 * dispara AJAX a admin-ajax.php?action=easymailing_track_checkout_email en
	 * cuanto hay un email válido, sin depender del debounce del Block Checkout.
	 */
	public function enqueueCheckoutTracker(): void
	{
		$logManager = $this->application->getContainer()->get("log_manager");

		$isCheckoutFn = function_exists('is_checkout');
		$isCheckout   = $isCheckoutFn ? is_checkout() : false;
		$logManager->createLog(
			\Easymailing\App\Core\Provider\Woocommerce\Model\LogType::INFO,
			sprintf("[EM-DEBUG] enqueueCheckoutTracker fired. is_checkout() available=%s result=%s", $isCheckoutFn ? 'yes' : 'no', $isCheckout ? 'true' : 'false')
		);

		if (!$isCheckoutFn || !$isCheckout) {
			return;
		}

		$pluginUrl = $this->application->getConfigurations()['plugin_url'];
		$version = defined('EASYMAILING_OFFICIAL_VERSION') ? EASYMAILING_OFFICIAL_VERSION : '1.4';

		wp_register_script(
			'easymailing-checkout-tracker',
			$pluginUrl . 'assets/build/plugin/easymailing_checkout_script.js',
			[],
			$version,
			true
		);
		wp_localize_script(
			'easymailing-checkout-tracker',
			'easymailingCheckoutVars',
			[
				'ajaxurl' => admin_url('admin-ajax.php'),
				'nonce'   => wp_create_nonce('easymailing-checkout-tracker'),
			]
		);
		wp_enqueue_script('easymailing-checkout-tracker');

		$logManager->createLog(
			\Easymailing\App\Core\Provider\Woocommerce\Model\LogType::INFO,
			"[EM-DEBUG] checkout tracker JS enqueued"
		);
	}

	public function enqueueCheckoutPhoneValidator(): void
	{
		if (!function_exists('is_checkout') || !is_checkout()) {
			return;
		}

		$synchronizationConfig = $this->application->getContainer()->get('config_repository')->getSynchronizationConfig();
		if (!$synchronizationConfig->isValidateCheckoutPhone()) {
			return;
		}

		$pluginUrl = $this->application->getConfigurations()['plugin_url'];
		$pluginPath = $this->application->getConfigurations()['plugin_path'];
		$version = defined('EASYMAILING_OFFICIAL_VERSION') ? EASYMAILING_OFFICIAL_VERSION : '1.4';

		$baseCountry = 'es';
		if (function_exists('wc_get_base_location')) {
			$baseLocation = wc_get_base_location();
			if (!empty($baseLocation['country'])) {
				$baseCountry = strtolower($baseLocation['country']);
			}
		}

		$allowedCountries = [];
		if (function_exists('WC') && WC() && WC()->countries) {
			$allowedCountries = array_map('strtolower', array_keys(WC()->countries->get_allowed_countries()));
		}

		$stylePath = $pluginPath . 'assets/build/plugin/easymailing_phone_validator_script.css';
		if (file_exists($stylePath)) {
			wp_enqueue_style(
				'easymailing-phone-validator',
				$pluginUrl . 'assets/build/plugin/easymailing_phone_validator_script.css',
				[],
				$version
			);
		}

		wp_register_script(
			'easymailing-phone-validator',
			$pluginUrl . 'assets/build/plugin/easymailing_phone_validator_script.js',
			[],
			$version,
			true
		);

		wp_localize_script(
			'easymailing-phone-validator',
			'easymailingPhoneValidatorVars',
			[
				'defaultCountry' => $baseCountry,
				'allowedCountries' => $allowedCountries,
				'errorMessage' => __('Introduce un teléfono válido con prefijo de país.', 'easymailing'),
				'flags1x' => $pluginUrl . 'assets/build/plugin/img/intl-tel-input/flags.webp',
				'flags2x' => $pluginUrl . 'assets/build/plugin/img/intl-tel-input/flags@2x.webp',
			]
		);

		wp_enqueue_script('easymailing-phone-validator');
	}

	private function addLoggedAction(string $hook, callable $callback, int $priority = 10, int $acceptedArgs = 1)
	{
		add_action($hook, function (...$args) use ($hook, $callback) {
			$this->logHook(LogType::ACTION, $hook, $callback);
			call_user_func_array($callback, $args);
		}, $priority, $acceptedArgs);
	}

	private function addLoggedFilter(string $hook, callable $callback, int $priority = 10, int $acceptedArgs = 1)
	{
		add_filter($hook, function (...$args) use ($hook, $callback) {
			$this->logHook(LogType::FILTER, $hook, $callback);
			return call_user_func_array($callback, $args);
		}, $priority, $acceptedArgs);
	}

	private function logHook(string $type, string $hook, callable $callback): void
	{
		$logManager = $this->application->getContainer()->get("log_manager");
		$callbackName = is_array($callback)
			? (is_object($callback[0]) ? get_class($callback[0]) : $callback[0]) . '::' . $callback[1]
			: (is_string($callback) ? $callback : 'closure');

		$logManager->createLog($type, "$hook | $callbackName");
	}

    public static function unRegister()
    {
        $application = Application::getInstance();

        /** BACKGROUND TASKS */
        $synchronizationService = $application->getContainer()->get("synchronization_hook");
        remove_action(BatchEnqueueManager::SYNCHRONIZATION_BACKGROUND_TASK, array($synchronizationService, "startSynchronizationInBackground"));
        remove_action(BatchEnqueueManager::SYNCHRONIZATION_CHECK_BACKGROUND_TASK, array($synchronizationService, "checkSynchronizationInBackground"));

	    self::unSchedulePendingActions(BatchEnqueueManager::SYNCHRONIZATION_BACKGROUND_TASK, BatchEnqueueManager::ENQUEUE_GROUP);
	    self::unSchedulePendingActions(BatchEnqueueManager::SYNCHRONIZATION_CHECK_BACKGROUND_TASK, BatchEnqueueManager::ENQUEUE_GROUP);

	    $flashBag = $application->getContainer()->get("flash_bag");
	    remove_action('admin_notices', [$flashBag, 'adminNotices']);

        /** PRODUCT WIDGETS */
        $productWidgets = $application->getContainer()->get('product_widgets');
        remove_action('add_meta_boxes', array($productWidgets, 'addWidgets'));
        remove_filter('manage_edit-product_columns', array($productWidgets, 'addSynchronizationColumn'));
        remove_action('manage_product_posts_custom_column', array($productWidgets, 'showCustomProductColumnData'));

        /** CATEGORY WIDGETS */
        $categoryWidgets = $application->getContainer()->get('category_widgets');
        remove_action('product_cat_edit_form_fields', array($categoryWidgets, 'addWidgets'));
        remove_filter('manage_edit-product_cat_columns', array($categoryWidgets, 'addSynchronizationColumn'));
        remove_action('manage_product_cat_custom_column', array($categoryWidgets, 'showCustomCategoryColumnData'));

        /** ORDER WIDGETS */
        $orderWidgets = $application->getContainer()->get('order_widgets');
        remove_action('add_meta_boxes', array($orderWidgets, 'addWidgets'), 10);
        remove_filter('manage_woocommerce_page_wc-orders_columns', array($orderWidgets, 'addSynchronizationColumn'));
        remove_action('manage_woocommerce_page_wc-orders_custom_column', array($orderWidgets, 'showCustomOrderColumnData'));

        /** CUSTOMER WIDGETS */
        $customerWidgets = $application->getContainer()->get('customer_widgets');
        remove_action('edit_user_profile', array($customerWidgets, 'addWidgets'));
        remove_action('show_user_profile', array($customerWidgets, 'addWidgets'));
        remove_filter('manage_users_columns', array($customerWidgets, 'addColumn'));
        remove_action('manage_users_custom_column',  array($customerWidgets, 'showCustomCustomerColumnData'));


        /** CUSTOMER HOOKS */
        $customerHooks = $application->getContainer()->get("customer_hooks");
        remove_action('woocommerce_checkout_fields', array($customerHooks, 'registerCheckoutFields'));
        remove_action('woocommerce_checkout_update_order_meta', array($customerHooks, 'saveCheckoutFields'));
        remove_action('woocommerce_register_form', array($customerHooks, 'addFieldsToRegistrationForm'));
        remove_action('woocommerce_created_customer', array($customerHooks, 'saveRegistrationFields'));
        remove_action('woocommerce_edit_account_form', array($customerHooks, 'addFieldsToEditAccountForm'));
        remove_action('woocommerce_save_account_details', array($customerHooks, 'saveAccountEditFields'));

        /** PRODUCT HOOKS */
        $productHooks = $application->getContainer()->get("product_hooks");
        remove_action("save_post", array($productHooks, 'synchronizeProductAdmin'));

        /** CATEGORY HOOKS */
        $categoryHooks = $application->getContainer()->get("category_hooks");
        remove_action("created_product_cat", array($categoryHooks, 'createCategory'));
        remove_action('edited_product_cat',  array($categoryHooks, 'updateCategory'));

		/** CAMPAIGN HASH */
	    $campaignHashHook = $application->getContainer()->get("campaign_hash_hook");
	    remove_action('woocommerce_load_cart_from_session', [$campaignHashHook, 'saveCampaignHash']);

	    /** CART REBUILD */
	    $cartRebuildHook = $application->getContainer()->get("cart_rebuild_hook");
	    remove_action('wp_loaded', [$cartRebuildHook, 'rebuildCart']);

	    /** CART PROCESS */
	    $cartHooks = $application->getContainer()->get("cart_hooks");
	    remove_action('woocommerce_load_cart_from_session', [$cartHooks, 'checkCartAfterLogin']);
	    remove_action('woocommerce_add_to_cart', [$cartHooks, 'cartUpdated']);
	    remove_action('woocommerce_remove_cart_item', [$cartHooks, 'cartUpdated']);
	    remove_action('woocommerce_after_cart_item_quantity_update', [$cartHooks, 'cartUpdated']);
	    remove_action('woocommerce_store_api_cart_update_customer_from_request', [$cartHooks, 'cartCustomerUpdated']);
	    remove_action('woocommerce_store_api_checkout_update_order_from_request', [$cartHooks, 'blockCheckoutUpdated']);
	    remove_action('woocommerce_checkout_update_order_review', [$cartHooks, 'classicCheckoutUpdated']);
	    remove_action('wp_ajax_easymailing_track_checkout_email', [$cartHooks, 'ajaxTrackCheckoutEmail']);
	    remove_action('wp_ajax_nopriv_easymailing_track_checkout_email', [$cartHooks, 'ajaxTrackCheckoutEmail']);

        /** ORDER HOOKS */
	    $orderHooks = $application->getContainer()->get("order_hooks");
        remove_action('woocommerce_checkout_order_created', array($orderHooks, 'orderCreated'));
        remove_action('woocommerce_order_status_changed', array($orderHooks, 'synchronizeStatus'));
        remove_action('woocommerce_order_status_changed', array($orderHooks, 'synchronizeStatus'));
//        remove_action('woocommerce_payment_complete', array($orderHooks, 'synchronizeStatus'));

	    /** @var DeleteHook $deleteHook */
	    $deleteHook = $application->getContainer()->get("delete_hook");
	    remove_action('wp_trash_post', array($deleteHook, 'onDeletePost'));
	    remove_action('woocommerce_trash_order', array($deleteHook, 'deleteOrder'));
	    remove_action('delete_user', array($deleteHook, 'deleteUser'));

	    /** @var SynchronizationAction $synchronizationAction */
	    $synchronizationAction =  $application->getContainer()->get('synchronization_action');
	    remove_action('post_row_actions', array($synchronizationAction, 'postActions'));
	    remove_action('user_row_actions', array($synchronizationAction, 'userActions'));
	    remove_action('product_cat_row_actions', array($synchronizationAction, 'categoryActions'));

    }

	public static function unSchedulePendingActions(string $hook, string $group): void {
		// Obtiene todas las acciones pendientes relacionadas con el hook y el grupo
		$actions = as_get_scheduled_actions([
			'hook' => $hook,
			'status' => \ActionScheduler_Store::STATUS_PENDING,
			'group' => $group,
		]);

		// Cancela cada acción individualmente
		foreach ($actions as $actionId) {
			as_unschedule_action($hook, [], $group);
		}
	}

	public static function shouldRegister(): bool
	{
		return true;
	}
}
