<?php
/**
 * Admin Menu
 *
 * Handles registration of WP PowerSuite admin menu and pages.
 * Registers the menu as a top-level menu item.
 *
 * @package WP_PowerSuite\Core
 * @since 1.0.0
 */

namespace WP_PowerSuite\Core;

use WP_PowerSuite\Admin\BrandAssets;

/**
 * Admin Menu Class
 *
 * Manages admin menu registration and page rendering.
 * Only loads in admin context and respects capability checks.
 *
 * @since 1.0.0
 */
class AdminMenu {

	/**
	 * Admin Menu Instance
	 *
	 * Singleton instance of the AdminMenu class.
	 *
	 * @var AdminMenu|null
	 * @since 1.0.0
	 */
	private static ?AdminMenu $instance = null;

	/**
	 * Page Slug
	 *
	 * The admin page slug identifier.
	 *
	 * @var string
	 * @since 1.0.0
	 */
	private string $page_slug = 'powersuite';

	/**
	 * Required Capability
	 *
	 * Capability required to access the admin page.
	 *
	 * @var string
	 * @since 1.0.0
	 */
	private string $capability = 'manage_options';

	/**
	 * Menu Hook Suffix
	 *
	 * WordPress hook suffix for the admin page.
	 *
	 * @var string|null
	 * @since 1.0.0
	 */
	private ?string $menu_hook_suffix = null;

	/**
	 * Initialization Flag
	 *
	 * Tracks whether the admin menu has been initialized.
	 *
	 * @var bool
	 * @since 1.0.0
	 */
	private bool $initialized = false;

