<?php
namespace WpRigel\Commandify;

defined( 'ABSPATH' ) || exit;

/**
 * Build a minimal WordPress menu programmatically
 * Used when the real menu isn't available (no cache, REST/CLI context)
 */
function build_minimal_wordpress_menu() {
	$menu       = array();
	$submenu    = array();
	$post_types = get_post_types( array( 'show_ui' => true ), 'objects' );

	// Dashboard.
	$menu[2] = array( 'Dashboard', 'read', 'index.php', 'Dashboard', 'menu-dashboard', 'menu-top menu-icon-dashboard', 'dashicons-dashboard' );

	// Posts.
	if ( isset( $post_types['post'] ) ) {
		$menu[5]             = array( 'Posts', 'edit_posts', 'edit.php', 'Posts', 'menu-posts', 'menu-top menu-icon-post', 'dashicons-admin-post' );
		$submenu['edit.php'] = array(
			array( 'All Posts', 'edit_posts', 'edit.php' ),
			array( 'Add New', 'edit_posts', 'post-new.php' ),
			array( 'Categories', 'manage_categories', 'edit-tags.php?taxonomy=category' ),
			array( 'Tags', 'manage_categories', 'edit-tags.php?taxonomy=post_tag' ),
		);
	}

	// Media.
	$menu[10]              = array( 'Media', 'upload_files', 'upload.php', 'Media', 'menu-media', 'menu-top menu-icon-media', 'dashicons-admin-media' );
	$submenu['upload.php'] = array(
		array( 'Library', 'upload_files', 'upload.php' ),
		array( 'Add New', 'upload_files', 'media-new.php' ),
	);

	// Pages.
	if ( isset( $post_types['page'] ) ) {
		$menu[20]                           = array( 'Pages', 'edit_pages', 'edit.php?post_type=page', 'Pages', 'menu-pages', 'menu-top menu-icon-page', 'dashicons-admin-page' );
		$submenu['edit.php?post_type=page'] = array(
			array( 'All Pages', 'edit_pages', 'edit.php?post_type=page' ),
			array( 'Add New', 'edit_pages', 'post-new.php?post_type=page' ),
		);
	}

	// Comments.
	$menu[25] = array( 'Comments', 'edit_posts', 'edit-comments.php', 'Comments', 'menu-comments', 'menu-top menu-icon-comments', 'dashicons-admin-comments' );

	// Custom Post Types.
	$position = 30;
	foreach ( $post_types as $post_type => $post_type_obj ) {
		if ( in_array( $post_type, array( 'post', 'page', 'attachment' ), true ) ) {
			continue;
		}

		if ( isset( $post_type_obj->show_in_menu ) && false === $post_type_obj->show_in_menu ) {
			continue;
		}

		$menu_slug         = 'edit.php?post_type=' . $post_type;
		$menu[ $position ] = array(
			$post_type_obj->labels->name,
			$post_type_obj->cap->edit_posts,
			$menu_slug,
			$post_type_obj->labels->name,
			'menu-' . $post_type,
			'menu-top',
			$post_type_obj->menu_icon ?: 'dashicons-admin-post',
		);

		$submenu[ $menu_slug ] = array(
			array( 'All ' . $post_type_obj->labels->name, $post_type_obj->cap->edit_posts, $menu_slug ),
			array( 'Add New', $post_type_obj->cap->create_posts ?? $post_type_obj->cap->edit_posts, 'post-new.php?post_type=' . $post_type ),
		);

		$position += 5;
	}//end foreach

	// Users.
	$menu[70]             = array( 'Users', 'list_users', 'users.php', 'Users', 'menu-users', 'menu-top menu-icon-users', 'dashicons-admin-users' );
	$submenu['users.php'] = array(
		array( 'All Users', 'list_users', 'users.php' ),
		array( 'Add New', 'create_users', 'user-new.php' ),
		array( 'Profile', 'read', 'profile.php' ),
	);

	// Tools.
	$menu[75]             = array( 'Tools', 'edit_posts', 'tools.php', 'Tools', 'menu-tools', 'menu-top menu-icon-tools', 'dashicons-admin-tools' );
	$submenu['tools.php'] = array(
		array( 'Available Tools', 'edit_posts', 'tools.php' ),
		array( 'Import', 'import', 'import.php' ),
		array( 'Export', 'export', 'export.php' ),
	);

	// Settings.
	$menu[80]                       = array( 'Settings', 'manage_options', 'options-general.php', 'Settings', 'menu-settings', 'menu-top menu-icon-settings', 'dashicons-admin-settings' );
	$submenu['options-general.php'] = array(
		array( 'General', 'manage_options', 'options-general.php' ),
		array( 'Writing', 'manage_options', 'options-writing.php' ),
		array( 'Reading', 'manage_options', 'options-reading.php' ),
		array( 'Discussion', 'manage_options', 'options-discussion.php' ),
		array( 'Media', 'manage_options', 'options-media.php' ),
		array( 'Permalinks', 'manage_options', 'options-permalink.php' ),
		array( 'Privacy', 'manage_privacy_options', 'options-privacy.php' ),
	);

	return array(
		'menu'    => $menu,
		'submenu' => $submenu,
	);
}

