<?php
/**
 * Handles the Content block.
 *
 * @package GenerateBlocksPro
 */

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

/**
 * Content block class.
 */
class GenerateBlocks_Block_Classic_Menu extends GenerateBlocks_Block {
	/**
	 * Keep track of all blocks of this type on the page.
	 *
	 * @var array $block_ids The current block id.
	 */
	protected static $block_ids = [];

	/**
	 * Store our block name.
	 *
	 * @var string $block_name The block name.
	 */
	public static $block_name = 'generateblocks-pro/classic-menu';

	/**
	 * Cache for mega menu display checks.
	 *
	 * @var array
	 */
	private static $mega_menu_cache = [];

	/**
	 * Check if a mega menu overlay should display based on conditions.
	 *
	 * @param int $overlay_id The overlay post ID.
	 * @return bool Whether the overlay should display.
	 */
	private static function should_display_mega_menu( $overlay_id ) {
		// Return false if overlays are disabled.
		if ( ! generateblocks_pro_overlays_enabled() ) {
			return false;
		}

		if ( ! $overlay_id ) {
			return false;
		}

		// Check cache first.
		if ( isset( self::$mega_menu_cache[ $overlay_id ] ) ) {
			return self::$mega_menu_cache[ $overlay_id ];
		}

		// Check if post exists and is published.
		$overlay_post = get_post( $overlay_id );
		if ( ! $overlay_post || 'publish' !== $overlay_post->post_status ) {
			self::$mega_menu_cache[ $overlay_id ] = false;
			return false;
		}

		$overlay_post_content = do_blocks( $overlay_post->post_content ) ?? '';

		if ( empty( $overlay_post_content ) ) {
			self::$mega_menu_cache[ $overlay_id ] = false;
			return false;
		}

		// Check display conditions.
		$display_condition  = get_post_meta( $overlay_id, '_gb_overlay_display_condition', true );
		$display_conditions = [];

		if ( $display_condition ) {
			// Check if the condition post exists and is published.
			$condition_post = get_post( $display_condition );

			if ( $condition_post && 'publish' === $condition_post->post_status ) {
				$display_conditions = get_post_meta( $display_condition, '_gb_conditions', true ) ?? [];
			}
		}

		$show = true;

		if ( ! empty( $display_conditions ) ) {
			$show             = GenerateBlocks_Pro_Conditions::show( $display_conditions );
			$invert_condition = GenerateBlocks_Pro_Overlays::get_overlay_meta( $overlay_id, '_gb_overlay_display_condition_invert' );

			// If invert is enabled, flip the result.
			if ( $invert_condition ) {
				$show = ! $show;
			}
		}

		// Cache the result.
		self::$mega_menu_cache[ $overlay_id ] = $show;

		return $show;
	}

