<?php
/**
 * Blocks
 *
 * @package StrategyBlocks
 */

namespace StrategyBlocks;

use StrategyBlocks\Utility;

/**
 * Creates the StrategyBlocks post type and shortcodes to output them.
 */
class Blocks extends \StrategyBlocks\Module {
	/**
	 * Only register if on an admin page and if fieldmanager plugin is active.
	 *
	 * @return bool
	 */
	public function can_register() {
		return true;
	}

	/**
	 * Register our hooks.
	 *
	 * @return void
	 */
	public function register() {
		add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_block_editor_assets' ] );
		add_action( 'wp_enqueue_scripts', [ $this, 'enqueues' ] );
		add_action( 'init', [ $this, 'register_blocks' ] );
		add_filter( 'block_editor_settings_all', [ $this, 'remove_block_wrapper_styles' ] );
		add_action( 'init', [ $this, 'register_block_patterns' ] );
		add_filter( 'block_categories_all', [ $this, 'register_block_categories' ], 5 );
		add_filter( 'block_type_metadata_settings', [ $this, 'filter_block_category' ], 10, 2 );
		/**
		 * Removes the Block Directory
		 *
		 * Third party blocks show up during search. We want to disable this.
		 */
		remove_action( 'enqueue_block_editor_assets', 'wp_enqueue_editor_block_directory_assets' );

		// Globally disable the Pattern Directory.
		add_filter( 'should_load_remote_block_patterns', '__return_false' );
		add_filter( 'render_block', [ $this, 'remove_wp_elements_classes' ], 10, 2 );

		add_action( 'enqueue_block_editor_assets', [ $this, 'blocks_localize_logo_id' ] );
		add_filter( 'allowed_block_types_all', [ $this, 'allowed_block_types' ], PHP_INT_MAX, 2 );

		// Adds user role to the user REST API endpoints
		add_action(
			'rest_api_init',
			function () {
				register_rest_field(
					'user',
					'user_role',
					[
						'get_callback' => function ( $user ) {
							$userdata = get_userdata( $user['id'] );
							return $userdata->roles;
						},
						'schema' => null,
					]
				);
			}
		);
	}

	/**
	 * Enqueue custom block editor JavaScript for animation previews.
	 *
	 * This script enables animation behavior (e.g., entrance animations, previews)
	 * within the Gutenberg editor, ensuring parity with frontend interaction.
	 *
	 * Dependencies include core block editor scripts like wp-blocks, wp-dom-ready, and wp-edit-post.
	 *
	 * @return void
	 */
	public function enqueue_block_editor_assets() {
		wp_enqueue_style(
			'strategy_blocks_css',
			Utility\style_url( 'style', 'admin' ),
			[],
			Utility\get_asset_info( 'style', 'version' ),
		);

		wp_enqueue_script(
			'strategy_blocks_editor_animations',
			Utility\script_url( 'block-editor-animations', 'admin' ),
			[ 'wp-blocks', 'wp-dom-ready', 'wp-edit-post' ],
			Utility\get_asset_info( 'block-editor-animations', 'version' ),
			true
		);

		wp_localize_script(
			'jquery',
			'lgMapData',
			[
				'gak' => base64_encode( defined( 'GOOGLE_API_TOKEN' ) ? GOOGLE_API_TOKEN : DEVELOPER_GOOGLE_API_TOKEN ),
			]
		);

		$this->strategy_blocks_register_icons();
	}

