<?php
/**
 * Abstract base module.
 *
 * @package MonitorCat\Module
 */

declare(strict_types=1);

namespace MonitorCat\Module;

defined( 'ABSPATH' ) || exit;

use MonitorCat\Admin\AssetManager;
use MonitorCat\Admin\PageRenderer;
use MonitorCat\Container;
use MonitorCat\Settings;

/**
 * Base class providing common functionality for all active modules.
 */
abstract class AbstractModule implements ModuleInterface {

	/**
	 * DI container.
	 *
	 * @var Container
	 */
	protected Container $container;

	/**
	 * Plugin settings.
	 *
	 * @var Settings
	 */
	protected Settings $settings;

	/**
	 * Asset manager.
	 *
	 * @var AssetManager
	 */
	protected AssetManager $assets;

	/**
	 * Page renderer.
	 *
	 * @var PageRenderer
	 */
	protected PageRenderer $renderer;

	/**
	 * Constructor.
	 *
	 * @param Container $container DI container.
	 */
	public function __construct( Container $container ) {
		$this->container = $container;
		$this->settings  = $container->get( Settings::class );
		$this->assets    = $container->get( AssetManager::class );
		$this->renderer  = $container->get( PageRenderer::class );
	}

	/**
	 * Whether the module is active.
	 *
	 * Override and return false for coming-soon modules.
	 *
	 * @return bool True by default.
	 */
	public function is_active(): bool {
		return true;
	}

	/**
	 * Boot the module — register admin hooks if in admin context.
	 */
	public function boot(): void {
		if ( is_admin() ) {
			add_action( 'admin_menu', array( $this, 'register_admin_page' ), 20 );
			add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
		}
	}

	/**
	 * Register the module's admin submenu page.
	 */
	public function register_admin_page(): void {
		add_submenu_page(
			'monitor-cat',
			$this->name(),
			$this->name(),
			'manage_options',
			'monitor-cat-' . $this->slug(),
			array( $this, 'render_page' )
		);
	}

	/**
	 * Enqueue module-specific assets on the module's own admin page.
	 *
	 * @param string $hook_suffix The current admin page hook suffix.
	 */
	public function enqueue_assets( string $hook_suffix ): void {
		if ( ! $this->is_own_page( $hook_suffix ) ) {
			return;
		}

		$this->assets->enqueue_style(
			'monitorcat-module-' . $this->slug(),
			'dist/css/module-' . $this->slug() . '.min.css'
		);

		$this->assets->enqueue_script(
			'monitorcat-module-' . $this->slug() . '-js',
			'dist/js/module-' . $this->slug() . '.min.js',
			array( 'monitorcat-admin-js' )
		);

		wp_localize_script(
			'monitorcat-module-' . $this->slug() . '-js',
			'MonitorCatModule',
			array(
				'restBase' => esc_url_raw( rest_url( 'monitor-cat/v1/' ) ),
				'nonce'    => wp_create_nonce( 'wp_rest' ),
				'slug'     => $this->slug(),
			)
		);
	}

	/**
	 * Render the module's admin page.
	 */
	public function render_page(): void {
		$this->renderer->render(
			'modules/' . $this->slug() . '/page',
			array(
				'module' => $this,
			)
		);
	}

	/**
	 * Check whether the current page belongs to this module.
	 *
	 * @param string $hook_suffix The current admin page hook suffix.
	 * @return bool True if on this module's page.
	 */
	protected function is_own_page( string $hook_suffix ): bool {
		return str_contains( $hook_suffix, 'monitor-cat-' . $this->slug() );
	}
}