	/**
	 * Render the Element block.
	 *
	 * @param array  $attributes    The block attributes.
	 * @param string $block_content The block content.
	 * @param array  $block         The block.
	 */
	public static function render_block( $attributes, $block_content, $block ) {
		// Clear mega menu cache for fresh checks.
		self::$mega_menu_cache = [];

		// Add styles to this block if needed.
		$block_content = generateblocks_maybe_add_block_css(
			$block_content,
			[
				'class_name' => __CLASS__,
				'attributes' => $attributes,
				'block_ids' => self::$block_ids,
			]
		);

		$selected_menu = $attributes['menu'] ?? '';
		$unique_id = $attributes['uniqueId'] ?? '';

		if ( ! $selected_menu || ! $unique_id ) {
			return;
		}

		if ( isset( $block->context['generateblocks-pro/subMenuType'] ) ) {
			$sub_menu_type = $block->context['generateblocks-pro/subMenuType'];
		} elseif ( isset( $_GET['subMenuType'] ) ) { // phpcs:ignore -- No processing of data.
			$sub_menu_type = esc_attr( $_GET['subMenuType'] ); // phpcs:ignore -- No processing of data.
		} else {
			$sub_menu_type = 'hover';
		}

		$classes = [
			'gb-menu',
			'gb-menu--base',
			'gb-menu-' . $unique_id,
			'gb-menu--' . $sub_menu_type,
		];

		if ( ! empty( $attributes['globalClasses'] ) ) {
			$classes = array_merge( $classes, $attributes['globalClasses'] );
		}

		if ( ! empty( $attributes['className'] ) ) {
			$classes[] = $attributes['className'];
		}

		$class = implode( ' ', $classes );

		$add_menu_item_classes = function( $classes, $menu_item ) use ( $sub_menu_type, $unique_id ) {
			$mega_menu = get_post_meta( $menu_item->ID, '_gb_mega_menu', true );

			if ( $mega_menu && self::should_display_mega_menu( $mega_menu ) ) {
				$classes[] = 'menu-item-has-gb-mega-menu';
				$classes[] = 'menu-item-has-children';
			}

			$classes[] = 'gb-menu-item';
			$new_unique_id = substr_replace( $unique_id, 'mi', 0, 2 );
			$classes[] = 'gb-menu-item-' . $new_unique_id;

			// Escape classes.
			$classes = array_map( 'esc_attr', $classes );

			return $classes;
		};

		$add_dropdown_icon = function( $title, $menu_item ) use ( $sub_menu_type ) {
			$mega_menu      = get_post_meta( $menu_item->ID, '_gb_mega_menu', true );
			$has_children   = in_array( 'menu-item-has-children', $menu_item->classes, true );
			$show_mega_menu = $mega_menu && self::should_display_mega_menu( $mega_menu );

			if ( $show_mega_menu || $has_children ) {
				$modal_id       = $show_mega_menu ? 'gb-overlay-' . $mega_menu : '';
				$arrow_icon     = '<svg class="gb-submenu-toggle-icon" viewBox="0 0 330 512" aria-hidden="true" width="1em" height="1em" fill="currentColor"><path d="M305.913 197.085c0 2.266-1.133 4.815-2.833 6.514L171.087 335.593c-1.7 1.7-4.249 2.832-6.515 2.832s-4.815-1.133-6.515-2.832L26.064 203.599c-1.7-1.7-2.832-4.248-2.832-6.514s1.132-4.816 2.832-6.515l14.162-14.163c1.7-1.699 3.966-2.832 6.515-2.832 2.266 0 4.815 1.133 6.515 2.832l111.316 111.317 111.316-111.317c1.7-1.699 4.249-2.832 6.515-2.832s4.815 1.133 6.515 2.832l14.162 14.163c1.7 1.7 2.833 4.249 2.833 6.515z"></path></svg>';

				$submenu_button = sprintf(
					'<span class="gb-submenu-toggle" aria-label="%3$s" role="button" aria-expanded="false" aria-haspopup="menu" tabindex="0"%2$s>%1$s</span>',
					$arrow_icon,
					$modal_id ? ' data-gb-overlay="' . esc_attr( $modal_id ) . '" data-gb-overlay-trigger-type="click" aria-controls="' . esc_attr( $modal_id ) . '"' : '',
					sprintf(
						/* translators: %s: Menu item title. */
						esc_attr__( '%s Sub-Menu', 'generateblocks-pro' ),
						$title
					)
				);

				if ( 'click' === $sub_menu_type ) {
					return $title . $arrow_icon;
				}

				return $title . $submenu_button;
			}

			return $title;
		};

		$add_link_atts = function ( $atts, $menu_item ) use ( $sub_menu_type ) {
			$class         = $atts['class'] ?? '';
			$class         .= ' gb-menu-link';
			$class         = trim( $class );
			$atts['class'] = esc_attr( $class );
			$disable_links = isset( $_GET['disableLinks'] ); // phpcs:ignore -- No processing of data.

			if ( $disable_links ) {
				$atts['onClick'] = 'event.preventDefault();';
			}

			if ( 'hover' === $sub_menu_type || 'click' === $sub_menu_type ) {
				$mega_menu = get_post_meta( $menu_item->ID, '_gb_mega_menu', true );
				$show_mega_menu = $mega_menu && self::should_display_mega_menu( $mega_menu );

				if ( $show_mega_menu ) {
					$modal_id = 'gb-overlay-' . $mega_menu;

					// Add directive and modal element target.
					$atts['data-gb-overlay'] = $modal_id;

					if ( 'hover' === $sub_menu_type ) {
						$atts['data-gb-overlay-trigger-type'] = 'hover';
					}

					$atts['aria-controls'] = $modal_id;
				}

				if ( $show_mega_menu || in_array( 'menu-item-has-children', $menu_item->classes, true ) ) {
					if ( 'click' === $sub_menu_type ) {
						$atts['role']          = 'button';
						$atts['aria-expanded'] = 'false';
						$atts['aria-label']    = sprintf(
							/* translators: %s: Menu item title. */
							esc_attr__( '%s Sub-Menu', 'generateblocks-pro' ),
							$menu_item->title ?? ''
						);
					}

					$atts['aria-haspopup'] = 'menu';
				}
			}

			return $atts;
		};

		$add_sub_menu_attributes = function( $atts, $args ) use ( $unique_id ) {
			$new_unique_id = substr_replace( $unique_id, 'sm', 0, 2 );
			$atts['class'] = 'sub-menu gb-sub-menu gb-sub-menu-' . $new_unique_id;

			return $atts;
		};

		$add_mega_menu = function( $item_output, $item ) {
			$item_id = $item->ID;
			$mega_menu = get_post_meta( $item_id, '_gb_mega_menu', true );

			if ( ! $mega_menu || ! self::should_display_mega_menu( $mega_menu ) ) {
				return $item_output;
			}

			$action_id = 'gb-mega-menu-' . $mega_menu;
			ob_start();
			do_action( $action_id, $item );
			$mega_menu_content = ob_get_clean();
			return $item_output . $mega_menu_content;
		};

		add_filter( 'nav_menu_css_class', $add_menu_item_classes, 10, 2 );
		add_filter( 'nav_menu_submenu_attributes', $add_sub_menu_attributes, 10, 2 );
		add_filter( 'nav_menu_item_title', $add_dropdown_icon, 10, 2 );
		add_filter( 'nav_menu_link_attributes', $add_link_atts, 10, 2 );
		add_filter( 'walker_nav_menu_start_el', $add_mega_menu, 10, 2 );

		ob_start();

		wp_nav_menu(
			[
				'menu'            => $selected_menu,
				'container'       => '',
				'container_class' => '',
				'menu_class'      => $class,
				'items_wrap'      => '<ul id="%1$s" class="%2$s">%3$s</ul>',
				'fallback_cb'     => false,
			]
		);

		remove_filter( 'nav_menu_css_class', $add_menu_item_classes, 10, 2 );
		remove_filter( 'nav_menu_submenu_attributes', $add_sub_menu_attributes, 10, 2 );
		remove_filter( 'nav_menu_item_title', $add_dropdown_icon, 10, 2 );
		remove_filter( 'nav_menu_link_attributes', $add_link_atts, 10, 2 );
		remove_filter( 'walker_nav_menu_start_el', $add_mega_menu, 10, 2 );

		do_action( 'generateblocks_pro_after_menu_block', $attributes, is_admin() );

		$block_content .= ob_get_clean();

		if ( ! wp_style_is( 'generateblocks-classic-menu', 'enqueued' ) ) {
			self::enqueue_style();
		}

		if ( ! wp_script_is( 'generateblocks-classic-menu', 'enqueued' ) ) {
			self::enqueue_scripts();
		}

		return $block_content;
	}

	/**
	 * Enqueue block styles.
	 */
	private static function enqueue_style() {
		wp_enqueue_style(
			'generateblocks-classic-menu',
			GENERATEBLOCKS_PRO_DIR_URL . 'dist/classic-menu-style.css',
			[],
			GENERATEBLOCKS_PRO_VERSION
		);
	}

	/**
	 * Enqueue block scripts.
	 */
	private static function enqueue_scripts() {
		wp_enqueue_script(
			'generateblocks-classic-menu',
			GENERATEBLOCKS_PRO_DIR_URL . 'dist/classic-menu.js',
			[],
			GENERATEBLOCKS_PRO_VERSION,
			true
		);
	}

	/**
	 * Enqueue block assets.
	 */
	public static function enqueue_assets() {
		self::enqueue_scripts();
		self::enqueue_style();
	}
}
