<?php
/**
 * Settings admin controller.
 *
 * @package Awesomemotive\Rewardswp\Controllers\Admin
 * @since 1.0.0
 */

namespace Awesomemotive\Rewardswp\Controllers\Admin;

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

use Awesomemotive\Rewardswp\Factories\ViewsFactory;
use Awesomemotive\Rewardswp\Interfaces\ControllerInterface;
use Awesomemotive\Rewardswp\Interfaces\ViewInterface;
use Awesomemotive\Rewardswp\Services\OptionsService;
use Awesomemotive\Rewardswp\Services\SettingsScreenService;
use Awesomemotive\Rewardswp\Views\Admin\SettingsView;
use function Awesomemotive\Rewardswp\Helpers\count_rewards;
use function Awesomemotive\Rewardswp\Helpers\is_rewardswp_admin_page;
use function Awesomemotive\Rewardswp\Helpers\sanitize_float;

class SettingsAdminController implements ControllerInterface {
	/**
	 * Admin submenu position.
	 *
	 * @since 1.0.0
	 *
	 * @var string
	 */
	const MENU_POSITION = 70;

	/**
	 * Admin submenu slug.
	 *
	 * @since 1.0.0
	 *
	 * @var string
	 */
	const MENU_SLUG = 'rewardswp-settings';

	/**
	 * AJAX nonce action for settings operations.
	 *
	 * @since 1.0.0
	 */
	const AJAX_NONCE = 'rewardswp_settings_admin_nonce';

	/**
	 * Views factory instance.
	 *
	 * @since 1.0.0
	 *
	 * @var ViewsFactory
	 */
	private ViewsFactory $views_factory;

	/**
	 * Settings screen service instance.
	 *
	 * @since 1.0.0
	 *
	 * @var SettingsScreenService
	 */
	private SettingsScreenService $settings_screen_service;

	/**
	 * Construct.
	 *
	 * @since 1.0.0
	 *
	 * @param ViewsFactory          $views_factory
	 * @param SettingsScreenService $settings_screen_service
	 */
	public function __construct(
		ViewsFactory $views_factory,
		SettingsScreenService $settings_screen_service
	) {
		$this->views_factory           = $views_factory;
		$this->settings_screen_service = $settings_screen_service;
	}

	/**
	 * Get page title.
	 *
	 * @since 1.0.0
	 *
	 * @return string
	 */
	public function get_page_title(): string {
		return esc_html__( 'Settings', 'rewardswp' );
	}

	/**
	 * Init.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function init(): void {
		add_action( 'admin_menu', [ $this, 'add_admin_menu' ], self::MENU_POSITION );
		add_action( 'admin_init', [ $this, 'register_settings' ] );
		add_action( 'wp_ajax_rewardswp_save_settings', [ $this, 'ajax_save_settings' ] );
		add_action( 'wp_ajax_rewardswp_get_reward_count', [ $this, 'ajax_get_reward_count' ] );
		add_action( 'admin_enqueue_scripts', [ $this, 'dequeue_conflicting_plugin_assets' ], 1 );
		add_action( 'admin_print_styles', [ $this, 'dequeue_conflicting_plugin_assets' ], 1 );
	}

	/**
	 * Remove conflicting plugin assets from RewardsWP admin pages.
	 *
	 * @since 1.0.3
	 *
	 * @return void
	 */
	public function dequeue_conflicting_plugin_assets(): void {
		if ( ! is_rewardswp_admin_page() ) {
			return;
		}

		$this->disable_learndash_assets();
	}

	/**
	 * Register the menu.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function add_admin_menu() {
		add_submenu_page(
			MainAdminController::MAIN_MENU_SLUG,
			$this->get_page_title(),
			$this->get_page_title(),
			'manage_options',
			self::MENU_SLUG,
			[ $this, 'render_page' ],
			self::MENU_POSITION
		);
	}

	/**
	 * Register settings for the plugin.
	 *
	 * The sanitization will occur when using the update_option to save the settings.
	 *
	 * @see SettingsAdminController::ajax_save_settings
	 *
	 * @since 1.0.0
	 */
	public function register_settings() {
		register_setting(
			OptionsService::OPTION_NAME,
			OptionsService::OPTION_NAME,
			[
				'type'              => 'array',
				'sanitize_callback' => [ $this->settings_screen_service, 'sanitize_settings' ],
			]
		);
	}

	/**
	 * Render the page.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function render_page(): void {
		$list_table = $this->views_factory->get_view( SettingsView::class );

		if ( is_subclass_of( $list_table, ViewInterface::class ) ) {
			$list_table->render();
		}
	}

	/**
	 * Save settings ajax handler.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function ajax_save_settings(): void {
		check_ajax_referer( self::AJAX_NONCE );

		$settings = filter_input( INPUT_POST, OptionsService::OPTION_NAME, FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );

		if ( ! is_array( $settings ) || empty( $settings ) ) {
			wp_send_json_error(
				[
					'message' => esc_html__( 'Invalid settings data.', 'rewardswp' ),
				]
			);

			wp_die();
		}

		// Remove any additional slashes automatically added during the form submission.
		array_walk_recursive(
			$settings,
			function ( &$value, $key ) {
				$value = wp_unslash( $value );
			}
		);

		update_option( OptionsService::OPTION_NAME, $settings );

		wp_send_json_success(
			[
				'message' => esc_html__( 'Settings saved successfully.', 'rewardswp' ),
			]
		);

		wp_die();
	}

	/**
	 * Reward count ajax handler.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function ajax_get_reward_count(): void {
		check_ajax_referer( self::AJAX_NONCE );

		$rewards = count_rewards(
			[
				'reward_type'    => sanitize_text_field( filter_input( INPUT_POST, 'reward_type' ) ),
				'recipient_type' => sanitize_text_field( filter_input( INPUT_POST, 'recipient_type' ) ),
				'amount'         => sanitize_text_field( sanitize_float( filter_input( INPUT_POST, 'reward_amount' ) ) ),
				'status'         => 'redeemed',
			]
		);

		wp_send_json_success(
			[
				'message' => sprintf(
					/* translators: %s is the number of rewards redeemed */
					esc_html__( '%s redeemed', 'rewardswp' ),
					$rewards
				),
			]
		);
	}

	/**
	 * Remove any CSS loaded by LearnDash in our screens.
	 *
	 * We intentionally left the learndash-admin-menu-style behind because this would affect their submenu.
	 *
	 * @since 1.0.2
	 *
	 * @return void
	 */
	private function disable_learndash_assets(): void {
		wp_dequeue_style( 'learndash-admin' );
		wp_dequeue_style( 'learndash-select2-jquery-style' );
		wp_dequeue_style( 'learndash_admin_shortcodes_style' );
		wp_dequeue_style( 'learndash-admin-settings-page' );
	}
}