	/**
	 * Get Admin Menu Instance
	 *
	 * Returns the singleton instance of the AdminMenu class.
	 *
	 * @since 1.0.0
	 * @return AdminMenu AdminMenu instance.
	 */
	public static function getInstance(): AdminMenu {
		if ( self::$instance === null ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Constructor
	 *
	 * Private constructor to enforce singleton pattern.
	 *
	 * @since 1.0.0
	 */
	private function __construct() {
		// Constructor is private to prevent direct instantiation
	}

	/**
	 * Prevent Cloning
	 *
	 * Prevents cloning of the singleton instance.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	private function __clone() {
		// Prevent cloning
	}

	/**
	 * Prevent Unserialization
	 *
	 * Prevents unserialization of the singleton instance.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public function __wakeup(): void {
		throw new \Exception( 'Cannot unserialize singleton' );
	}

	/**
	 * Initialize Admin Menu
	 *
	 * Registers the admin menu and hooks. Should only be called
	 * in admin context.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public function init(): void {
		// Prevent multiple initializations
		if ( $this->initialized ) {
			return;
		}

		// Only initialize in admin context
		if ( ! is_admin() ) {
			return;
		}

		$this->capability = NetworkScope::adminCapability();

		// Register admin menu (network-wide when the plugin is network-activated)
		add_action( NetworkScope::adminMenuHook(), [ $this, 'registerMenu' ] );
		add_action( NetworkScope::adminHeadHook(), [ $this, 'injectMenuIconStyles' ] );

		$this->initialized = true;
	}

	/**
	 * Register Admin Menu
	 *
	 * Registers the WP PowerSuite as a top-level menu item.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public function registerMenu(): void {
		if ( ! current_user_can( $this->capability ) ) {
			return;
		}

		// Same-origin menu icon (bundled SVG, or dashicons fallback).
		$menu_icon = BrandAssets::admin_menu_icon();
		$menu_name = WhiteLabel::menuTitle();
		$page_name = WhiteLabel::pluginName();
		$this->menu_hook_suffix = add_menu_page(
			$page_name,                                      // Page title
			$menu_name,                                      // Menu title
			$this->capability,                               // Capability
			$this->page_slug,                               // Menu slug
			[ $this, 'renderPage' ],                         // Callback
			$menu_icon,                                      // Icon (dashicons or local URL)
			30                                                // Position (after Settings)
		);

		add_submenu_page(
			$this->page_slug,                               // Parent slug
			__( 'Modules', 'wp-powersuite' ),               // Page title
			__( 'Modules', 'wp-powersuite' ),                // Menu title
			$this->capability,                               // Capability
			$this->page_slug,                               // Menu slug (same as main page)
			[ $this, 'renderPage' ]                          // Callback
		);

		add_submenu_page(
			$this->page_slug,                               // Parent slug
			__( 'Settings', 'wp-powersuite' ),              // Page title
			__( 'Settings', 'wp-powersuite' ),               // Menu title
			$this->capability,                               // Capability
			'powersuite-settings',                           // Menu slug
			[ $this, 'renderSettingsPage' ]                  // Callback
		);

		$this->registerHiddenPerformancePage();
		$this->registerHiddenWhiteLabelPage();
		$this->registerLicensePage();
	}

	/**
	 * Register License screen — visible submenu or hidden direct-access page.
	 */
	private function registerLicensePage(): void {
		if ( ! class_exists( 'WPPS_License_Manager', false ) ) {
			return;
		}

		$parent = WhiteLabel::shouldHideLicenseMenu() ? null : $this->page_slug;

		add_submenu_page(
			$parent,
			__( 'License', 'wp-powersuite' ),
			WhiteLabel::shouldHideLicenseMenu() ? '' : __( 'License', 'wp-powersuite' ),
			$this->capability,
			WhiteLabel::LICENSE_PAGE_SLUG,
			[ $this, 'renderLicensePage' ]
		);
	}

	/**
	 * Hidden White Label settings page (direct URL access when tab is hidden).
	 */
	private function registerHiddenWhiteLabelPage(): void {
		add_submenu_page(
			null,
			__( 'White Label', 'wp-powersuite' ),
			'',
			$this->capability,
			WhiteLabel::WHITE_LABEL_PAGE_SLUG,
			[ $this, 'renderWhiteLabelPage' ]
		);
	}

	/**
	 * Register the Performance Monitor screen without adding a sidebar menu item.
	 *
	 * Uses a null parent slug so WordPress exposes the admin.php?page= URL only.
	 * Skipped entirely when the feature is disabled in Settings.
	 */
	private function registerHiddenPerformancePage(): void {
		if ( ! OptionStore::getInstance()->isPerformanceMonitorEnabled() ) {
			return;
		}

		add_submenu_page(
			null,
			__( 'Performance Monitor', 'wp-powersuite' ),
			'',
			$this->capability,
			PerformanceBudgetConfig::PERFORMANCE_ADMIN_PAGE,
			[ $this, 'renderPerformancePage' ]
		);
	}

	/**
	 * URL for the hidden Performance Monitor screen.
	 */
	public static function performanceMonitorUrl(): string {
		return admin_url( 'admin.php?page=' . PerformanceBudgetConfig::PERFORMANCE_ADMIN_PAGE );
	}

	/**
	 * Inject CSS to resize admin menu icon (custom URL icons display too large by default).
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public function injectMenuIconStyles(): void {
		$menu_icon = BrandAssets::admin_menu_icon();
		if ( BrandAssets::is_dashicon_menu_icon( $menu_icon ) ) {
			return;
		}

		$slug = sanitize_html_class( $this->page_slug );
		?>
		<style>
			#adminmenu #toplevel_page_<?php echo esc_attr( $slug ); ?> .wp-menu-image img {
				width: 20px;
				height: 20px;
				padding: 7px 0 0;
				opacity: 0.6;
			}
			#adminmenu #toplevel_page_<?php echo esc_attr( $slug ); ?> .wp-menu-image {
				background-size: 20px 20px !important;
				background-position: center center !important;
			}
			#adminmenu #toplevel_page_<?php echo esc_attr( $slug ); ?>.current .wp-menu-image img,
			#adminmenu #toplevel_page_<?php echo esc_attr( $slug ); ?>.wp-has-current-submenu .wp-menu-image img {
				opacity: 1;
			}
		</style>
		<?php
	}

	/**
	 * Render Admin Page
	 *
	 * Renders the main admin page content. Loads the view template.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public function renderPage(): void {
		// Check capability again (security)
		if ( ! current_user_can( $this->capability ) ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'wp-powersuite' ) );
		}

		$this->loadView();
	}

	/**
	 * Render Performance Page
	 *
	 * Renders the performance dashboard page.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public function renderPerformancePage(): void {
		if ( ! current_user_can( $this->capability ) ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'wp-powersuite' ) );
		}

		if ( ! OptionStore::getInstance()->isPerformanceMonitorEnabled() ) {
			wp_safe_redirect( admin_url( 'admin.php?page=powersuite-settings' ) );
			exit;
		}

		$this->loadPerformanceView();
	}

	/**
	 * Load View Template
	 *
	 * Loads and renders the admin page view template.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	private function loadView(): void {
		$view_file = $this->getViewPath();

		if ( ! file_exists( $view_file ) || ! is_readable( $view_file ) ) {
			wp_die(
				sprintf(
					'<h1>%s</h1><p>%s</p>',
					esc_html__( 'Error', 'wp-powersuite' ),
					esc_html__( 'View template not found.', 'wp-powersuite' )
				)
			);
		}

		// Extract variables for the view
		$plugin_name = WhiteLabel::pluginName();
		$page_title  = WhiteLabel::dashboardTitle();

		// Include the view template
		include $view_file;
	}

	/**
	 * Get View Path
	 *
	 * Returns the absolute path to the admin view template.
	 *
	 * @since 1.0.0
	 * @return string View file path.
	 */
	private function getViewPath(): string {
		$plugin_dir = defined( 'WP_POWERSUITE_PLUGIN_DIR' )
			? WP_POWERSUITE_PLUGIN_DIR
			: '';

		return $plugin_dir . 'src' . DIRECTORY_SEPARATOR . 'Admin' . DIRECTORY_SEPARATOR . 'Views' . DIRECTORY_SEPARATOR . 'app.php';
	}

	/**
	 * Load Performance View Template
	 *
	 * Loads and renders the performance dashboard view template.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	private function loadPerformanceView(): void {
		$plugin_dir = defined( 'WP_POWERSUITE_PLUGIN_DIR' )
			? WP_POWERSUITE_PLUGIN_DIR
			: '';

		$default_view = $plugin_dir . 'src' . DIRECTORY_SEPARATOR . 'Admin' . DIRECTORY_SEPARATOR . 'Views' . DIRECTORY_SEPARATOR . 'performance.php';

		/**
		 * Override the Performance Monitor admin view path (developer companion plugin).
		 *
		 * @param string $view_file Absolute path to the view template.
		 */
		$view_file = (string) apply_filters( 'wp_powersuite_performance_view_file', $default_view );

		if ( ! file_exists( $view_file ) || ! is_readable( $view_file ) ) {
			wp_die(
				sprintf(
					'<h1>%s</h1><p>%s</p>',
					esc_html__( 'Error', 'wp-powersuite' ),
					esc_html__( 'Performance view template not found. Activate WP PowerSuite Dev — Performance Monitor.', 'wp-powersuite' )
				)
			);
		}

		// Extract variables for the view
		$plugin_name = WhiteLabel::pluginName();
		$page_title  = __( 'Performance Monitor', 'wp-powersuite' );

		// Include the view template
		include $view_file;
	}

	/**
	 * Get Page Slug
	 *
	 * Returns the admin page slug.
	 *
	 * @since 1.0.0
	 * @return string Page slug.
	 */
	public function getPageSlug(): string {
		return $this->page_slug;
	}

	/**
	 * Get Menu Hook Suffix
	 *
	 * Returns the WordPress hook suffix for the admin page.
	 *
	 * @since 1.0.0
	 * @return string|null Hook suffix or null if not registered.
	 */
	public function getMenuHookSuffix(): ?string {
		return $this->menu_hook_suffix;
	}

	/**
	 * Set Required Capability
	 *
	 * Sets the capability required to access the admin page.
	 *
	 * @since 1.0.0
	 * @param string $capability Capability name.
	 * @return void
	 */
	public function setCapability( string $capability ): void {
		$this->capability = $capability;
	}

	/**
	 * Get Required Capability
	 *
	 * Returns the capability required to access the admin page.
	 *
	 * @since 1.0.0
	 * @return string Capability name.
	 */
	public function getCapability(): string {
		return $this->capability;
	}

	/**
	 * Check if Admin Menu is Initialized
	 *
	 * Returns whether the admin menu has been initialized.
	 *
	 * @since 1.0.0
	 * @return bool True if initialized, false otherwise.
	 */
	public function isInitialized(): bool {
		return $this->initialized;
	}

	/**
	 * Render License Page
	 *
	 * Renders the license activation or license info page.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public function renderLicensePage(): void {
		if ( ! WhiteLabel::canAccessHiddenPages() ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'wp-powersuite' ), 403 );
		}

		$manager = \WPPS_License_Manager::get_instance();
		$manager->sync_for_admin_page();
		$is_valid   = $manager->is_valid();
		$status     = $manager->get_status_data();
		$status_key = sanitize_key( $status['status'] ?? ( $is_valid ? 'active' : 'inactive' ) );
		if ( $is_valid && ! in_array( $status_key, [ 'active', 'grace', 'expired' ], true ) ) {
			$status_key = 'active';
		}
		$status_labels = [
			'active'           => __( 'Active', 'wp-powersuite' ),
			'inactive'         => __( 'Inactive', 'wp-powersuite' ),
			'expired'          => __( 'Expired', 'wp-powersuite' ),
			'invalid'          => __( 'Invalid', 'wp-powersuite' ),
			'connection_issue' => __( 'Connection issue', 'wp-powersuite' ),
			'grace'            => __( 'Grace period', 'wp-powersuite' ),
			'unknown'          => __( 'Unknown', 'wp-powersuite' ),
		];

		echo '<div class="wrap wpps-admin-wrap">';
		echo '<hr class="wp-header-end" style="margin:0;padding:0;border:none;height:0;overflow:hidden;">';

		echo '<div class="wpps-license-page wpps-license-page__hero">';
		\WP_PowerSuite\Admin\PageHero::render(
			[
				'eyebrow'         => '',
				'title'           => __( 'License', 'wp-powersuite' ),
				'tagline'         => $is_valid
					? __( 'Premium access is stored locally after activation. The license server is checked periodically for revocations; renew to receive updates.', 'wp-powersuite' )
					: __( 'Activate your license to unlock premium modules. Updates require an active subscription.', 'wp-powersuite' ),
				'icon'            => 'dashicons-admin-network',
				'status'          => $status_labels[ $status_key ] ?? $status_labels['unknown'],
				'status_inactive' => ! $is_valid && ! in_array( $status_key, [ 'active', 'grace', 'expired' ], true ),
				'actions'         => \WP_PowerSuite\Admin\PageHero::nav_actions( 'license' ),
			]
		);
		echo '</div>';

		if ( $is_valid ) {
			$manager->render_license_info();
		} else {
			$manager->render_activation_form();
		}

		echo '</div>';
	}

	/**
	 * Render Settings Page
	 *
	 * Renders the settings page content.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public function renderSettingsPage(): void {
		if ( ! WhiteLabel::canAccessHiddenPages() ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'wp-powersuite' ), 403 );
		}

		$tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'general';
		if ( $tab === 'white-label' && WhiteLabel::shouldHideWhiteLabelSettings() ) {
			wp_safe_redirect( WhiteLabel::whiteLabelDirectUrl() );
			exit;
		}

		$this->loadSettingsView();
	}

	/**
	 * Render standalone White Label settings (hidden admin page).
	 */
	public function renderWhiteLabelPage(): void {
		if ( ! WhiteLabel::canAccessHiddenPages() ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'wp-powersuite' ), 403 );
		}

