<?php
/**
 * Blocks registry — manages available Gutenberg blocks, their enabled/disabled
 * state, and registers active block types with WordPress.
 *
 * @package JWP_STK
 */

namespace JWP_STK\Blocks;

use JWP_STK\Options;

defined( 'ABSPATH' ) || exit;

/**
 * Blocks_Registry class.
 */
class Blocks_Registry {

	/**
	 * Options key used to persist per-block enabled state.
	 */
	const OPTIONS_KEY = 'blocks_settings';

	/**
	 * Class instance.
	 *
	 * @var Blocks_Registry
	 */
	protected static $instance;

	/**
	 * Catalogue of blocks shipped with the plugin.
	 *
	 * Each entry: slug, name, description, dir (class / asset subdirectory name).
	 *
	 * @var array<int, array<string, string>>
	 */
	protected static $available_blocks = array(
		array(
			'slug'        => 'wishlist',
			'name'        => 'Wishlist',
			'description' => 'Display the customer\'s wishlist on any page.',
			'dir'         => 'Wishlist',
		),
		array(
			'slug'        => 'add-to-wishlist',
			'name'        => 'Add to Wishlist',
			'description' => 'Add a Wishlist button inside any WooCommerce product loop or product template.',
			'dir'         => 'AddToWishlist',
		),
		array(
			'slug'        => 'social-sharing',
			'name'        => 'Social Sharing',
			'description' => 'Add social sharing buttons to a product page or wishlist page.',
			'dir'         => 'SocialSharing',
		),
	);

	/**
	 * Get class instance.
	 *
	 * @return Blocks_Registry
	 */
	public static function get_instance() {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_filter( 'block_categories_all', array( $this, 'register_block_category' ), 9 );
		add_action( 'init', array( $this, 'register_blocks' ) );
		add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_block_editor_data' ) );
	}

	/**
	 * Register the Store Toolkit block category.
	 *
	 * @param array $categories Existing block categories.
	 * @return array
	 */
	public function register_block_category( array $categories ) {
		array_unshift(
			$categories,
			array(
				'slug'  => 'jstk-blocks',
				'title' => __( 'Store Toolkit', 'jetix-store-toolkit' ),
				'icon'  => null,
			)
		);
		return $categories;
	}

	/**
	 * Return all available blocks with their active state.
	 *
	 * @return array<int, array<string, mixed>>
	 */
	public function get_blocks() {
		$settings = Options::get_instance()->get( self::OPTIONS_KEY, array() );
		$blocks   = array();

		foreach ( self::$available_blocks as $block ) {
			$slug            = $block['slug'];
			$enabled         = isset( $settings[ $slug ]['enabled'] )
				? (bool) $settings[ $slug ]['enabled']
				: true;
			$block['active'] = $enabled;
			$blocks[]        = $block;
		}

		return $blocks;
	}

	/**
	 * Enable or disable a block.
	 *
	 * @param string $slug   Block slug.
	 * @param bool   $active Whether to enable the block.
	 * @return bool
	 */
	public function toggle_block( string $slug, bool $active ) {
		// Validate slug against known blocks.
		$known = array_column( self::$available_blocks, 'slug' );
		if ( ! in_array( $slug, $known, true ) ) {
			return false;
		}

		$settings                     = Options::get_instance()->get( self::OPTIONS_KEY, array() );
		$settings[ $slug ]['enabled'] = $active;
		Options::get_instance()->set( self::OPTIONS_KEY, $settings );

		return true;
	}

	/**
	 * Register active block types with WordPress.
	 *
	 * Runs on the 'init' hook.
	 *
	 * @return void
	 */
	public function register_blocks() {
		$settings = Options::get_instance()->get( self::OPTIONS_KEY, array() );

		foreach ( self::$available_blocks as $block ) {
			$slug    = $block['slug'];
			$enabled = isset( $settings[ $slug ]['enabled'] )
				? (bool) $settings[ $slug ]['enabled']
				: true;

			if ( ! $enabled ) {
				continue;
			}

			$block_asset_dir = JWP_STK_PLUGIN_DIR . 'assets/js/blocks/' . $block['slug'];

			if ( ! file_exists( $block_asset_dir . '/block.json' ) ) {
				continue;
			}

			// Load per-block PHP class for the render callback.
			$block_class_file = JWP_STK_PLUGIN_DIR . 'includes/Blocks/' . $block['dir'] . '/class-block.php';

			if ( file_exists( $block_class_file ) ) {
				require_once $block_class_file;
				$class_name = '\\JWP_STK\\Blocks\\' . $block['dir'] . '\\Block';

				if ( class_exists( $class_name ) ) {
					$instance = new $class_name();
					$instance->register( $block_asset_dir );
					continue;
				}
			}

			// Fallback: register without render callback.
			register_block_type( $block_asset_dir );
		}
	}

	/**
	 * Inject active module slugs into the block editor so Edit components
	 * can conditionally render a notice when their required module is inactive.
	 *
	 * The data is written to window.jwpStkBlocksData before wp-blocks loads.
	 *
	 * @return void
	 */
	public function enqueue_block_editor_data() {
		$active_modules = \JWP_STK\Module_Manager::get_instance()->get_active_modules();

		wp_add_inline_script(
			'wp-blocks',
			'window.jwpStkBlocksData = ' . wp_json_encode( array( 'activeModules' => $active_modules ) ) . ';',
			'before'
		);
	}
}