	/**
	 * Enqueue our built assets.
	 *
	 * @return void
	 */
	public function enqueues() {
		$template_parts = [
			get_block_template( get_stylesheet() . '//header', 'wp_template_part' ),
			get_block_template( get_stylesheet() . '//footer', 'wp_template_part' ),
		];

		if ( is_home() || is_archive() || is_search() || is_single() ) {
			$template_parts[] = get_block_template( get_stylesheet() . '//index', 'wp_template_part' );
		}

		wp_enqueue_style(
			'strategy_blocks_css',
			Utility\style_url( 'style', 'frontend' ),
			[],
			Utility\get_asset_info( 'style', 'version' ),
		);

		if (
			Utility\truly_has_block( 'leadgen/image-slider', $template_parts ) ||
			Utility\truly_has_block( 'leadgen/testimonials', $template_parts ) ||
			Utility\truly_has_block( 'leadgen/posts', $template_parts ) ||
			isset( $_GET['block_migration_preview'] )
		) {
			wp_enqueue_script(
				'strategy_slider',
				Utility\script_url( 'slider', 'frontend' ),
				[],
				Utility\get_asset_info( 'slider', 'version' ),
				true
			);
		}

		if ( Utility\truly_has_block( 'leadgen/google-map', $template_parts ) ) {
			wp_enqueue_script(
				'strategy_google_map',
				Utility\script_url( 'google-map', 'frontend' ),
				[],
				Utility\get_asset_info( 'google-map', 'version' ),
				true
			);
			wp_localize_script(
				'strategy_google_map',
				'lgMapData',
				[
					'gak' => base64_encode( defined( 'GOOGLE_API_TOKEN' ) ? GOOGLE_API_TOKEN : DEVELOPER_GOOGLE_API_TOKEN ),
				]
			);
		}
	}

	/**
	 * Registers WordPress blocks found in the distribution directory by scanning for
	 * `block.json` files and calling `register_block_type_from_metadata()` on each.
	 *
	 * If a block folder contains a `markup.php` file, a custom render callback is added,
	 * which includes the file and returns its output.
	 *
	 * @return void
	 */
	public function register_blocks() {
		if ( file_exists( STRATEGY_BLOCKS_BLOCK_DIST_DIR ) ) {
			$block_json_files = glob( STRATEGY_BLOCKS_BLOCK_DIST_DIR . '*/block.json' );

			// auto register all blocks that were found.
			foreach ( $block_json_files as $filename ) {
				$block_folder = dirname( $filename );
				$block_name = basename( $block_folder );

				// Skip the "container" block because it's not ready for production
				if ( 'container' === $block_name || 'example' === $block_name ) {
					continue;
				}

				$block_options = [];
				$markup_file_path = $block_folder . '/markup.php';
				if ( file_exists( $markup_file_path ) ) {
					// only add the render callback if the block has a file called markdown.php in it's directory
					$block_options['render_callback'] = function ( $attributes, $content, $block ) use ( $block_folder ) {
						ob_start();
						// create helpful variables that will be accessible in markup.php file
						$context = $block->context;
						// get the actual markup from the markup.php file
						include $block_folder . '/markup.php';
						return ob_get_clean();
					};
				};

				register_block_type_from_metadata( $block_folder, $block_options );
			};
		};
	}

	/**
	 * Removes inline style tags that WP inserts and keeps our stylesheets in the editor.
	 *
	 * @param array $settings Settings array that WP uses for the block editor.
	 */
	public function remove_block_wrapper_styles( $settings ) {
		if ( $settings && isset( $settings['styles'] ) ) {
			foreach ( $settings['styles'] as $i => $style ) {
				if ( ! isset( $style['baseURL'] ) ) {
					unset( $settings['styles'][ $i ] );
				}
			}
			$settings['styles'] = array_values( $settings['styles'] );
		}

		return $settings;
	}