/**
 * Store admin menu data for later use in REST API context
 * This runs on admin_menu at high priority to capture the complete menu
 */
add_action(
	'admin_menu',
	function () {
		global $menu, $submenu;

		if ( ! empty( $menu ) ) {
			set_transient(
				'commandify_menu_data',
				array(
					'menu'    => $menu,
					'submenu' => $submenu,
				),
				HOUR_IN_SECONDS
			);
		}
	},
	9999
);

/**
 * Register WordPress admin menu as navigation commands
 * This hooks into commandify_register_commands which is fired from Registry::load_commands()
 * Priority 20 ensures it runs after early commands but before late commands
 */
/**
 * Determine if we should wait for the admin menu to be built (to avoid stale caches)
 *
 * @return bool
 */
function should_delay_navigation_registration() {
	if ( ! is_admin() ) {
		return false;
	}

	if ( wp_doing_ajax() || wp_doing_cron() ) {
		return false;
	}
	// Remove wp_doing_rest check since the function does not exist or is not available

	if ( did_action( 'admin_menu' ) ) {
		return false;
	}

	return empty( $GLOBALS['menu'] );
}

/**
 * Bootstrap navigation commands registration.
 *
 * If we're still before admin_menu and no global menu exists yet, delay registration until
 * after the admin menu has been built so that brand-new plugin menus appear immediately.
 * Otherwise, register commands right away (e.g. for AJAX/REST contexts).
 */
add_action(
	'commandify_register_commands',
	function () {
		if ( should_delay_navigation_registration() ) {
			add_action(
				'admin_menu',
				function () {
					commandify_register_navigation_commands();
				},
				9999
			);
			return;
		}

		commandify_register_navigation_commands();
	},
	5
);

/**
 * Register navigation commands.
 *
 * This function encapsulates the existing logic but ensures it only runs once, regardless
 * of whether it's triggered immediately or deferred until after admin_menu.
 */
