<?php
/**
 * Admin menu registration.
 *
 * @package SubmissionInbox
 */

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

/**
 * Registers the InboxMend admin area.
 */
class SUBIN_AdminMenu {
	const CAPABILITY = 'manage_options';
	const MENU_SLUG  = 'subin-inbox';

	/**
	 * Settings repository.
	 *
	 * @var SUBIN_SettingsRepository
	 */
	private $settings;

	/**
	 * Form submission context.
	 *
	 * @var \SUBIN\Forms\FormSubmissionContext|null
	 */
	private $form_context;

	/**
	 * Menu hook suffixes.
	 *
	 * @var array<int,string>
	 */
	private $hooks = array();

	/**
	 * Constructor.
	 *
	 * @param SUBIN_SettingsRepository                 $settings Settings repository.
	 * @param \SUBIN\Forms\FormSubmissionContext|null $form_context Form context.
	 */
	public function __construct( SUBIN_SettingsRepository $settings, $form_context = null ) {
		$this->settings     = $settings;
		$this->form_context = $form_context;
	}

	/**
	 * Register admin hooks.
	 *
	 * @return void
	 */
	public function register() {
		add_action( 'admin_menu', array( $this, 'register_menu' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
		add_action( 'admin_head', array( $this, 'hide_hidden_submenu_items' ) );
		add_action( 'current_screen', array( $this, 'suppress_third_party_notices' ), PHP_INT_MAX );
		add_filter( 'parent_file', array( $this, 'filter_parent_file' ) );
		add_filter( 'submenu_file', array( $this, 'filter_submenu_file' ) );
	}

	/**
	 * Register menu pages.
	 *
	 * @return void
	 */
	public function register_menu() {
		$inbox_page         = new SUBIN_InboxPage( $this->form_context );
		$email_status_page  = new SUBIN_EmailStatusPage();
		$email_log_page     = new SUBIN_EmailLogPage();
		$smtp_settings_page = new SUBIN_SmtpSettingsPage( $this->settings );
		$forms_page         = new SUBIN_FormsPage();
		$auto_replies_page  = new SUBIN_AutoRepliesPage();
		$settings_page      = new SUBIN_SettingsPage( $this->settings );

		$inbox_hook = add_menu_page(
			__( 'InboxMend', 'submission-inbox' ),
			__( 'InboxMend', 'submission-inbox' ),
			self::CAPABILITY,
			self::MENU_SLUG,
			array( $inbox_page, 'render' ),
			'dashicons-email-alt2',
			56
		);

		if ( $inbox_hook ) {
			$this->hooks[] = $inbox_hook;
			add_action( 'load-' . $inbox_hook, array( $inbox_page, 'handle_request' ) );
			add_action( 'load-' . $inbox_hook, array( $inbox_page, 'handle_export_request' ) );
		}

		$inbox_submenu_hook = add_submenu_page(
			self::MENU_SLUG,
			__( 'Inbox', 'submission-inbox' ),
			__( 'Inbox', 'submission-inbox' ),
			self::CAPABILITY,
			self::MENU_SLUG,
			array( $inbox_page, 'render' )
		);

		if ( $inbox_submenu_hook ) {
			$this->hooks[] = $inbox_submenu_hook;
			if ( $inbox_submenu_hook !== $inbox_hook ) {
				add_action( 'load-' . $inbox_submenu_hook, array( $inbox_page, 'handle_request' ) );
				add_action( 'load-' . $inbox_submenu_hook, array( $inbox_page, 'handle_export_request' ) );
			}
		}

		$forms_hook = add_submenu_page(
			self::MENU_SLUG,
			__( 'Forms', 'submission-inbox' ),
			__( 'Forms', 'submission-inbox' ),
			self::CAPABILITY,
			'submission-inbox-forms',
			array( $forms_page, 'render' )
		);

		if ( $forms_hook ) {
			$this->hooks[] = $forms_hook;
			add_action( 'load-' . $forms_hook, array( $forms_page, 'handle_request' ) );
		}

		$auto_replies_hook = add_submenu_page(
			self::MENU_SLUG,
			__( 'Auto-replies', 'submission-inbox' ),
			__( 'Auto-replies', 'submission-inbox' ),
			self::CAPABILITY,
			'submission-inbox-auto-replies',
			array( $auto_replies_page, 'render' )
		);

		if ( $auto_replies_hook ) {
			$this->hooks[] = $auto_replies_hook;
			add_action( 'load-' . $auto_replies_hook, array( $auto_replies_page, 'handle_request' ) );
			add_action( 'load-' . $auto_replies_hook, array( $this, 'load_auto_replies_page' ) );
		}

		$this->hooks[] = add_submenu_page(
			self::MENU_SLUG,
			__( 'Email Health', 'submission-inbox' ),
			__( 'Email Health', 'submission-inbox' ),
			self::CAPABILITY,
			'subin-email-status',
			array( $email_status_page, 'render' )
		);

		$email_log_hook = add_submenu_page(
			self::MENU_SLUG,
			__( 'Email Log', 'submission-inbox' ),
			__( 'Email Log', 'submission-inbox' ),
			self::CAPABILITY,
			'subin-email-log',
			array( $email_log_page, 'render' )
		);

		if ( $email_log_hook ) {
			$this->hooks[] = $email_log_hook;
			add_action( 'load-' . $email_log_hook, array( $email_log_page, 'handle_export_request' ) );
		}

		$smtp_settings_hook = add_submenu_page(
			'',
			__( 'SMTP Settings', 'submission-inbox' ),
			__( 'SMTP Settings', 'submission-inbox' ),
			self::CAPABILITY,
			'subin-smtp-settings',
			array( $smtp_settings_page, 'render' )
		);

		if ( $smtp_settings_hook ) {
			$this->hooks[] = $smtp_settings_hook;
			add_action( 'load-' . $smtp_settings_hook, array( $this, 'load_smtp_settings_page' ) );
		}

		$settings_hook = add_submenu_page(
			self::MENU_SLUG,
			__( 'Settings', 'submission-inbox' ),
			__( 'Settings', 'submission-inbox' ),
			self::CAPABILITY,
			'subin-settings',
			array( $settings_page, 'render' )
		);

		if ( $settings_hook ) {
			$this->hooks[] = $settings_hook;
			add_action( 'load-' . $settings_hook, array( $settings_page, 'handle_request' ) );
		}

	}

	/**
	 * Hide routed utility pages while keeping them registered for access checks.
	 *
	 * @return void
	 */
	public function hide_hidden_submenu_items() {
	}

	/**
	 * Keep Submission Inbox admin screens focused on plugin-owned notices.
	 *
	 * @param WP_Screen|null $screen Current admin screen.
	 * @return void
	 */
	public function suppress_third_party_notices( $screen = null ) {
		if ( ! $screen || empty( $screen->id ) || ! in_array( $screen->id, $this->hooks, true ) ) {
			return;
		}

		remove_all_actions( 'admin_notices' );
		remove_all_actions( 'all_admin_notices' );
		remove_all_actions( 'network_admin_notices' );
		remove_all_actions( 'user_admin_notices' );
	}

	/**
	 * Enqueue admin assets on plugin pages.
	 *
	 * @param string $hook_suffix Current admin hook suffix.
	 * @return void
	 */
	public function enqueue_assets( $hook_suffix ) {
		if ( ! in_array( $hook_suffix, $this->hooks, true ) ) {
			return;
		}

		$is_design_studio      = $this->is_design_studio_editor_request();
		$is_inbox_page         = $this->is_inbox_page_request();
		$is_email_page         = $this->is_email_page_request();
		$is_settings_page      = $this->is_settings_page_request();
		$is_forms_page         = $this->is_forms_page_request();
		$is_auto_reply_page    = $this->is_auto_reply_page_request();
		$is_auto_reply_editor  = $this->is_auto_reply_editor_request();
		if ( $is_design_studio ) {
			wp_enqueue_media();
			wp_enqueue_editor();
		}

		if ( $is_auto_reply_editor ) {
			wp_enqueue_media();
			wp_enqueue_editor();
		}

		if ( $is_design_studio ) {
			wp_enqueue_style(
				'subin-grapesjs',
				SUBIN_PLUGIN_URL . 'assets/vendor/grapesjs/grapes.min.css',
				array(),
				'0.22.16'
			);

			wp_enqueue_script(
				'subin-grapesjs',
				SUBIN_PLUGIN_URL . 'assets/vendor/grapesjs/grapes.min.js',
				array(),
				'0.22.16',
				true
			);
		}

		if ( $is_forms_page ) {
			wp_enqueue_style(
				'subin-frontend',
				SUBIN_PLUGIN_URL . 'assets/frontend.css',
				array(),
				SUBIN_PLUGIN_VERSION
			);
		}

		wp_enqueue_style(
			'subin-admin',
			SUBIN_PLUGIN_URL . 'assets/css/admin.css',
			$is_forms_page ? array( 'subin-frontend' ) : array(),
			(string) filemtime( SUBIN_PLUGIN_DIR . 'assets/css/admin.css' )
		);

		if ( $is_inbox_page ) {
			wp_enqueue_style(
				'subin-admin-inbox',
				SUBIN_PLUGIN_URL . 'assets/css/admin/inbox.css',
				array( 'subin-admin' ),
				(string) filemtime( SUBIN_PLUGIN_DIR . 'assets/css/admin/inbox.css' )
			);
		}

		if ( $is_forms_page ) {
			wp_enqueue_style(
				'subin-admin-forms',
				SUBIN_PLUGIN_URL . 'assets/css/admin/forms.css',
				array( 'subin-admin' ),
				(string) filemtime( SUBIN_PLUGIN_DIR . 'assets/css/admin/forms.css' )
			);
		}

		if ( $is_settings_page || $is_forms_page || $is_auto_reply_page ) {
			wp_enqueue_style(
				'subin-admin-settings-controls',
				SUBIN_PLUGIN_URL . 'assets/css/admin/settings-controls.css',
				array( 'subin-admin' ),
				(string) filemtime( SUBIN_PLUGIN_DIR . 'assets/css/admin/settings-controls.css' )
			);
		}

		if ( $is_settings_page ) {
			wp_enqueue_style(
				'subin-admin-settings',
				SUBIN_PLUGIN_URL . 'assets/css/admin/settings.css',
				array( 'subin-admin', 'subin-admin-settings-controls' ),
				(string) filemtime( SUBIN_PLUGIN_DIR . 'assets/css/admin/settings.css' )
			);
		}

		if ( $is_email_page ) {
			wp_enqueue_style(
				'subin-admin-email',
				SUBIN_PLUGIN_URL . 'assets/css/admin/email.css',
				array( 'subin-admin' ),
				(string) filemtime( SUBIN_PLUGIN_DIR . 'assets/css/admin/email.css' )
			);
		}

		if ( $is_design_studio ) {
			wp_enqueue_style(
				'subin-design-studio-css',
				SUBIN_PLUGIN_URL . 'assets/css/design-studio/design-studio.css',
				array( 'subin-grapesjs', 'subin-admin' ),
				(string) filemtime( SUBIN_PLUGIN_DIR . 'assets/css/design-studio/design-studio.css' )
			);
		}

		if ( $is_auto_reply_page ) {
			wp_enqueue_style(
				'subin-auto-reply-editor-css',
				SUBIN_PLUGIN_URL . 'assets/css/auto-reply/auto-reply.css',
				array( 'subin-admin' ),
				(string) filemtime( SUBIN_PLUGIN_DIR . 'assets/css/auto-reply/auto-reply.css' )
			);
		}

		wp_enqueue_script(
			'subin-admin',
			SUBIN_PLUGIN_URL . 'assets/js/admin.js',
			array(),
			(string) filemtime( SUBIN_PLUGIN_DIR . 'assets/js/admin.js' ),
			true
		);

		if ( $is_design_studio ) {
			$design_studio_deps = array( 'subin-grapesjs', 'jquery', 'media-editor', 'media-views', 'wp-util' );
			$design_studio_path = 'assets/js/design-studio/';
			$design_studio_files = array(
				'subin-design-studio-components' => 'design-studio-components.js',
				'subin-design-studio-traits'     => 'design-studio-traits.js',
				'subin-design-studio-rendering'  => 'design-studio-rendering.js',
				'subin-design-studio-inspector'  => 'design-studio-inspector.js',
				'subin-design-studio-data'       => 'design-studio-data.js',
			);

			foreach ( $design_studio_files as $handle => $file ) {
				wp_enqueue_script(
					$handle,
					SUBIN_PLUGIN_URL . $design_studio_path . $file,
					$design_studio_deps,
					(string) filemtime( SUBIN_PLUGIN_DIR . $design_studio_path . $file ),
					true
				);
				$design_studio_deps = array( $handle );
			}

			wp_enqueue_script(
				'subin-design-studio',
				SUBIN_PLUGIN_URL . $design_studio_path . 'design-studio.js',
				$design_studio_deps,
				(string) filemtime( SUBIN_PLUGIN_DIR . $design_studio_path . 'design-studio.js' ),
				true
			);
		}

		if ( $is_auto_reply_editor ) {
			$auto_reply_path = 'assets/js/auto-reply/';
			wp_enqueue_script(
				'subin-auto-reply-wp-editor',
				SUBIN_PLUGIN_URL . $auto_reply_path . 'auto-reply-wp-editor.js',
				array( 'jquery' ),
				(string) filemtime( SUBIN_PLUGIN_DIR . $auto_reply_path . 'auto-reply-wp-editor.js' ),
				true
			);
		}
	}

	/**
	 * Keep hidden auto-reply routes under the InboxMend menu.
	 *
	 * @param string $parent_file Current parent file.
	 * @return string
	 */
	public function filter_parent_file( $parent_file ) {
		$page = SUBIN_Request::get_key( 'page' );
		if ( 'subin-smtp-settings' === $page ) {
			return self::MENU_SLUG;
		}

		if ( $this->is_auto_reply_page_request() ) {
			return self::MENU_SLUG;
		}

		return $parent_file;
	}

	/**
	 * Highlight the current InboxMend submenu item for routed pages.
	 *
	 * @param string $submenu_file Current submenu file.
	 * @return string
	 */
	public function filter_submenu_file( $submenu_file ) {
		if ( $this->is_auto_reply_page_request() ) {
			return 'submission-inbox-auto-replies';
		}

		$page = SUBIN_Request::get_key( 'page' );
		if ( 'subin-smtp-settings' === $page ) {
			return 'subin-settings';
		}

		return $submenu_file;
	}

	/**
	 * Set a title for the hidden auto-reply route before admin-header.php renders.
	 *
	 * @return void
	 */
	public function load_auto_replies_page() {
		global $title;

		$title = __( 'Auto-replies', 'submission-inbox' );
	}

	/**
	 * Redirect the legacy SMTP settings route before the admin header renders.
	 *
	 * @return void
	 */
	public function load_smtp_settings_page() {
		if ( ! current_user_can( self::CAPABILITY ) ) {
			wp_die( esc_html__( 'You do not have permission to perform this action.', 'submission-inbox' ) );
		}

		wp_safe_redirect( admin_url( 'admin.php?page=subin-settings&subin_settings_tab=sending' ) );
		exit;
	}

	/**
	 * Check whether the current admin request is the form Design Studio editor.
	 *
	 * @return bool
	 */
	private function is_design_studio_editor_request() {
		$page    = SUBIN_Request::get_key( 'page' );
		$view    = SUBIN_Request::get_key( 'view' );
		$tab     = SUBIN_Request::get_key( 'tab' );
		$form_id = SUBIN_Request::get_absint( 'form_id' );

		return 'submission-inbox-forms' === $page && 'edit' === $view && $form_id > 0 && ( '' === $tab || 'design_studio' === $tab );
	}

	/**
	 * Check if the current request is any Forms admin page.
	 *
	 * @return bool
	 */
	private function is_forms_page_request() {
		$page = SUBIN_Request::get_key( 'page' );

		return 'submission-inbox-forms' === $page;
	}

	/**
	 * Check if the current request is any Inbox admin page.
	 *
	 * @return bool
	 */
	private function is_inbox_page_request() {
		$page = SUBIN_Request::get_key( 'page' );

		return self::MENU_SLUG === $page;
	}

	/**
	 * Check if the current request is an Email Health or Email Log page.
	 *
	 * @return bool
	 */
	private function is_email_page_request() {
		$page = SUBIN_Request::get_key( 'page' );

		return in_array( $page, array( 'subin-email-status', 'subin-email-log' ), true );
	}

	/**
	 * Check if the current request is a Settings admin page.
	 *
	 * @return bool
	 */
	private function is_settings_page_request() {
		$page = SUBIN_Request::get_key( 'page' );

		return in_array( $page, array( 'subin-settings', 'subin-smtp-settings' ), true );
	}

	/**
	 * Check whether the current admin request is the auto-reply editor.
	 *
	 * @return bool
	 */
	private function is_auto_reply_editor_request() {
		$page = SUBIN_Request::get_key( 'page' );
		$view = SUBIN_Request::get_key( 'view' );

		return 'submission-inbox-auto-replies' === $page && in_array( $view, array( 'editor', 'edit' ), true );
	}

	/**
	 * Check if the current request is any auto-reply admin page.
	 *
	 * @return bool
	 */
	private function is_auto_reply_page_request() {
		$page = SUBIN_Request::get_key( 'page' );

		return 'submission-inbox-auto-replies' === $page;
	}

}
