<?php
/**
 * SaveHandler
 *
 * Handles settings form save and reset via admin-post.php.
 * Owns nonce verification, capability check, sanitization, and redirect.
 *
 * @package Relatedly\Admin\Settings
 * @since   2.0.0
 */

namespace Relatedly\Admin\Settings;

use Relatedly\Core\Options;
use Relatedly\Core\OptionsSanitizer;
use Relatedly\Core\Cache;

defined( 'ABSPATH' ) || exit;

/**
 * Handles settings save, reset, and cache-clear form submissions.
 *
 * @since 2.0.0
 */
class SaveHandler {

	/**
	 * Plugin settings repository.
	 *
	 * @since 2.0.0
	 * @var Options
	 */
	private Options $options;

	/**
	 * Cache service.
	 *
	 * @since 2.0.0
	 * @var Cache
	 */
	private Cache $cache;

	/**
	 * Create the save handler.
	 *
	 * @since 2.0.0
	 * @param Options $options Plugin settings repository.
	 * @param Cache   $cache   Cache service.
	 */
	public function __construct( Options $options, Cache $cache ) {
		$this->options = $options;
		$this->cache   = $cache;
	}

	/**
	 * Register admin-post handlers.
	 *
	 * @since 2.0.0
	 */
	public function init_hooks(): void {
		add_action( 'admin_post_relatedly_save_settings', [ $this, 'handle_save' ] );
		add_action( 'admin_post_relatedly_reset_settings', [ $this, 'handle_reset' ] );
		add_action( 'admin_post_relatedly_clear_cache', [ $this, 'handle_clear_cache' ] );
	}

	// -------------------------------------------------------------------------
	// Save
	// -------------------------------------------------------------------------

	/**
	 * Save submitted settings.
	 *
	 * @since 2.0.0
	 */
	public function handle_save(): void {
		$this->check_permissions( 'relatedly_save_settings' );

		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified in check_permissions() above.
		$input      = wp_unslash( $_POST );
		$active_tab = isset( $input['relatedly_active_tab'] ) ? sanitize_key( $input['relatedly_active_tab'] ) : '';
		$sanitizer  = new OptionsSanitizer( $this->options );
		$clean      = $sanitizer->sanitize( $input, $active_tab );

		$saved = $this->options->save( $clean );
		$this->cache->flush();

		do_action( 'relatedly_settings_saved' );

		$this->redirect( $saved ? 'saved' : 'error', $active_tab );
	}

	// -------------------------------------------------------------------------
	// Reset
	// -------------------------------------------------------------------------

	/**
	 * Reset settings to default values.
	 *
	 * @since 2.0.0
	 */
	public function handle_reset(): void {
		$this->check_permissions( 'relatedly_reset_settings' );

		$saved = $this->options->save( $this->options->defaults() );
		$this->cache->flush();

		$this->redirect( $saved ? 'reset' : 'error' );
	}

	// -------------------------------------------------------------------------
	// Clear cache
	// -------------------------------------------------------------------------

	/**
	 * Clear all cached related post pools.
	 *
	 * @since 2.0.0
	 */
	public function handle_clear_cache(): void {
		$this->check_permissions( 'relatedly_clear_cache' );
		$this->cache->flush();
		$this->redirect( 'cache_cleared' );
	}

	// -------------------------------------------------------------------------
	// Internal
	// -------------------------------------------------------------------------

	/**
	 * Verify capability and nonce before handling a form action.
	 *
	 * @param string $nonce_action Expected nonce action.
	 */
	private function check_permissions( string $nonce_action ): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have permission to do this.', 'relatedly' ) );
		}

		if ( ! wp_verify_nonce(
			sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ?? '' ) ),
			$nonce_action
		) ) {
			wp_die( esc_html__( 'Security check failed.', 'relatedly' ) );
		}
	}

	/**
	 * Redirect back to the settings page with a status message.
	 *
	 * @param string $message Message key.
	 * @param string $tab     Active settings tab.
	 */
	private function redirect( string $message, string $tab = '' ): void {
		$args = [
			'page'    => 'relatedly',
			'message' => $message,
		];
		if ( '' !== $tab ) {
			$args['tab'] = $tab;
		}
		$url = add_query_arg( $args, admin_url( 'admin.php' ) );
		wp_safe_redirect( $url );
		exit;
	}
}