		$view_file = defined( 'WP_POWERSUITE_PLUGIN_DIR' )
			? WP_POWERSUITE_PLUGIN_DIR . 'src/Admin/Views/white-label.php'
			: '';

		if ( $view_file === '' || ! is_readable( $view_file ) ) {
			wp_die( esc_html__( 'White Label view template not found.', 'wp-powersuite' ) );
		}

		include $view_file;
	}

	/**
	 * Load Settings View Template
	 *
	 * Loads and renders the settings page view template.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	private function loadSettingsView(): void {
		$view_file = $this->getSettingsViewPath();

		if ( ! file_exists( $view_file ) || ! is_readable( $view_file ) ) {
			wp_die(
				sprintf(
					'<h1>%s</h1><p>%s</p>',
					esc_html__( 'Error', 'wp-powersuite' ),
					esc_html__( 'Settings view template not found.', 'wp-powersuite' )
				)
			);
		}

		// Include the view template
		include $view_file;
	}

	/**
	 * Get Settings View Path
	 *
	 * Returns the absolute path to the settings view template.
	 *
	 * @since 1.0.0
	 * @return string View file path.
	 */
	private function getSettingsViewPath(): string {
		$plugin_dir = defined( 'WP_POWERSUITE_PLUGIN_DIR' )
			? WP_POWERSUITE_PLUGIN_DIR
			: '';

		return $plugin_dir . 'src' . DIRECTORY_SEPARATOR . 'Admin' . DIRECTORY_SEPARATOR . 'Views' . DIRECTORY_SEPARATOR . 'settings.php';
	}

	/**
	 * Screen / hook suffix for the hidden Performance Monitor page (null parent submenu).
	 */
	public static function performanceMonitorScreenId(): string {
		return 'admin_page_' . PerformanceBudgetConfig::PERFORMANCE_ADMIN_PAGE;
	}

	/**
	 * Whether the given admin screen belongs to WP PowerSuite.
	 *
	 * Uses WordPress screen IDs only (not $_GET) so conditional asset loading
	 * cannot be influenced by spoofed query arguments.
	 *
	 * @since 1.0.0
	 */
	public static function isPowerSuiteAdminScreen( ?\WP_Screen $screen = null ): bool {
		if ( ! is_admin() ) {
			return false;
		}

		if ( $screen === null && function_exists( 'get_current_screen' ) ) {
			$screen = get_current_screen();
		}

		if ( ! $screen instanceof \WP_Screen || ! is_string( $screen->id ) ) {
			return false;
		}

		return self::isPowerSuiteScreenId( $screen->id );
	}

	/**
	 * Whether an admin.php?page= slug belongs to WP PowerSuite.
	 */
	public static function isPowerSuitePageSlug( string $page_slug ): bool {
		$page_slug = sanitize_key( $page_slug );

		if ( $page_slug === '' ) {
			return false;
		}

		return $page_slug === 'powersuite'
			|| $page_slug === WhiteLabel::WHITE_LABEL_PAGE_SLUG
			|| str_starts_with( $page_slug, 'powersuite-' );
	}

	/**
	 * Whether a WordPress admin screen ID belongs to WP PowerSuite.
	 */
	public static function isPowerSuiteScreenId( string $screen_id ): bool {
		if ( $screen_id === 'toplevel_page_powersuite' ) {
			return true;
		}

		if ( $screen_id === self::performanceMonitorScreenId() ) {
			return true;
		}

		if ( $screen_id === 'admin_page_' . WhiteLabel::WHITE_LABEL_PAGE_SLUG ) {
			return true;
		}

		if ( str_starts_with( $screen_id, 'wp-powersuite_page_' ) ) {
			return true;
		}

		// Legacy hook prefix when the parent hook resolves to the menu slug.
		if ( str_starts_with( $screen_id, 'powersuite_page_' ) ) {
			return true;
		}

		// White-label menu titles change sanitize_title( menu_title ), which WordPress uses
		// as the submenu hook prefix (e.g. acme-suite_page_powersuite-settings).
		return preg_match( '/_page_powersuite(-|$)/', $screen_id ) === 1;
	}

	/**
	 * Whether an admin page hook suffix belongs to WP PowerSuite.
	 *
	 * @since 1.0.0
	 */
	public static function isPowerSuiteHookSuffix( string $hook_suffix ): bool {
		return self::isPowerSuiteScreenId( $hook_suffix );
	}

	/**
	 * Is Current Page
	 *
	 * Checks if the current admin page is the WP PowerSuite page.
	 *
	 * @since 1.0.0
	 * @return bool True if current page, false otherwise.
	 */
	public function isCurrentPage(): bool {
		if ( ! is_admin() ) {
			return false;
		}

		$screen = get_current_screen();
		if ( ! $screen ) {
			return false;
		}

		if ( $this->menu_hook_suffix && $screen->id === $this->menu_hook_suffix ) {
			return true;
		}

		return self::isPowerSuiteAdminScreen( $screen );
	}
}

