<?php
if (!defined('ABSPATH')) {
	exit;
}

/********************************************************************
 * Copyright (C) 2025 Hassine RIANI (https://upvimeo.com)
 *
 * This file is part of Upvimeo
 *
 * Upvimeo is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * Upvimeo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Upvimeo. If not, see <https://www.gnu.org/licenses/>.
 **********************************************************************/

/**
 * Class UpVimeo_Notices_Helper
 *
 * Responsible for displaying notices in the admin dashboard
 *
 * @license GPLv2
 * @copyright Hassine RIANI (https://upvimeo.com)
 * @since 1.0.0
 */
class UpVimeo_Notices_Helper
{

	/**
	 * The plugin name
	 * @var string
	 */
	private $title = 'Upvimeo';

	/**
	 * The notices prefix
	 * @var string
	 */
	private $prefix = 'upvimeo_';

	/**
	 * Dismiss expiry
	 * @var int
	 */
	private $expiry = 8640000;

	/**
	 * @var UpVimeo_Notices_Helper
	 */
	private static $_instance;

	/**
	 * The queue of notices
	 * @var stdClass
	 */
	private $admin_notices;

	/**
	 * Notice types
	 */
	const TYPES = 'error,warning,info,success';

	/**
	 * MGO_Admin_Notices constructor.
	 */
	private function __construct()
	{
		$this->admin_notices = new stdClass();
		foreach (explode(',', self::TYPES) as $type) {
			$this->admin_notices->{$type} = array();
		}
		add_action('admin_init', array($this, 'admin_init'), 10);
		add_action('UPVIMEO_admin_notices', array($this, 'admin_notices'), 10);
	}

	/**
	 * Return the current instance
	 * @return UpVimeo_Notices_Helper
	 */
	public static function instance()
	{
		if (!(self::$_instance instanceof self)) {
			self::$_instance = new self();
		}

		return self::$_instance;
	}

	/**
	 * Admin init
	 */
	public function admin_init()
	{
		$notice_id = isset($_GET['notice_id']) ? sanitize_text_field(wp_unslash($_GET['notice_id'])) : '';
		$dismiss_option = isset($_GET['dismiss']) ? sanitize_text_field(wp_unslash($_GET['dismiss'])) : '';
		$nonce = isset($_GET['_wpnonce']) ? sanitize_text_field(wp_unslash($_GET['_wpnonce'])) : '';

		if (!empty($notice_id) && is_string($dismiss_option)) {
			if (wp_verify_nonce($nonce, 'dismiss_notice_' . $notice_id)) {
				set_transient($this->get_notice_key($notice_id), 'd', $this->expiry);
			}
			wp_die();
		}
	}

	/**
	 * Show admin notices
	 */
	public function admin_notices()
	{
		add_action('admin_notices', array($this, 'handle_admin_notices'));
	}


	/**
	 * Handle admin notices
	 */
	public function handle_admin_notices()
	{

		// Handle flash messages.
		$flash = new UpVimeo_Flash();
		$notice = $flash->unflash_message();
		if (isset($notice['message']) && isset($notice['type'])) {
			$key = md5(time() . get_current_user_id() . $notice['message']);
			if (in_array($notice['type'], array('error', 'success', 'warning'))) {
				$type = $notice['type'];
				$this->$type($key, $notice['message'], false);
			}
		}

		// Handle all messages.
		foreach (explode(',', self::TYPES) as $type) {
			foreach ($this->admin_notices->{$type} as $admin_notice) {
				$dismiss_url = add_query_arg(array(
					$this->prefix . 'dismiss' => $admin_notice->dismiss_option,
					$this->prefix . 'notice_id' => $admin_notice->id,
				), admin_url());

				$value = get_transient($this->get_notice_key($admin_notice->id));

				if (!$value || $value !== 'd') {

					$dismissible = (bool) $admin_notice->dismiss_option;
					if ($dismissible) {
						$dismiss_url = wp_nonce_url($dismiss_url, 'dismiss_notice_' . $admin_notice->id);
					}
					$dismiss_url = $dismissible ? esc_url($dismiss_url) : '';
					$dismiss_class = $dismissible ? 'is-dismissible' : '';

					if ($dismissible) {
						?>
						<div class="notice notice-<?php echo esc_attr($type); ?> <?php echo esc_attr($dismiss_class); ?>" data-dismiss-url="<?php echo esc_url($dismiss_url); ?>">
						<?php
					} else {
						?>
						<div class="notice notice-<?php echo esc_attr($type); ?> <?php echo esc_attr($dismiss_class); ?>">
						<?php
					}
					echo sprintf("<h2>%s %s</h2>", esc_html($this->title), esc_html($type));
					echo sprintf('<p>%s</p>', esc_html($admin_notice->message));
					echo '</div>';
				}
			}
		}
	}

	/**
	 * Add error notification message.
	 *
	 * @param $id
	 * @param $message
	 * @param $dismiss_option
	 */
	public function error($id, $message, $dismiss_option = false)
	{
		$this->notice('error', $id, $message, $dismiss_option);
	}

	/**
	 * Add warning notification message.
	 *
	 * @param $id
	 * @param $message
	 * @param $dismiss_option
	 */
	public function warning($id, $message, $dismiss_option = false)
	{
		$this->notice('warning', $id, $message, $dismiss_option);
	}

	/**
	 * Add success notification message.
	 *
	 * @param $id
	 * @param $message
	 * @param $dismiss_option
	 */
	public function success($id, $message, $dismiss_option = false)
	{
		$this->notice('success', $id, $message, $dismiss_option);
	}

	/**
	 * Add info notification message.
	 *
	 * @param $id
	 * @param $message
	 * @param $dismiss_option
	 */
	public function info($id, $message, $dismiss_option = false)
	{
		$this->notice('info', $id, $message, $dismiss_option);
	}

	/**
	 * Add notice
	 *
	 * @param $type
	 * @param $id
	 * @param $message
	 * @param $dismiss_option
	 */
	private function notice($type, $id, $message, $dismiss_option)
	{
		$notice = new stdClass();
		$notice->id = $id;
		$notice->message = $message;
		$notice->dismiss_option = $dismiss_option;

		$this->admin_notices->{$type}[] = $notice;
	}

	/**
	 * Returns the notice database key
	 *
	 * @param $id
	 *
	 * @return string
	 */
	private function get_notice_key($id)
	{
		return $this->prefix . 'dismissed_' . $id;
	}
}

UpVimeo_Notices_Helper::instance();
