<?php
/**
 * Class Admin
 *
 * @package TEC\Common\TrustedLogin\Client
 *
 * @copyright 2021 Katz Web Services, Inc.
 */

namespace TEC\Common\TrustedLogin;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use WP_User;
use WP_Admin_Bar;

/**
 * Handle all the functionality that is related to the WordPress Dashboard.
 */
final class Admin {

	/**
	 * URL pointing to the "About TrustedLogin" page, shown below the Grant Access dialog
	 */
	const ABOUT_TL_URL = 'https://www.trustedlogin.com/about/easy-and-safe/';

	const ABOUT_LIVE_ACCESS_URL = 'https://www.trustedlogin.com/about/live-access/';

	/**
	 * Config object.
	 *
	 * @var Config
	 */
	private $config;

	/**
	 * SupportUser object.
	 *
	 * @var SupportUser $support_user
	 */
	private $support_user;

	/**
	 * Form object.
	 *
	 * @var Form $form
	 */
	private $form;

	/**
	 * Admin constructor.
	 *
	 * @param Config      $config Config object.
	 * @param Form        $form Form object.
	 * @param SupportUser $support_user SupportUser object.
	 */
	public function __construct( Config $config, Form $form, SupportUser $support_user ) {
		$this->config       = $config;
		$this->form         = $form;
		$this->support_user = $support_user;
	}

	/**
	 * Sets up all the admin and login hooks.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function init() {

		if ( is_admin() ) {
			$this->admin_init();
		}

		// Always load login hooks; it's faster than calling is_login()!
		$this->login_init();
	}

	/**
	 * Sets up all the admin hooks.
	 *
	 * @since 1.8.0
	 *
	 * @return void
	 */
	public function admin_init() {

		// @phpstan-ignore-next-line
		add_action(
			'trustedlogin/' . $this->config->ns() . '/button',
			array(
				$this->form,
				'generate_button',
			),
			10,
			2
		);

		// @phpstan-ignore-next-line
		add_action(
			'trustedlogin/' . $this->config->ns() . '/users_table',
			array(
				$this->form,
				'output_support_users',
			),
			20
		);

		add_action(
			'trustedlogin/' . $this->config->ns() . '/auth_screen',
			array(
				$this->form,
				'print_auth_screen',
			),
			20
		);

		add_filter(
			'user_row_actions',
			array(
				$this,
				'user_row_action_revoke',
			),
			10,
			2
		);
		add_action(
			'admin_bar_menu',
			array(
				$this,
				'admin_bar_add_toolbar_items',
			),
			100
		);

		if ( $this->config->get_setting( 'menu' ) ) {
			$menu_priority = $this->config->get_setting( 'menu/priority', 100 );
			add_action(
				'admin_menu',
				array(
					$this,
					'admin_menu_auth_link_page',
				),
				(int) $menu_priority
			);
		}

		if ( $this->config->get_setting( 'register_assets', true ) ) {
			add_action(
				'admin_enqueue_scripts',
				array(
					$this->form,
					'register_assets',
				)
			);
		}

		add_action(
			'trustedlogin/' . $this->config->ns() . '/admin/access_revoked',
			array(
				$this,
				'admin_notices',
			)
		);
	}

	/**
	 * Sets up all the admin hooks.
	 *
	 * @since 1.8.0
	 *
	 * @return void
	 */
	private function login_init() {

		add_action(
			'login_form_trustedlogin',
			array(
				$this->form,
				'maybe_print_request_screen',
			),
			20
		);

		if ( $this->config->get_setting( 'register_assets', true ) ) {
			add_action(
				'login_enqueue_scripts',
				array(
					$this->form,
					'register_assets',
				)
			);
		}
	}

	/**
	 * Filter: Update the actions on the users.php list for our support users.
	 *
	 * @since 1.0.0
	 *
	 * @param array   $actions     The user row actions links.
	 * @param WP_User $user_object The user object.
	 *
	 * @return array
	 */
	public function user_row_action_revoke( $actions, $user_object ) {

		if ( ! current_user_can( $this->support_user->role->get_name() ) && ! current_user_can( 'delete_users' ) ) {
			return $actions;
		}

		$revoke_url = $this->support_user->get_revoke_url( $user_object );

		if ( ! $revoke_url ) {
			return $actions;
		}

		return array(
			'revoke' => "<a class='trustedlogin tl-revoke submitdelete' href='" . esc_url( $revoke_url ) . "'>" . esc_html__( 'Revoke Access', 'trustedlogin' ) . '</a>',
		);
	}


	/**
	 * Adds a "Revoke TrustedLogin" menu item to the admin toolbar
	 *
	 * @param WP_Admin_Bar $admin_bar The admin bar object.
	 *
	 * @return void
	 */
	public function admin_bar_add_toolbar_items( $admin_bar ) {

		if ( ! current_user_can( $this->support_user->role->get_name() ) ) {
			return;
		}

		if ( ! $admin_bar instanceof WP_Admin_Bar ) {
			return;
		}

		$is_user_active = $this->support_user->is_active();

		if ( ! $is_user_active ) {
			return;
		}

		$icon = '<span style="
			height: 32px;
			width: 23px;
			margin: 0 1px;
			display: inline-block;
			vertical-align: top;
			background: url(\'data:image/svg+xml;base64, \') left center no-repeat;
			background-size: 22px 23px;
		"></span>';

		$admin_bar->add_menu(
			array(
				'id'     => 'tl-' . $this->config->ns() . '-revoke',
				'title'  => $icon . esc_html__( 'Revoke Access', 'trustedlogin' ),
				'href'   => $this->support_user->get_revoke_url( 'all' ),
				'parent' => 'top-secondary',
				'meta'   => array(
					'class' => 'tl-destroy-session',
					'title' => esc_html__( 'You are logged in as a support user. Click to permanently revoke access.', 'trustedlogin' ),
				),
			)
		);
	}

	/**
	 * Generates the auth link page
	 *
	 * This simulates the addition of an admin submenu item with null as the menu location
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function admin_menu_auth_link_page() {

		/**
		 * Get the menu slug parent from the configuration.
		 *
		 * @var string|false $parent_slug
		 */
		$parent_slug = $this->config->get_setting( 'menu/slug', null );

		// When false, there will be no menus added.
		if ( false === $parent_slug ) {
			return;
		}

		$ns = $this->config->ns();

		$menu_slug = apply_filters( 'trustedlogin/' . $this->config->ns() . '/admin/menu/menu_slug', 'grant-' . $ns . '-access' );

		$menu_title = $this->config->get_setting( 'menu/title', esc_html__( 'Grant Support Access', 'trustedlogin' ) );

		$menu_position = $this->config->get_setting( 'menu/position', null );
		$menu_position = is_null( $menu_position ) ? null : (float) $menu_position;

		// If empty (null or empty string), add top-level menu.
		if ( empty( $parent_slug ) ) {
			add_menu_page(
				$menu_title,
				$menu_title,
				'create_users',
				$menu_slug,
				array( $this->form, 'print_auth_screen' ),
				$this->config->get_setting( 'menu/icon_url', '' ),
				$menu_position
			);

			return;
		}

		add_submenu_page(
			$parent_slug,
			$menu_title,
			$menu_title,
			'create_users',
			$menu_slug,
			array( $this->form, 'print_auth_screen' ),
			$menu_position
		);
	}

	/**
	 * Add admin_notices hooks
	 *
	 * @return void
	 */
	public function admin_notices() {
		add_action( 'admin_notices', array( $this->form, 'admin_notice_revoked' ) );
	}
}