	/**
	 * Register block pattern categories
	 *
	 * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-patterns/
	 *
	 * @return void
	 */
	public function register_block_patterns() {
		register_block_pattern_category(
			'lead-gen-base',
			[ 'label' => __( 'Base', 'lead-gen' ) ]
		);

		register_block_pattern_category(
			'lg-professional',
			[ 'label' => __( 'Professional Theme', 'lead-gen' ) ]
		);

		register_block_pattern_category(
			'pages',
			[ 'label' => __( 'Pages', 'lead-gen' ) ]
		);

		register_block_pattern_category(
			'sections',
			[ 'label' => __( 'Sections', 'lead-gen' ) ]
		);

		if ( function_exists( 'register_block_pattern' ) ) {
			// TODO: Only add the patterns marked for a particular theme using the ACF dropdown.
			$block_patterns = array(
				// Page Templates
				[
					'slug'      => 'home-page-template',
					'title'     => 'Home',
					'category'  => 'pages',
				],
				[
					'slug'      => 'about-page-template',
					'title'     => 'About',
					'category'  => 'pages',
				],
				[
					'slug'      => 'contact-page-template',
					'title'     => 'Contact',
					'category'  => 'pages',
				],
				[
					'slug'      => 'gallery-page-template',
					'title'     => 'Gallery',
					'category'  => 'pages',
				],
				[
					'slug'      => 'individual-product-page-template',
					'title'     => 'Individual Product',
					'category'  => 'pages',
				],
				[
					'slug'      => 'landing-page-template',
					'title'     => 'Landing Page',
					'category'  => 'pages',
				],
				[
					'slug'      => 'location-page-template',
					'title'     => 'Location',
					'category'  => 'pages',
				],
				[
					'slug'      => 'resources-page-template',
					'title'     => 'Resources',
					'category'  => 'pages',
				],
				[
					'slug'      => 'service-areas-page-template',
					'title'     => 'Service Areas',
					'category'  => 'pages',
				],
				[
					'slug'      => 'services-page-template',
					'title'     => 'Services',
					'category'  => 'pages',
				],
				[
					'slug'      => 'privacy-page-template',
					'title'     => 'Privacy Policy',
					'category'  => 'pages',
				],
				[
					'slug'      => 'accessibility-page-template',
					'title'     => 'Accessibility Statement',
					'category'  => 'pages',
				],
				[
					'slug'      => 'home-portfolio',
					'title'     => 'Home with Portfolio',
					'category'  => 'pages',
				],
				[
					'slug'      => 'portfolio-page',
					'title'     => 'Portfolio',
					'category'  => 'pages',
				],
				[
					'slug'      => 'portfolio-single-page',
					'title'     => 'Individual Portfolio',
					'category'  => 'pages',
				],
				// Section Templates
				[
					'slug'      => 'blog-archive-section',
					'title'     => 'Blog | Archive',
					'category'  => 'sections',
				],
				[
					'slug'      => 'blog-single-section',
					'title'     => 'Blog | Single',
					'category'  => 'sections',
				],
				[
					'slug'      => 'cards-horizontal-section',
					'title'     => 'Cards | Horizontal',
					'category'  => 'sections',
				],
				[
					'slug'      => 'cards-vertical-section',
					'title'     => 'Cards | Vertical',
					'category'  => 'sections',
				],
				[
					'slug'      => 'portfolio-cards',
					'title'     => 'Cards | Portfolio',
					'category'  => 'sections',
				],
				[
					'slug'      => 'contact-info-section',
					'title'     => 'Contact Info',
					'category'  => 'sections',
				],
				[
					'slug'      => 'content-1-col-center-section',
					'title'     => 'Content | 1 Column | Centered',
					'category'  => 'sections',
				],
				[
					'slug'      => 'content-2-3-split-section',
					'title'     => 'Content | 2/3 Split',
					'category'  => 'sections',
				],
				[
					'slug'      => 'content-2-col-section',
					'title'     => 'Content | 2 Columns',
					'category'  => 'sections',
				],
				[
					'slug'      => 'content-2-col-list-section',
					'title'     => 'Content | 2 Columns | List',
					'category'  => 'sections',
				],
				[
					'slug'      => 'content-2-col-stacked-section',
					'title'     => 'Content | 2 Columns | Stacked',
					'category'  => 'sections',
				],
				[
					'slug'      => 'content-full-image-left-section',
					'title'     => 'Content Full Image Left',
					'category'  => 'sections',
				],
				[
					'slug'      => 'content-full-image-right-section',
					'title'     => 'Content Full Image Right',
					'category'  => 'sections',
				],
				[
					'slug'      => 'content-expanded-section',
					'title'     => 'Content | Expanded',
					'category'  => 'sections',
				],
				[
					'slug'      => 'content-location-section',
					'title'     => 'Content | Location',
					'category'  => 'sections',
				],
				[
					'slug'      => 'cta-steps-section',
					'title'     => 'CTA | Steps',
					'category'  => 'sections',
				],
				[
					'slug'      => 'faqs-section',
					'title'     => 'FAQs',
					'category'  => 'sections',
				],
				[
					'slug'      => 'floating-value-stack-section',
					'title'     => 'Floating Value Stack',
					'category'  => 'sections',
				],
				[
					'slug'      => 'gallery-section',
					'title'     => 'Gallery',
					'category'  => 'sections',
				],
				[
					'slug'      => 'hero-full-screen-section',
					'title'     => 'Hero | Full Screen',
					'category'  => 'sections',
				],
				[
					'slug'      => 'hero-with-values-full-screen-section',
					'title'     => 'Hero | Full Screen w/Values',
					'category'  => 'sections',
				],
				[
					'slug'      => 'hero-large-section',
					'title'     => 'Hero | Large',
					'category'  => 'sections',
				],
				[
					'slug'      => 'hero-small-section',
					'title'     => 'Hero | Small',
					'category'  => 'sections',
				],
				[
					'slug'      => 'icons-with-desc-section',
					'title'     => 'Icons With Descriptions',
					'category'  => 'sections',
				],
				[
					'slug'      => 'lead-magnet-section',
					'title'     => 'Lead Magnet',
					'category'  => 'sections',
				],
				[
					'slug'      => 'map-full-section',
					'title'     => 'Map | Full',
					'category'  => 'sections',
				],
				[
					'slug'      => 'recent-posts-section',
					'title'     => 'Recent Posts',
					'category'  => 'sections',
				],
				[
					'slug'      => 'team-members-section',
					'title'     => 'Team Members',
					'category'  => 'sections',
				],
				[
					'slug'      => 'testimonials-section',
					'title'     => 'Testimonials',
					'category'  => 'sections',
				],
				[
					'slug'      => 'zig-zag',
					'title'     => 'Zig Zag Content',
					'category'  => 'sections',
				],
			);

			foreach ( $block_patterns as $block_pattern ) {
				$content = file_get_contents( STRATEGY_BLOCKS_PATH . '/patterns/' . $block_pattern['category'] . '/' . $block_pattern['slug'] . '.html' );
				register_block_pattern(
					$block_pattern['category'] . '/' . $block_pattern['slug'],
					array(
						'title'      => $block_pattern['title'],
						'content'    => str_replace( [ "\n", "\r", "\t" ], '', $content ),
						'categories' => [ $block_pattern['category'] ],
					)
				);
			}
		}
	}

