<?php
/**
 * Blocks Register
 *
 * @package SureDonation
 */

namespace SureDonation\Inc\Blocks;

use SureDonation\Inc\Payments\Stripe\Stripe_Helper;
use SureDonation\Inc\Traits\Get_Instance;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Register class for blocks.
 *
 * @since 0.0.1
 */
class Register {
	use Get_Instance;

	/**
	 * Constructor.
	 *
	 * @since 0.0.1
	 */
	public function __construct() {
		add_action( 'init', [ $this, 'register_blocks' ] );
		add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_editor_assets' ] );
		add_filter( 'block_categories_all', [ $this, 'register_block_category' ], 10, 2 );
	}

	/**
	 * Register custom block category for SureDonation blocks.
	 *
	 * Only adds the category on the donation form editor.
	 *
	 * @param array<int, array<string, mixed>> $categories Existing block categories.
	 * @param \WP_Block_Editor_Context         $context    Block editor context.
	 * @return array<int, array<string, mixed>> Modified block categories.
	 * @since 0.0.1
	 */
	public function register_block_category( $categories, $context ) {
		// Only show category on donation form editor.
		if ( ! isset( $context->post ) || 'suredonation_form' !== $context->post->post_type ) {
			return $categories;
		}

		// Add SureDonation category at the beginning.
		return array_merge(
			[
				[
					'slug'  => 'suredonation',
					'title' => __( 'General Fields', 'suredonation' ),
					'icon'  => null,
				],
			],
			$categories
		);
	}

	/**
	 * Enqueue block editor assets.
	 *
	 * Only loads on the donation form editor.
	 *
	 * @return void
	 * @since 0.0.1
	 */
	public function enqueue_editor_assets() {
		$screen = get_current_screen();

		// Only load on donation form editor.
		if ( ! $screen || 'suredonation_form' !== $screen->post_type ) {
			return;
		}

		// Enqueue the blocks script.
		wp_enqueue_script(
			'suredonation-blocks',
			SUREDONATION_URL . 'assets/build/blocks.js',
			[ 'wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-i18n', 'wp-block-editor', 'wp-data' ],
			SUREDONATION_VER,
			true
		);

		// Localize script with admin data for blocks.
		wp_localize_script(
			'suredonation-blocks',
			'suredonation_admin',
			[
				'payments' => [
					'stripe_connected'   => Stripe_Helper::is_stripe_connected(),
					'stripe_connect_url' => Stripe_Helper::get_stripe_connect_url(),
				],
			]
		);
	}

	/**
	 * Register all blocks.
	 *
	 * @return void
	 * @since 0.0.1
	 */
	public function register_blocks() {
		$blocks = [
			[
				'dir'       => SUREDONATION_DIR . 'inc/blocks/**/*.php',
				'namespace' => 'SureDonation\\Inc\\Blocks',
			],
		];

		/**
		 * Filter to add and register additional blocks.
		 *
		 * @param array<int, array<string, string>> $additional_blocks Additional blocks to register.
		 */
		$additional_blocks = apply_filters( 'suredonation_register_additional_blocks', [] );

		if ( ! empty( $additional_blocks ) && is_array( $additional_blocks ) && count( $additional_blocks ) > 0 ) {
			$blocks = [ ...$blocks, ...$additional_blocks ];
		}

		foreach ( $blocks as $block ) {
			if ( ! is_array( $block ) || ! isset( $block['dir'] ) || ! isset( $block['namespace'] ) ) {
				continue;
			}
			$block_files = glob( $block['dir'] );
			if ( is_array( $block_files ) ) {
				$this->register_block( $block_files, $block['namespace'], 'Block' );
			}
		}
	}

	/**
	 * Register blocks from directory.
	 *
	 * @param array<int, string> $blocks_dir      Array of block file paths.
	 * @param string             $block_namespace Block namespace.
	 * @param string             $base            Base class name.
	 * @return void
	 * @since 0.0.1
	 */
	public function register_block( $blocks_dir, $block_namespace, $base ) {
		if ( empty( $blocks_dir ) ) {
			return;
		}

		foreach ( $blocks_dir as $filename ) {
			// Skip base.php and register.php.
			$basename = basename( $filename );
			if ( 'base.php' === $basename || 'register.php' === $basename ) {
				continue;
			}

			require_once $filename;

			// Replace hyphens with underscores in directory name.
			$classname = str_replace( '-', '_', basename( dirname( $filename ) ) );

			// Convert to title case.
			$classname = ucwords( $classname, '_' );

			$full_class_name = $block_namespace . '\\' . $classname . '\\' . $base;

			// Check if the class exists.
			if ( class_exists( $full_class_name ) ) {
				$block = new $full_class_name();

				// Call register on the block object.
				if ( method_exists( $block, 'register' ) ) {
					$block->register();
				}
			}
		}
	}
}
