<?php
namespace Lean_CSNS;

// Prevent direct access
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Handles WooCommerce Cart Block compatibility.
 * Classic cart hooks and wc_add_notice() do not work inside the Cart Block
 * (React-rendered). All block-specific PHP and JS loading lives here.
 */
class Block_Cart_Integration {

	private static $instance = null;

	public static function get_instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	private function __construct() {
		$this->init();
	}

	private function init() {
		add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_block_cart_script' ] );
		add_action( 'wp_footer', [ $this, 'inject_block_cart_notices' ] );
	}

	/**
	 * Enqueue the block cart JS (button injection + block event listeners).
	 * Loaded on both classic and block cart pages so the detector can run
	 * regardless of whether is_cart() or has_block() fires first.
	 */
	public function enqueue_block_cart_script() {
		if ( ! is_cart() && ! has_block( 'woocommerce/cart' ) ) {
			return;
		}

		wp_enqueue_script(
			'lean-csns-block-cart',
			LEAN_CSNS_PL_URL . 'assets/js/block-cart-integration.js',
			[ 'jquery', 'lean-csns-frontend' ],
			lean_csns_get_version(),
			true
		);
	}

	/**
	 * Inject pending notices into the WC Cart Block via wp.data.
	 * The Cart Block renders via React and ignores PHP wc_add_notice() calls,
	 * so notices are dispatched to core/notices with wc/cart context instead.
	 * Session key lean_csns_block_notices is written by URL_Handler::load_shared_cart().
	 */
	public function inject_block_cart_notices() {
		if ( ! is_cart() || ! WC()->session ) {
			return;
		}

		$notices = WC()->session->get( 'lean_csns_block_notices' );
		if ( empty( $notices ) ) {
			return;
		}

		// Clear immediately so a page refresh does not re-show the same notices.
		WC()->session->set( 'lean_csns_block_notices', null );

		$json = wp_json_encode( $notices );
		?>
		<script>
		( function() {
			var notices = <?php echo $json; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- wp_json_encode output is safe here ?>;

			// True when a cart notice banner already shows this exact message.
			// Modern WooCommerce bridges wc_add_notice() into the block cart on its own,
			// so we must not add a second copy — check the rendered DOM, which catches the
			// bridged notice regardless of which notice context/store it lives in.
			function lean_csns_message_already_shown( msg ) {
				var banners = document.querySelectorAll( '.wc-block-components-notice-banner' );
				for ( var i = 0; i < banners.length; i++ ) {
					if ( banners[ i ].textContent.indexOf( msg ) !== -1 ) {
						return true;
					}
				}
				return false;
			}

			function lean_csns_inject_block_notices() {
				if ( typeof wp === 'undefined' || ! wp.data ) {
					return setTimeout( lean_csns_inject_block_notices, 100 );
				}
				var store = wp.data.dispatch( 'core/notices' );
				if ( ! store || ! store.createNotice ) {
					return setTimeout( lean_csns_inject_block_notices, 100 );
				}
				notices.forEach( function( n ) {
					if ( lean_csns_message_already_shown( n.message ) ) {
						return; // WooCommerce already shows it — don't double.
					}
					store.createNotice( n.type, n.message, { context: 'wc/cart', isDismissible: true } );
				} );
			}

			// Wait for the block cart to render its own (bridged) notices first, then
			// only fill in anything it didn't show (older WooCommerce that ignores wc_add_notice).
			setTimeout( lean_csns_inject_block_notices, 400 );
		} )();
		</script>
		<?php
	}
}

// Initialize singleton instance
Block_Cart_Integration::get_instance();