	/**
	 * Adds LeadGen-specific categories to the list of blocks in the editor.
	 *
	 * @param array $categories         The existing array of editor categories
	 *
	 * @return array                    The modified categories array
	 */
	public function register_block_categories( $categories ) {

		$categories[] = array(
			'slug'  => 'lg-basic',
			'title' => 'Basic',
		);

		$categories[] = array(
			'slug'  => 'lg-layout',
			'title' => 'Layout',
		);

		$categories[] = array(
			'slug'  => 'lg-media',
			'title' => 'Media',
		);

		return $categories;
	}

	/**
	 * Changes the category of specific blocks.
	 *
	 * @param array $settings               The block settings
	 * @param array $metadata               Metadata pertaining to a block
	 *
	 * @return array                        Return the new/unchanged settings
	 */
	public function filter_block_category( $settings, $metadata ) {
		if ( isset( $metadata['name'] ) && isset( $settings['category'] ) ) {
			if ( strpos( $metadata['name'], 'core/' ) !== false && 'core/template-part' !== $metadata['name'] ) {
				$settings['category'] = 'lg-basic';
			}
		}

		return $settings;
	}

	/**
	 * Remove classes that start with "wp-elements-" from the block content.
	 *
	 * This function takes the HTML content of a block and removes any classes
	 * that start with the prefix "wp-elements-". It utilizes a regular
	 * expression to find the class attribute and filters out the unwanted
	 * classes, returning the modified block content.
	 *
	 * @param string $block_content The HTML content of the block.
	 * @param array  $block Additional information about the block (not used in this function).
	 *
	 * @return string The modified block content with specified classes removed.
	 */
	public function remove_wp_elements_classes( $block_content, $block ) {
		// Remove only classes that start with "wp-elements-"
		$block_content = preg_replace_callback(
			'/class="([^"]*)"/',
			function ( $matches ) {
				// Split classes into an array
				$classes = explode( ' ', $matches[1] );
				// Filter out any classes that start with "wp-elements-"
				$filtered_classes = array_filter(
					$classes,
					function ( $class ) {
						return ! preg_match( '/^wp-elements-/', $class );
					}
				);
				// Rebuild the class attribute
				$new_classes = implode( ' ', $filtered_classes );
				return 'class="' . trim( $new_classes ) . '"';
			},
			$block_content
		);

		return $block_content;
	}

