<?php
/**
 * Notice Manager — FREE
 *
 * Hides WordPress core and plugin admin notices for non-admin users.
 *
 * KEY FIX: before wiping admin_notices, this module saves any callback
 * registered by an Pnlrdb* class (e.g. Role Preview banner) and
 * re-attaches it after the wipe, so our own UI is never accidentally hidden.
 *
 * @package Panelra
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class Pnlrdb_Notice_Manager
 */
class Pnlrdb_Notice_Manager {

	/** Class-name prefix used to identify callbacks we must never remove. */
	const PROTECTED_PREFIX = 'Pnlrdb';

	/**
	 * Register hooks.
	 */
	public function __construct() {
		add_action( 'current_screen', array( $this, 'maybe_boot_notice_hiding' ) );
	}

	/**
	 * Decide whether notice hiding should be activated for this request.
	 *
	 * @param WP_Screen $screen Current screen object.
	 * @return void
	 */
	public function maybe_boot_notice_hiding( $screen ) {
		if ( ! $screen || ! is_object( $screen ) ) {
			return;
		}

		// Never hide notices on the Panelra settings page.
		$page = isset( $_GET['page'] ) ? sanitize_key( $_GET['page'] ) : ''; // phpcs:ignore
		if ( 'pnlrdb-settings' === $page ) {
			return;
		}

		// Builder-driven suppression on the dashboard.
		$layout = class_exists( 'Pnlrdb_Dashboard_Builder' )
			? Pnlrdb_Dashboard_Builder::get_layout()
			: array();

		$builder_hide = (
			isset( $screen->base ) &&
			'dashboard' === $screen->base &&
			! empty( $layout['enabled'] ) &&
			! empty( $layout['hide_notices'] )
		);

		if ( $builder_hide ) {
			add_action( 'admin_print_scripts', array( $this, 'remove_notice_hooks' ), 1 );
			add_action( 'admin_enqueue_scripts', array( $this, 'print_hide_css' ), 999 );
			remove_action( 'welcome_panel', 'wp_welcome_panel' );
			return;
		}

		if ( current_user_can( 'manage_options' ) ) {
			return;
		}

		if ( ! get_option( 'pnlrdb_hide_notices', 0 ) ) {
			return;
		}

		add_action( 'admin_print_scripts', array( $this, 'remove_notice_hooks' ), 1 );
		add_action( 'admin_enqueue_scripts', array( $this, 'print_hide_css' ), 999 );

		if ( isset( $screen->base ) && 'dashboard' === $screen->base ) {
			remove_action( 'welcome_panel', 'wp_welcome_panel' );
		}
	}

	/**
	 * Remove all notice hooks EXCEPT those registered by Pnlrdb* classes.
	 *
	 * Saves Pnlrdb callbacks from admin_notices / all_admin_notices,
	 * clears everything, then re-attaches the saved callbacks at their
	 * original priority. This preserves the Role Preview banner.
	 *
	 * @return void
	 */
	public function remove_notice_hooks() {
		global $wp_filter;

		$hooks = array(
			'admin_notices',
			'all_admin_notices',
			'network_admin_notices',
			'user_admin_notices',
		);

		foreach ( $hooks as $hook ) {
			if ( empty( $wp_filter[ $hook ] ) ) {
				continue;
			}

			// Collect callbacks registered by Pnlrdb* classes.
			$preserved = array();
			foreach ( $wp_filter[ $hook ]->callbacks as $priority => $items ) {
				foreach ( $items as $item ) {
					$fn = $item['function'];
					if (
						is_array( $fn ) &&
						isset( $fn[0] ) &&
						is_object( $fn[0] ) &&
						strpos( get_class( $fn[0] ), self::PROTECTED_PREFIX ) === 0
					) {
						$preserved[] = array( $priority, $fn, $item['accepted_args'] );
					}
				}
			}

			remove_all_actions( $hook );

			// Re-attach preserved callbacks.
			foreach ( $preserved as list( $prio, $fn, $args ) ) {
				add_action( $hook, $fn, $prio, $args );
			}
		}
	}

	/**
	 * Print CSS to hide remaining notices.
	 * Explicitly excludes #ap773pro-rp-banner (Role Preview) via :not().
	 *
	 * @return void
	 */
	public function print_hide_css() {
		$css = '.notice:not(#ap773pro-rp-banner),'
			. '.notice-error,.notice-warning,.notice-success,.notice-info,'
			. '.updated,.update-nag,.error,div.error,div.updated,#update-nag,'
			. '.update-message,.wrap > .notice,.wrap > .updated,.wrap > .error,'
			. '.e-notice,.e-notice__wrapper,.e-admin-top-bar,'
			. '.elementor-notice,.elementor-message,'
			. '.fs-notice,.sui-notice,.components-notice'
			. '{display:none !important;}';
		wp_register_style( 'pnlrdb-hide-notices', false, array(), PNLRDB_VERSION );
		wp_enqueue_style( 'pnlrdb-hide-notices' );
		wp_add_inline_style( 'pnlrdb-hide-notices', $css );
	}
}
