<?php
/**
 * Admin Dashboard Message Widget
 *
 * Registers a WordPress Dashboard widget that displays a configurable broadcast
 * message to all users who can access wp-admin/index.php. The widget is only
 * registered when the `enabled` flag in the stored option is true.
 *
 * @package Agency_Pulse_Admin_Menu
 * @since   1.0.0
 */

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

class Agency_Pulse_Admin_Menu_Dashboard_Widget {

	// -------------------------------------------------------------------------
	// Initialisation
	// -------------------------------------------------------------------------

	/**
	 * Register the wp_dashboard_setup hook.
	 *
	 * Called from Agency_Pulse_Admin_Menu::setup_hooks() during plugins_loaded.
	 *
	 * @since 1.0.0
	 */
	public static function init(): void {
		add_action( 'wp_dashboard_setup', array( __CLASS__, 'register' ) );
		// Reorder after all plugins have added their widgets.
		add_action( 'wp_dashboard_setup', array( __CLASS__, 'reorder' ), 999 );
		// Force first position even for users who have a stored layout preference.
		add_filter( 'get_user_option_meta-box-order_dashboard', array( __CLASS__, 'force_first_in_stored_order' ) );
	}

	// -------------------------------------------------------------------------
	// Widget registration
	// -------------------------------------------------------------------------

	/**
	 * Register the dashboard widget if the feature is enabled.
	 *
	 * Reads the stored option (autoloaded) and returns early when disabled so
	 * no widget slot is consumed on the dashboard.
	 *
	 * @since 1.0.0
	 */
	public static function register(): void {
		$data = get_option(
			Agency_Pulse_Admin_Menu_Constants::OPTION_DASHBOARD_MESSAGE,
			array( 'enabled' => false )
		);

		if ( empty( $data['enabled'] ) ) {
			return;
		}

		$title = ! empty( $data['title'] )
			? sanitize_text_field( $data['title'] )
			: __( 'Admin Notice', 'agency-pulse-admin-menu' );

		wp_add_dashboard_widget(
			'aamo_dashboard_message',
			esc_html( $title ),
			array( __CLASS__, 'render' )
		);
	}

	// -------------------------------------------------------------------------
	// Position enforcement
	// -------------------------------------------------------------------------

	/**
	 * Move the widget to the front of the normal/high slot in $wp_meta_boxes.
	 *
	 * Runs at wp_dashboard_setup priority 999 so all other plugins have already
	 * registered their widgets. This sets the default order for users who have
	 * no stored layout preference.
	 *
	 * @since 1.0.0
	 */
	public static function reorder(): void {
		global $wp_meta_boxes;

		$data = get_option( Agency_Pulse_Admin_Menu_Constants::OPTION_DASHBOARD_MESSAGE, array() );
		if ( empty( $data['show_first'] ) ) {
			return;
		}

		$widget_id = 'aamo_dashboard_message';

		if ( empty( $wp_meta_boxes['dashboard'] ) ) {
			return;
		}

		// Locate and remove the widget from wherever WordPress placed it.
		$entry      = null;
		$source_col = null;
		$source_pri = null;

		foreach ( $wp_meta_boxes['dashboard'] as $col => $priorities ) {
			foreach ( $priorities as $priority => $widgets ) {
				if ( isset( $widgets[ $widget_id ] ) ) {
					$entry      = $widgets[ $widget_id ];
					$source_col = $col;
					$source_pri = $priority;
					break 2;
				}
			}
		}

		if ( null === $entry ) {
			return; // Widget wasn't registered (feature is disabled).
		}

		unset( $wp_meta_boxes['dashboard'][ $source_col ][ $source_pri ][ $widget_id ] );

		// Prepend to normal/high — creates the priority bucket if needed.
		if ( ! isset( $wp_meta_boxes['dashboard']['normal']['high'] ) ) {
			$wp_meta_boxes['dashboard']['normal']['high'] = array();
		}

		$wp_meta_boxes['dashboard']['normal']['high'] = array_merge(
			array( $widget_id => $entry ),
			$wp_meta_boxes['dashboard']['normal']['high']
		);
	}

	/**
	 * Filter the user's stored dashboard widget order to keep our widget first.
	 *
	 * WordPress stores each user's drag-and-drop arrangement in user meta under
	 * `meta-box-order_dashboard`. This filter runs on every dashboard page load
	 * and ensures the widget always appears at the top of the left (normal) column,
	 * regardless of what the user may have dragged it to previously.
	 *
	 * @since 1.0.0
	 * @param array|false $order Stored order array (col => comma-separated widget IDs), or false.
	 * @return array|false
	 */
	public static function force_first_in_stored_order( $order ) {
		$data = get_option(
			Agency_Pulse_Admin_Menu_Constants::OPTION_DASHBOARD_MESSAGE,
			array( 'enabled' => false )
		);

		if ( empty( $data['enabled'] ) || empty( $data['show_first'] ) ) {
			return $order;
		}

		$widget_id = 'aamo_dashboard_message';

		if ( ! is_array( $order ) ) {
			$order = array();
		}

		// Remove the widget from any column it currently sits in.
		foreach ( $order as $col => $ids_string ) {
			$ids          = array_filter( explode( ',', $ids_string ) );
			$ids          = array_values( array_diff( $ids, array( $widget_id ) ) );
			$order[ $col ] = implode( ',', $ids );
		}

		// Prepend to the normal (left) column.
		$normal_ids = array_filter( explode( ',', $order['normal'] ?? '' ) );
		array_unshift( $normal_ids, $widget_id );
		$order['normal'] = implode( ',', $normal_ids );

		return $order;
	}

	// -------------------------------------------------------------------------
	// Widget rendering
	// -------------------------------------------------------------------------

	/**
	 * Render the dashboard widget body.
	 *
	 * Content is passed through wp_kses_post() so only safe HTML tags remain.
	 *
	 * @since 1.0.0
	 */
	public static function render(): void {
		$data    = get_option( Agency_Pulse_Admin_Menu_Constants::OPTION_DASHBOARD_MESSAGE, array() );
		$content = ! empty( $data['content'] ) ? $data['content'] : '';
		echo wp_kses_post( $content );
	}
}