	/**
	 * Registers Font Awesome icons by scanning a local SVG directory and
	 * making the icon data available to JavaScript via `wp_localize_script`.
	 *
	 * This function:
	 * - Checks if the Font Awesome SVG directory exists.
	 * - Retrieves all `.svg` files in the directory.
	 * - Builds an array of icon data (name and URL).
	 * - Passes the icon data to the JavaScript environment for use in the editor.
	 *
	 * The localized data is assigned to the `fontAwesomeIcons` variable,
	 * available to the `strategy_blocks_editor_animations` script handle.
	 *
	 * @return void
	 */
	public function strategy_blocks_register_icons() {
		$svg_dir = STRATEGY_BLOCKS_DIST_PATH . 'font-awesome/svgs/solid';
		$svg_url = STRATEGY_BLOCKS_DIST_URL . 'font-awesome/svgs/solid';
		$icons   = [];

		if ( ! is_dir( $svg_dir ) ) {
			error_log( "SVG DIR NOT FOUND: $svg_dir" );
		}

		$icon_files = glob( $svg_dir . '/*.svg' );

		if ( empty( $icon_files ) ) {
			error_log( 'NO SVG FILES FOUND' );
		}

		foreach ( $icon_files as $file ) {
			$icon_name = basename( $file, '.svg' );
			$icons[]   = [
				'name' => $icon_name,
				'url'  => $svg_url . '/' . $icon_name . '.svg',
			];
		}
		wp_localize_script( 'strategy_blocks_editor_animations', 'fontAwesomeIcons', $icons );
	}

	/**
	 * Localizes the site logo ID and alternate logo ID for use in block editor scripts.
	 *
	 * This function retrieves the primary site logo ID from the theme customizer settings
	 * and the alternate logo ID from a global ACF options field named 'design_settings'.
	 * It then exposes both values to the JavaScript block editor environment using
	 * `wp_localize_script`, assigning them to the `siteLogo` object for use in editor scripts.
	 *
	 * @return void
	 */
	public function blocks_localize_logo_id() {
		$design_settings = get_field( 'design_settings', 'options' );
		$logo = get_theme_mod( 'custom_logo' );
		$alternate_logo = '';
		if ( isset( $design_settings['alternate_logo'] ) ) {
			$alternate_logo = $design_settings['alternate_logo'];
		}

		wp_localize_script(
			'strategy_blocks_editor_animations',
			'siteLogo',
			array(
				'id' => $logo,
				'alternate_id' => $alternate_logo,
			)
		);
	}

	/**
	 * Define a list of core block types allowed by the page builder
	 *
	 * @param array                   $allowed_block_types Array of block type slugs, or boolean to enable/disable all. Default true (all registered block types supported).
	 * @param WP_Block_Editor_Context $editor_context The current block editor context.
	 */
	public function allowed_block_types( $allowed_block_types, $editor_context ) {
		$registered_block_slugs = array_map(
			function ( $block ) {
				return $block->name;
			},
			\WP_Block_Type_Registry::get_instance()->get_all_registered()
		);

		$filtered_values = [
			'core/paragraph',
			'core/table',
			'core/list',
			'core/list-item',
			'core/html',
			'core/block',
			'core/pattern',
			'core/template-part',
			'core/post-content',
			'core/freeform',
		];

		foreach ( $registered_block_slugs as $key => $value ) {
			if ( strpos( $key, 'acf/' ) !== false || strpos( $key, 'yoast' ) !== false || strpos( $key, 'gravityforms/' ) !== false || strpos( $key, 'leadgen/' ) !== false ) {
				$filtered_values[] = $key;
			}
		}

		return $filtered_values;
	}
}
