<?php

namespace DisableAuthorArchives;

use WP_PowerSuite\Core\AbstractModule;

class Module extends AbstractModule {

	private const MODULE_ID = 'disable-author-archives';
	private const MODULE_VERSION = '1.3.0';
	private const REWRITE_FLUSH_TRANSIENT = 'wpps_disable_author_archives_flush_rewrite';

	public function getId(): string {
		return self::MODULE_ID;
	}

	public function getName(): string {
		return __( 'Disable Author Archives', 'wp-powersuite' );
	}

	public function getVersion(): string {
		return self::MODULE_VERSION;
	}

	public function getDescription(): string {
		return __( 'Turns off public author archive URLs so writer names are harder to harvest and those pages stop attracting junk traffic.', 'wp-powersuite' );
	}

	public function getContext(): string|array {
		return [ 'admin', 'frontend', 'rest' ];
	}

	protected function registerHooks(): void {
		add_filter( 'author_rewrite_rules', [ $this, 'strip_author_rewrite_rules' ] );
		add_filter( 'wp_sitemaps_add_provider', [ $this, 'remove_users_sitemap_provider' ], PHP_INT_MAX, 2 );
		add_action( 'init', [ $this, 'maybe_flush_rewrite_rules' ], 999 );
		add_action( 'wp_powersuite_module_toggled', [ $this, 'on_module_toggled' ], 10, 2 );

		if ( ! \WP_PowerSuite\Core\OptionStoreModuleSettingsRepository::isModuleEnabled( 'disable-rest-api' ) ) {
			add_action( 'rest_api_init', [ $this, 'register_rest_user_guard' ], 1 );
		}

		if ( is_admin() ) {
			add_action( 'load-users.php', [ $this, 'register_user_row_actions' ] );
		}

		if ( ! is_admin() && ! $this->is_rest_request() ) {
			add_action( 'template_redirect', [ $this, 'block_author_archives' ], 1 );
			add_filter( 'author_link', [ $this, 'strip_author_link' ], PHP_INT_MAX, 3 );
		}
	}

	public function on_module_toggled( string $module_id, bool $enable ): void {
		unset( $enable );
		if ( self::MODULE_ID !== $module_id ) {
			return;
		}

		set_transient( self::REWRITE_FLUSH_TRANSIENT, 1, MINUTE_IN_SECONDS );
	}

	public function maybe_flush_rewrite_rules(): void {
		if ( ! get_transient( self::REWRITE_FLUSH_TRANSIENT ) ) {
			return;
		}

		delete_transient( self::REWRITE_FLUSH_TRANSIENT );
		flush_rewrite_rules( false );
	}

	public function register_user_row_actions(): void {
		add_filter( 'user_row_actions', [ $this, 'remove_user_view_action' ], PHP_INT_MAX );
	}

	public function register_rest_user_guard(): void {
		static $registered = false;
		if ( $registered ) {
			return;
		}
		$registered = true;
		add_filter( 'rest_pre_dispatch', [ $this, 'block_anonymous_users_rest' ], 10, 3 );
	}

	public function block_author_archives(): void {
		$author_q = isset( $_GET['author'] ) ? sanitize_text_field( wp_unslash( (string) $_GET['author'] ) ) : '';

		if ( '' === $author_q && ! is_author() ) {
			return;
		}

		$this->send_author_404();
	}

	public function strip_author_link( string $_link, mixed $_author_id, string $_author_nicename ): string {
		unset( $_link, $_author_id, $_author_nicename );
		return home_url( '/' );
	}

	/**
	 * @param mixed $result
	 * @return mixed
	 */
	public function block_anonymous_users_rest( $result, $server, $request ) {
		unset( $server );
		if ( ! empty( $result ) ) {
			return $result;
		}
		if ( ! $request instanceof \WP_REST_Request ) {
			return $result;
		}
		if ( is_user_logged_in() ) {
			return $result;
		}
		$route = (string) $request->get_route();
		if ( '' === $route || ! preg_match( '#^/wp/v2/users(?:/|$)#', $route ) ) {
			return $result;
		}
		return new \WP_Error(
			'rest_user_enumeration_forbidden',
			__( 'You are not allowed to access user data.', 'wp-powersuite' ),
			[ 'status' => rest_authorization_required_code() ]
		);
	}

	/**
	 * @param array<string, string> $actions
	 * @return array<string, string>
	 */
	public function remove_user_view_action( array $actions ): array {
		unset( $actions['view'] );
		return $actions;
	}

	/**
	 * @param \WP_Sitemaps_Provider|string|false $provider
	 * @return \WP_Sitemaps_Provider|string|false
	 */
	public function remove_users_sitemap_provider( $provider, string $name ) {
		return 'users' === $name ? false : $provider;
	}

	/**
	 * @param array<string, string> $rules
	 * @return array<string, string>
	 */
	public function strip_author_rewrite_rules( array $rules ): array {
		return [];
	}

	private function is_rest_request(): bool {
		return defined( 'REST_REQUEST' ) && REST_REQUEST;
	}

	private function send_author_404(): void {
		global $wp_query;

		$wp_query->set_404();
		status_header( 404 );
		nocache_headers();
		exit;
	}

}
