<?php
/**
 * @license GPL-2.0-or-later
 *
 * Modified using {@see https://github.com/BrianHenryIE/strauss}.
 */

namespace GravityKit\GravityView\Foundation\Integrations;

use GravityKit\GravityView\Foundation\Helpers\Arr;
use GravityKit\GravityView\Foundation\Helpers\Core as CoreHelpers;
use GravityKit\GravityView\Foundation\Licenses\LicenseManager;
use GravityKit\GravityView\Foundation\ThirdParty\TrustedLogin\Form as TrustedLoginForm;
use GravityKit\GravityView\Foundation\ThirdParty\TrustedLogin\SupportUser as TrustedLoginSupportUser;
use GravityKit\GravityView\Foundation\ThirdParty\TrustedLogin\SiteAccess as TrustedLoginSiteAccess;
use GravityKit\GravityView\Foundation\ThirdParty\TrustedLogin\Logging as TrustedLoginLogging;
use GravityKit\GravityView\Foundation\ThirdParty\TrustedLogin\Config as TrustedLoginConfig;
use GravityKit\GravityView\Foundation\ThirdParty\TrustedLogin\Client as TrustedLoginClient;
use GravityKit\GravityView\Foundation\Core;
use GravityKit\GravityView\Foundation\Logger\Framework as LoggerFramework;
use GravityKit\GravityView\Foundation\WP\AdminMenu;
use Exception;

class TrustedLogin {
	const ID = 'gk_foundation_trustedlogin';

	const TL_API_KEY = '3b3dc46c0714cc8e';

	/**
	 * Access capabilities.
	 *
	 * @since 1.0.0
	 *
	 * @var string
	 */
	private $_capability = 'manage_options';

	/**
	 * TL Client class instance.
	 *
	 * @since 1.0.0
	 *
	 * @var TrustedLoginClient|null;
	 */
	private $_trustedlogin_client = null;

	/**
	 * Class instance.
	 *
	 * @since 1.0.0
	 *
	 * @var TrustedLogin|null;
	 */
	private static $_instance = null;

	/**
	 * Class constructor.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	private function __construct() {
		try {
			$this->_trustedlogin_client = new TrustedLoginClient(
				new TrustedLoginConfig( $this->get_config() )
			);
		} catch ( Exception $e ) {
			LoggerFramework::get_instance()->error( 'Unable to initialize TrustedLogin client: ' . $e->getMessage() );

			return;
		}

		try {
			$this->add_gk_submenu_item();
		} catch ( Exception $e ) {
			LoggerFramework::get_instance()->error( 'Unable to add TrustedLogin to the Foundation menu: ' . $e->getMessage() );

			return;
		}

		add_filter( 'gk/foundation/integrations/helpscout/configuration', [ $this, 'add_tl_key_to_helpscout_beacon' ] );
		add_action( 'trustedlogin/' . self::ID . '/admin/access_revoked', [ $this, 'replace_revoked_notice' ], 11 );
	}

	/**
	 * Returns class instance.
	 *
	 * @since 1.0.0
	 *
	 * @return TrustedLogin
	 */
	public static function get_instance() {
		if ( ! self::$_instance ) {
			self::$_instance = new self();
		}

		return self::$_instance;
	}

	/**
	 * Adds Settings submenu to the GravityKit top-level admin menu.
	 *
	 * @since 1.0.0
	 *
	 * @throws Exception TrustedLoginConfig throws an exception when the config object is empty (do not apply to us).
	 *
	 * @return void
	 */
	public function add_gk_submenu_item() {
		$tl_config  = new TrustedLoginConfig( $this->get_config() );
		$tl_logging = new TrustedLoginLogging( $tl_config );
		$tl_form    = new TrustedLoginForm( $tl_config, $tl_logging, new TrustedLoginSupportUser( $tl_config, $tl_logging ), new TrustedLoginSiteAccess( $tl_config, $tl_logging ) );

		$page_title = esc_html__( 'Grant Support Access', 'gk-gravityview' );
		$menu_title = $page_title;

		AdminMenu::add_submenu_item(
			[
				'page_title'         => $page_title,
				'menu_title'         => $menu_title,
				'capability'         => $this->_capability,
				'id'                 => self::ID,
				'callback'           => [ $tl_form, 'print_auth_screen' ],
				'order'              => 1,
				'hide_admin_notices' => true,
			],
			'bottom'
		);
	}

	/**
	 * Returns TrustedLogin configuration.
	 *
	 * @since 1.0.0
	 *
	 * @return array
	 */
	public function get_config() {
		$config = [
			'auth'            => [
				'api_key' => self::TL_API_KEY,
			],
			'menu'            => [
				'slug' => false, // Prevent TL from adding a menu item; we'll do it manually in the add_gk_submenu_item() method.
			],
			'role'            => 'administrator',
			'clone_role'      => false,
			'logging'         => [
				'enabled' => false,
			],
			'vendor'          => [
				'namespace'    => self::ID,
				'title'        => 'GravityKit',
				'email'        => 'support+{hash}@gravitykit.com',
				'website'      => 'https://www.gravitykit.com',
				'support_url'  => 'https://www.gravitykit.com/support/',
				'display_name' => 'GravityKit Support',
				'logo_url'     => CoreHelpers::get_assets_url( 'gravitykit-logo.svg' ),
			],
			'register_assets' => true,
			'paths'           => [
				'css' => CoreHelpers::get_assets_url( 'trustedlogin/trustedlogin.css' ),
			],
			'webhook'         => [
				'url'           => 'https://hooks.zapier.com/hooks/catch/28670/bnwjww2/silent/',
				'debug_data'    => true,
				'create_ticket' => true,
			],
		];

		$license_manager = LicenseManager::get_instance();

		foreach ( $license_manager->get_licenses_data() as $license_data ) {
			if ( Arr::get( $license_data, 'products' ) && ! $license_manager->is_expired_license( Arr::get( $license_data, 'expiry' ) ) ) {
				Arr::set( $config, 'auth.license_key', Arr::get( $license_data, 'key' ) );

				break;
			}
		}

		return $config;
	}

	/**
	 * Updates Help Scout beacon with TL access key.
	 *
	 * @since 1.0.0
	 *
	 * @param array $configuration Help Scout beacon configuration data.
	 *
	 * @return array
	 */
	public function add_tl_key_to_helpscout_beacon( $configuration ) {
		Arr::set( $configuration, 'identify.tl_access_key', $this->_trustedlogin_client->get_access_key() );

		return $configuration;
	}

	/**
	 * Replaces TrustedLogin's native WordPress admin notice with a Foundation notice
	 * and redirects to strip the revoke query parameters from the URL.
	 *
	 * @since 1.12.0
	 *
	 * @return void
	 */
	public function replace_revoked_notice() {
		$vendor_title = $this->get_config()['vendor']['title'];

		// translators: %s is replaced with the company name.
		$message = sprintf( esc_html__( '%s access revoked.', 'gk-gravityview' ), '<strong>' . esc_html( $vendor_title ) . '</strong>' );

		Core::notices()->add_stored(
			[
				'namespace' => 'trustedlogin',
				'slug'      => 'access-revoked',
				'message'   => $message,
				'severity'  => 'success',
				'flash'     => true,
				'scope'     => 'user',
				'screens'   => [ 'dashboard' ],
				'context'   => [ 'site', 'ms_main', 'ms_subsite' ],
			]
		);

		// Redirect to dashboard to strip revoke query params and prevent re-firing.
		wp_safe_redirect( admin_url() );

		exit;
	}
}
