<?php
namespace DisableHeartbeat;

use WP_PowerSuite\Core\AbstractModule;

class Module extends AbstractModule {

	private const MODULE_ID = 'disable-heartbeat';
	private const MODULE_VERSION = '1.2.2';

	private const MODES = [
		'disable_all',
		'disable_frontend',
		'disable_dashboard',
		'disable_admin',
		'throttle',
	];

	private array $settings = [];

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

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

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

	public function getDescription(): string {
		return __( 'Reduce automatic background requests from WordPress to ease server load. Pick what to turn off or slow down in the module settings.', 'wp-powersuite' );
	}

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

	protected function registerHooks(): void {
		$this->settings = self::normalizeSettings(
			$this->moduleSettings()->all( $this->getDefaultSettings() )
		);

		$mode = $this->settings['mode'];

		switch ( $mode ) {
			case 'disable_all':
				add_action( 'admin_enqueue_scripts', [ $this, 'maybeDisableHeartbeatExceptEditor' ], 999 );
				add_action( 'wp_enqueue_scripts', [ $this, 'disableHeartbeat' ], 999 );
				break;

			case 'disable_frontend':
				add_action( 'wp_enqueue_scripts', [ $this, 'disableHeartbeat' ], 999 );
				break;

			case 'disable_dashboard':
				add_action( 'admin_enqueue_scripts', [ $this, 'maybeDisableHeartbeatDashboard' ], 999 );
				break;

			case 'disable_admin':
				add_action( 'admin_enqueue_scripts', [ $this, 'maybeDisableHeartbeatExceptEditor' ], 999 );
				break;

			case 'throttle':
				add_filter( 'heartbeat_settings', [ $this, 'throttleHeartbeat' ], 999 );
				break;
		}
	}

	/**
	 * @param array<string, mixed> $settings Raw or partial settings.
	 * @return array{mode: string, allow_in_editor: bool, throttle_interval: int}
	 */
	public static function normalizeSettings( array $settings ): array {
		$mode = isset( $settings['mode'] ) ? sanitize_key( (string) $settings['mode'] ) : 'throttle';
		if ( ! in_array( $mode, self::MODES, true ) ) {
			$mode = 'throttle';
		}

		return [
			'mode'              => $mode,
			'allow_in_editor'   => ! empty( $settings['allow_in_editor'] ),
			'throttle_interval' => max( 15, min( 300, (int) ( $settings['throttle_interval'] ?? 60 ) ) ),
		];
	}

	/**
	 * Disable Heartbeat only on the main Dashboard (index.php), like common hosting presets.
	 */
	public function maybeDisableHeartbeatDashboard(): void {
		global $pagenow;
		if ( empty( $pagenow ) || $pagenow !== 'index.php' ) {
			return;
		}
		$this->disableHeartbeat();
	}

	/**
	 * Honor allow_in_editor for disable_admin and disable_all admin paths.
	 */
	public function maybeDisableHeartbeatExceptEditor(): void {
		if ( ! empty( $this->settings['allow_in_editor'] ) && $this->isPostEditor() ) {
			return;
		}
		$this->disableHeartbeat();
	}

	public function getDefaultSettings(): array {
		return [
			'mode'              => 'throttle',
			'allow_in_editor'   => false,
			'throttle_interval' => 60,
		];
	}

	public function disableHeartbeat(): void {
		wp_deregister_script( 'heartbeat' );
	}

	public function throttleHeartbeat( array $settings ): array {
		$interval = max( 15, absint( $this->settings['throttle_interval'] ?? 60 ) );
		$settings['interval']        = $interval;
		$settings['minimalInterval'] = $interval;

		return $settings;
	}

	private function isPostEditor(): bool {
		global $pagenow;
		if ( ! is_admin() ) {
			return false;
		}

		if ( in_array( $pagenow, [ 'post.php', 'post-new.php' ], true ) ) {
			return true;
		}

		$screen = get_current_screen();
		if ( $screen && in_array( $screen->base, [ 'post', 'page' ], true ) ) {
			return true;
		}

		return false;
	}
}
