<?php
/**
 * Plugin-owned admin notices.
 *
 * @package SubmissionInbox
 */

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

/**
 * Stores one-time admin notices across redirects and renders them consistently.
 */
class SUBIN_AdminNotices {
	const USER_META_KEY = '_subin_admin_notices';

	/**
	 * Store a notice for the next plugin admin page load.
	 *
	 * @param string $message Notice message.
	 * @param string $type Notice type.
	 * @param string $code Optional notice code.
	 * @return void
	 */
	public static function flash( $message, $type = 'success', $code = '' ) {
		$message = trim( wp_strip_all_tags( (string) $message ) );
		if ( '' === $message ) {
			return;
		}

		$user_id = get_current_user_id();
		if ( $user_id <= 0 ) {
			return;
		}

		$notices   = self::stored_notices( $user_id );
		$notices[] = array(
			'message' => $message,
			'type'    => self::normalize_type( $type ),
			'code'    => sanitize_key( $code ),
			'time'    => time(),
		);

		update_user_meta( $user_id, self::USER_META_KEY, array_slice( $notices, -5 ) );
	}

	/**
	 * Render and consume flashed notices.
	 *
	 * @return void
	 */
	public static function render() {
		$notices = self::consume();
		if ( empty( $notices ) ) {
			return;
		}
		?>
		<div class="subin-admin-notices" aria-live="polite">
			<?php foreach ( $notices as $notice ) : ?>
				<?php self::render_notice( (string) $notice['message'], (string) $notice['type'] ); ?>
			<?php endforeach; ?>
		</div>
		<?php
	}

	/**
	 * Render existing WordPress settings errors with plugin-owned markup.
	 *
	 * This keeps existing add_settings_error() call sites working while avoiding
	 * the hidden WordPress .notice markup on InboxMend admin screens.
	 *
	 * @param string $setting Settings error group.
	 * @return void
	 */
	public static function render_settings_errors( $setting = 'subin_messages' ) {
		$errors = get_settings_errors( $setting );
		if ( empty( $errors ) ) {
			return;
		}

		?>
		<div class="subin-admin-notices" aria-live="polite">
			<?php foreach ( $errors as $error ) : ?>
				<?php
				$message = isset( $error['message'] ) ? (string) $error['message'] : '';
				$type    = isset( $error['type'] ) ? (string) $error['type'] : 'info';
				self::render_notice( $message, $type );
				?>
			<?php endforeach; ?>
		</div>
		<?php
	}

	/**
	 * Render a single non-flash notice.
	 *
	 * @param string $message Notice message.
	 * @param string $type Notice type.
	 * @return void
	 */
	public static function render_notice( $message, $type = 'success' ) {
		$message = trim( (string) $message );
		if ( '' === $message ) {
			return;
		}

		$type = self::normalize_type( $type );
		?>
		<div class="subin-admin-notice subin-admin-notice--<?php echo esc_attr( $type ); ?>" role="<?php echo 'error' === $type ? 'alert' : 'status'; ?>">
			<p><?php echo esc_html( $message ); ?></p>
		</div>
		<?php
	}

	/**
	 * Read and remove stored notices.
	 *
	 * @return array<int,array{message:string,type:string,code:string,time:int}>
	 */
	private static function consume() {
		$user_id = get_current_user_id();
		if ( $user_id <= 0 ) {
			return array();
		}

		$notices = self::stored_notices( $user_id );
		delete_user_meta( $user_id, self::USER_META_KEY );

		return $notices;
	}

	/**
	 * Get stored notices for a user.
	 *
	 * @param int $user_id User id.
	 * @return array<int,array{message:string,type:string,code:string,time:int}>
	 */
	private static function stored_notices( $user_id ) {
		$stored = get_user_meta( $user_id, self::USER_META_KEY, true );
		if ( ! is_array( $stored ) ) {
			return array();
		}

		$notices = array();
		foreach ( $stored as $notice ) {
			if ( ! is_array( $notice ) || empty( $notice['message'] ) ) {
				continue;
			}

			$notices[] = array(
				'message' => trim( wp_strip_all_tags( (string) $notice['message'] ) ),
				'type'    => self::normalize_type( (string) ( $notice['type'] ?? 'success' ) ),
				'code'    => sanitize_key( (string) ( $notice['code'] ?? '' ) ),
				'time'    => absint( $notice['time'] ?? 0 ),
			);
		}

		return $notices;
	}

	/**
	 * Normalize notice type.
	 *
	 * @param string $type Raw type.
	 * @return string
	 */
	private static function normalize_type( $type ) {
		$type = sanitize_key( $type );
		if ( 'updated' === $type ) {
			return 'success';
		}

		if ( in_array( $type, array( 'success', 'error', 'warning', 'info' ), true ) ) {
			return $type;
		}

		return 'success';
	}
}
