<?php
/**
 * Frontend Event Subscriber for Cart Recovery
 *
 * Handles WordPress events related to frontend scripts, recovery actions,
 * and flash message injection.
 *
 * @package EDD\Pro\CartRecovery\Events
 * @copyright Copyright (c) 2026, Sandhills Development, LLC
 * @license https://opensource.org/licenses/GPL-2.0 GNU Public License
 * @since   3.6.5
 */

declare(strict_types=1);

namespace EDD\Pro\CartRecovery\Events;

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore

use EDD\EventManagement\SubscriberInterface;
use EDD\Pro\CartRecovery\Handlers\Recovery;
use EDD\Utils\Messages;

/**
 * Frontend Event Subscriber class.
 *
 * Subscribes to WordPress frontend events for script enqueuing and action handling.
 */
class FrontendEventSubscriber implements SubscriberInterface {

	/**
	 * Recovery action handler instance.
	 *
	 * @var Recovery
	 */
	private Recovery $recovery_handler;

	/**
	 * Constructor.
	 *
	 * @since 3.6.5
	 * @param Recovery $recovery_handler Recovery action handler instance.
	 */
	public function __construct( Recovery $recovery_handler ) {
		$this->recovery_handler = $recovery_handler;
	}

	/**
	 * Returns subscribed events.
	 *
	 * @since 3.6.5
	 * @return array Event subscriptions.
	 */
	public static function get_subscribed_events(): array {
		return array(
			'wp_enqueue_scripts'            => 'enqueue_scripts',
			'edd_cart_recovery_restore'     => 'maybe_handle_recovery_actions',
			'edd_cart_recovery_unsubscribe' => 'maybe_handle_recovery_actions',
			'edd_cart_empty'                => array( 'maybe_display_recovery_message', 5 ),
		);
	}

	/**
	 * Enqueues frontend scripts for ACR functionality.
	 *
	 * @since 3.6.5
	 * @return void
	 */
	public function enqueue_scripts(): void {
		if ( ! $this->can_enqueue() ) {
			return;
		}

		wp_enqueue_script(
			'edd-cart-recovery',
			edd_get_assets_url( 'pro/js/frontend' ) . 'cart-recovery.js',
			array(),
			edd_admin_get_script_version(),
			true
		);

		$timestamp = time();

		wp_localize_script(
			'edd-cart-recovery',
			'eddCartRecovery',
			array(
				'restEndpoint'  => rest_url( 'edd/v3/acr' ),
				'nonce'         => wp_create_nonce( 'wp_rest' ),
				'timestamp'     => $timestamp,
				'token'         => \EDD\REST\Security::generate_token( $timestamp ),
				'hasTrackedCart' => (bool) EDD()->session->get( 'acr_cart' ),
			)
		);

		wp_enqueue_script(
			'edd-cart-session',
			edd_get_assets_url( 'pro/js/frontend' ) . 'cart-session.js',
			array(),
			edd_admin_get_script_version(),
			true
		);
	}

	/**
	 * Handles recovery actions triggered via query parameters.
	 *
	 * @since 3.6.5
	 * @param array $data The data passed to the event.
	 * @return void
	 */
	public function maybe_handle_recovery_actions( array $data ): void {
		$this->recovery_handler->handle_recovery_actions( $data );
	}

	/**
	 * Replaces the empty cart message with a recovery message.
	 * This is to display unsubscribe or restore success/error messages on the checkout page.
	 *
	 * @since 3.6.5
	 * @return void
	 */
	public function maybe_display_recovery_message(): void {
		// Only run on the main query to avoid displaying in widgets.
		if ( ! is_main_query() ) {
			return;
		}

		if ( ! edd_is_checkout() ) {
			return;
		}

		if ( Messages::get_by_code( 'edd_acr_unsubscribed' ) || Messages::get_by_code( 'edd_acr_restore_failed' ) ) {
			remove_action( 'edd_cart_empty', 'edd_empty_checkout_cart' );
		}
	}

	/**
	 * Checks if the frontend scripts can be enqueued.
	 *
	 * @since 3.6.5
	 * @return bool True if the scripts can be enqueued, false otherwise.
	 */
	private function can_enqueue(): bool {
		if ( ! edd_get_option( 'acr_enabled', false ) ) {
			return false;
		}

		if ( EDD()->session->get( 'acr_cart' ) ) {
			return true;
		}

		if ( edd_get_cart_quantity() ) {
			return true;
		}

		return false;
	}
}