function commandify_register_navigation_commands() {
	static $registered = false;

	if ( $registered ) {
		return;
	}

	$registered = true;

	global $menu, $submenu;

	// Strategy: Always ensure we have a complete menu structure.
	// 1. If global menu exists (admin context), use it
	// 2. If empty, check cache from previous admin page load
	// 3. If cache also empty, build a minimal menu programmatically

	// Use local variables to avoid modifying globals.
	$current_menu    = null;
	$current_submenu = null;

	if ( ! empty( $menu ) ) {
		// Use global menu (admin context).
		$current_menu    = $menu;
		$current_submenu = $submenu;
	} else {
		// Try cache first.
		$cached_menu = get_transient( 'commandify_menu_data' );
		if ( $cached_menu && ! empty( $cached_menu['menu'] ) ) {
			$current_menu    = $cached_menu['menu'];
			$current_submenu = $cached_menu['submenu'];
		} else {
			// Cache is empty - build a minimal but useful menu programmatically.
			// This provides basic navigation even if admin hasn't been visited yet.
			$built_menu      = build_minimal_wordpress_menu();
			$current_menu    = $built_menu['menu'];
			$current_submenu = $built_menu['submenu'];

			// Cache it for next time.
			if ( ! empty( $current_menu ) ) {
				set_transient(
					'commandify_menu_data',
					array(
						'menu'    => $current_menu,
						'submenu' => $current_submenu,
					),
					HOUR_IN_SECONDS
				);
			}
		}//end if
	}//end if

		// If still empty, skip.
	if ( empty( $current_menu ) ) {
		return;
	}

		$priority = 100;

	foreach ( $current_menu as $menu_item ) {
		// Skip separators and invalid items.
		if ( empty( $menu_item[0] ) || strpos( $menu_item[0], 'separator' ) !== false ) {
			continue;
		}

		// Check if has capablities for the menu item.
		if ( ! empty( $menu_item[1] ) && ! current_user_can( $menu_item[1] ) ) {
			continue;
		}

		// Extract menu data.
		$menu_title_raw = $menu_item[0];
		// Remove all span tags (update badges, counts, etc.) BEFORE stripping tags
		$menu_title_raw = preg_replace( '/<span[^>]*>.*?<\/span>/is', '', $menu_title_raw );
		$menu_title     = wp_strip_all_tags( $menu_title_raw );
		$menu_title     = trim( $menu_title );

		$menu_capability = $menu_item[1] ?? 'read';
		$menu_slug       = $menu_item[2] ?? '';
		$menu_icon       = $menu_item[6] ?? 'dashicons-admin-generic';

		// Build menu URL.
		// menu_page_url() only works for pages registered via add_menu_page().
		// For direct PHP files (like index.php, edit.php), it returns empty string.
		$menu_url = menu_page_url( $menu_slug, false );

		// If menu_page_url() returned empty, build URL manually.
		if ( empty( $menu_url ) ) {
			if ( strpos( $menu_slug, '.php' ) !== false ) {
				// Direct PHP file (e.g., index.php, edit.php, upload.php)
				$menu_url = admin_url( $menu_slug );
			} else {
				// Page slug (e.g., registered via add_menu_page())
				$menu_url = admin_url( 'admin.php?page=' . $menu_slug );
			}
		}

		// Extract icon class (handle both dashicons and custom icons).
		if ( strpos( $menu_icon, 'dashicons-' ) === 0 ) {
			$icon_class = $menu_icon;
		} elseif ( strpos( $menu_icon, 'data:image' ) === 0 || strpos( $menu_icon, 'http' ) === 0 ) {
			$icon_class = $menu_icon;
			// Keep full URL for images
		} else {
			$icon_class = 'dashicons-admin-generic';
		}

		// Generate command ID from slug.
		$command_id = str_replace( array( '_', ' ' ), '-', 'nav-' . sanitize_title( $menu_slug ) );

		// Extract keywords from menu title.
		$title_words = explode( ' ', strtolower( $menu_title ) );
		$keywords    = array_merge( array( 'go to', 'navigate' ), $title_words );

		// Check if this menu has submenus.
		$has_submenu = isset( $current_submenu[ $menu_slug ] ) && ! empty( $current_submenu[ $menu_slug ] );

		if ( $has_submenu ) {
			// Register submenus with parent → child format.
			foreach ( $current_submenu[ $menu_slug ] as $submenu_item ) {
				$submenu_title_raw = $submenu_item[0] ?? '';
				// Remove all span tags (update badges, counts, etc.) BEFORE stripping tags
				$submenu_title_raw = preg_replace( '/<span[^>]*>.*?<\/span>/is', '', $submenu_title_raw );
				$submenu_title     = wp_strip_all_tags( $submenu_title_raw );
				$submenu_title     = trim( $submenu_title );

				// Skip if submenu title is empty.
				if ( empty( $submenu_title ) ) {
					continue;
				}

				$submenu_capability = $submenu_item[1] ?? 'read';
				$submenu_slug       = $submenu_item[2] ?? '';

				// Build submenu URL.
				if ( strpos( $submenu_slug, '.php' ) !== false ) {
					$submenu_url = admin_url( $submenu_slug );
				} else {
					$submenu_url = admin_url( 'admin.php?page=' . $submenu_slug );
				}

				// Hierarchical title format: "Parent → Child".
				$hierarchical_title = $menu_title . ' → ' . $submenu_title;

				// Generate command ID only allowed characters are letters, numbers, and hyphens.
				$submenu_command_id = str_replace( array( '_', ' ' ), '-', 'nav-' . sanitize_title( $menu_slug . '-' . $submenu_slug ) );

				// Extract keywords from both parent and submenu titles.
				$submenu_keywords = array_merge(
					array( 'go to', 'navigate' ),
					explode( ' ', strtolower( $menu_title ) ),
					explode( ' ', strtolower( $submenu_title ) )
				);

					// Determine context for this submenu based on its purpose.
					$submenu_context = array();

					// "Add New", "Add Post", "Add Page" etc. submenus should appear on list screens
				if ( stripos( $submenu_title, 'Add New' ) !== false ||
					stripos( $submenu_title, 'Add Post' ) !== false ||
					stripos( $submenu_title, 'Add Page' ) !== false ||
					stripos( $submenu_title, 'Add ' ) === 0 ) {

					// Extract post type from menu slug.
					if ( strpos( $menu_slug, 'post_type=' ) !== false ) {
						preg_match( '/post_type=([a-z0-9_-]+)/i', $menu_slug, $matches );
						if ( ! empty( $matches[1] ) ) {
							$submenu_context[] = 'edit-' . $matches[1];
							// e.g., edit-page
						}
					} elseif ( 'edit.php' === $menu_slug ) {
						$submenu_context[] = 'edit-post';
						// Posts list page
					} elseif ( 'upload.php' === $menu_slug ) {
						$submenu_context[] = 'upload';
						// Media library
					} elseif ( 'users.php' === $menu_slug ) {
						$submenu_context[] = 'users';
						// Users list page
					}
				}

					// "All X" submenus should appear on edit/new screens
				if ( stripos( $submenu_title, 'All ' ) === 0 ) {
					// Extract post type from menu slug.
					if ( strpos( $menu_slug, 'post_type=' ) !== false ) {
						preg_match( '/post_type=([a-z0-9_-]+)/i', $menu_slug, $matches );
						if ( ! empty( $matches[1] ) ) {
							$post_type         = $matches[1];
							$submenu_context[] = $post_type;
							// e.g., page (edit screen)
							$submenu_context[] = $post_type . '-new';
							// e.g., page-new
						}
					} elseif ( 'edit.php' === $menu_slug ) {
						$submenu_context[] = 'post';
						// Post edit screen
						$submenu_context[] = 'post-new';
						// New post screen
					} elseif ( 'upload.php' === $menu_slug ) {
						$submenu_context[] = 'attachment';
						// Media edit
					} elseif ( 'users.php' === $menu_slug ) {
						$submenu_context[] = 'user-edit';
						// User edit
						$submenu_context[] = 'user-new';
						// New user
					}//end if
				}//end if

					// Build command array.
					$submenu_command = array(
						'id'          => $submenu_command_id,
						'title'       => $hierarchical_title,
						/* translators: %s: Menu item title */
						'description' => sprintf( __( 'Navigate to %s', 'commandify' ), $submenu_title ),
						'type'        => 'navigation',
						'callback'    => $submenu_url,
						'category'    => 'navigation',
						'icon'        => $icon_class,
						'keywords'    => array_unique( $submenu_keywords ),
						'capability'  => $submenu_capability,
						'priority'    => $priority--,
					);

					// Only add context if it has values (don't add empty arrays).
					if ( ! empty( $submenu_context ) ) {
						$submenu_command['context'] = $submenu_context;
					}

					// Register submenu command.
					commandify_register_command( $submenu_command );
			}//end foreach
		} else {
			// Determine context for top-level menus.
			// For custom post types, the top-level menu goes to the list page,.
			// so it should be contextual on edit/new screens
			$menu_context = array();
			if ( strpos( $menu_slug, 'post_type=' ) !== false ) {
				preg_match( '/post_type=([a-z0-9_-]+)/i', $menu_slug, $matches );
				if ( ! empty( $matches[1] ) ) {
					$post_type      = $matches[1];
					$menu_context[] = $post_type;
					// Edit screen (e.g., ap_announcement)
					$menu_context[] = $post_type . '-new';
					// New screen (e.g., ap_announcement-new)
				}
			}

			// Build command array.
			$menu_command = array(
				'id'          => $command_id,
				'title'       => $menu_title,
				/* translators: %s: Menu item title */
				'description' => sprintf( __( 'Navigate to %s', 'commandify' ), $menu_title ),
				'type'        => 'navigation',
				'callback'    => $menu_url,
				'category'    => 'navigation',
				'icon'        => $icon_class,
				'keywords'    => array_unique( $keywords ),
				'capability'  => $menu_capability,
				'priority'    => $priority--,
			);

			// Only add context if it has values.
			if ( ! empty( $menu_context ) ) {
				$menu_command['context'] = $menu_context;
			}

			// Register top-level menu without submenus.
			commandify_register_command( $menu_command );
		}//end if
	}//end foreach
}
