<?php
/**
 * Masteriyo two-factor authentication setup.
 *
 * @package Masteriyo\Addons\TwoFactorAuthentication
 *
 * @since 2.7.0
 */
namespace Masteriyo\Addons\TwoFactorAuthentication;

use Masteriyo\Addons\TwoFactorAuthentication\AjaxHandlers\LoginOTPAjaxHandler;
use Masteriyo\Constants;

defined( 'ABSPATH' ) || exit;
/**
 * Main Masteriyo Two FActor Authentication class.
 *
 * @class Masteriyo\Addons\TwoFactorAuthentication
 */
class TwoFactorAuthenticationAddon {
	/**
		 * Instance
		 *
		 * @since 2.7.0
		 *
		 * @var \Masteriyo\Addons\TwoFactorAuthentication\TwoFactorAuthenticationAddon
		 */
	protected static $instance = null;

	/**
	 * Constructor.
	 *
	 * @since 2.7.0
	 */
	private function __construct() {
	}

	/**
	 * Return the instance.
	 *
	 * @since 2.7.0
	 *
	 * @return \Masteriyo\Addons\TwoFactorAuthentication\TwoFactorAuthenticationAddon
	 */
	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}

		return self::$instance;
	}
	/**
	 * Initialize module.
	 *
	 * @since 2.7.0
	 */
	public function init() {
		TwoFactorAuthenticator::init();

		$this->init_hooks();
	}

	/**
	 * Initialize hooks.
	 *
	 * @since 2.7.0
	 */
	public function init_hooks() {
		add_filter( 'masteriyo_ajax_handlers', array( $this, 'register_ajax_handlers' ) );
		add_filter( 'masteriyo_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
		add_filter( 'masteriyo_localized_public_scripts', array( $this, 'localize_two_factor_authentication_scripts' ) );
		add_filter( 'masteriyo_rest_response_setting_data', array( $this, 'append_setting_in_response' ), 10, 4 );
		add_action( 'masteriyo_new_setting', array( $this, 'save_two_factor_authentication_settings' ), 10, 1 );
	}

	/**
	 * Register ajax handlers.
	 *
	 * @since 2.7.0
	 *
	 * @param array $handlers
	 *
	 * @return array
	 */
	public function register_ajax_handlers( $handlers ) {
		$handlers[] = LoginOTPAjaxHandler::class;

		return $handlers;
	}

	/**
	 * Enqueue scripts.
	 *
	 * @since 2.7.0
	 *
	 * @param array $scripts Array of scripts.
	 * @return array
	 */
	public function enqueue_scripts( $scripts ) {
		$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';

		return masteriyo_parse_args(
			$scripts,
			array(
				'two-factor-authentication-otp-login' => array(
					'src'      => plugin_dir_url( Constants::get( 'MASTERIYO_TWO_FACTOR_AUTHENTICATION_ADDON_FILE' ) ) . '/assets/js/frontend/otp-login' . $suffix . '.js',
					'context'  => 'public',
					'callback' => 'masteriyo_is_otp_page',
					'deps'     => array( 'jquery' ),
				),
			)
		);
	}

	/**
	 * Localize two-factor authentication page scripts.
	 *
	 * @since 2.7.00
	 *
	 * @param array $scripts
	 *
	 * @return array
	 */
	public function localize_two_factor_authentication_scripts( $scripts ) {
		return masteriyo_parse_args(
			$scripts,
			array(
				'two-factor-authentication-otp-login' => array(
					'name' => 'MASTERIYO_TWO_FACTOR_AUTHENTICATION_DATA',
					'data' => array(
						'ajax_url' => admin_url( 'admin-ajax.php' ),
						'nonce'    => wp_create_nonce( 'masteriyo_login_otp_resend_nonce' ),
					),
				),
			)
		);

	}

	/**
	 * Append setting to response.
	 *
	 * @since 2.7.0
	 *
	 * @param array $data Setting data.
	 * @param \Masteriyo\Models\Setting $setting Setting object.
	 * @param string $context What the value is for. Valid values are view and edit.
	 * @param \Masteriyo\RestApi\Controllers\Version1\SettingsController $controller REST settings controller object.
	 *
	 * @return array
	 */
	public function append_setting_in_response( $data, $setting, $context, $controller ) {
		$data['authentication']['two_factor_authentication'] = Setting::all();

		return $data;
	}

	/**
	 * Save global two-factor authentication settings.
	 *
	 * @since 2.7.0
	 *
	 * @param \Masteriyo\Models\Setting $setting Setting object.
	 */
	public function save_two_factor_authentication_settings( $setting ) {
		$request = masteriyo_current_http_request();

		if ( ! masteriyo_is_rest_api_request() ) {
			return;
		}

		if ( ! isset( $request['authentication'] ) || ! isset( $request['authentication']['two_factor_authentication'] ) ) {
			return;
		}

		$settings = masteriyo_array_only( $request['authentication']['two_factor_authentication'], array_keys( Setting::all() ) );
		$settings = masteriyo_parse_args( $settings, Setting::all() );

		// Sanitization.
		$settings['method']                  = sanitize_text_field( $settings['method'] );
		$settings['location']                = sanitize_text_field( $settings['location'] );
		$settings['opt_length']              = absint( $settings['opt_length'] );
		$settings['opt_expiration']          = absint( $settings['opt_expiration'] );
		$settings['opt_resend_interval']     = absint( $settings['opt_resend_interval'] );
		$settings['opt_resend_max_attempts'] = absint( $settings['opt_resend_max_attempts'] );

		Setting::set_props( $settings );

		Setting::save();
	}
}
