<?php

declare( strict_types=1 );

namespace StrykeWP\Core;

use StrykeWP\Admin\Dashboard;
use StrykeWP\Admin\MenuManager;
use StrykeWP\Modules\ModuleRegistry;

/**
 * Main plugin orchestrator for STRYKE WP.
 *
 * Receives all pre-built services via constructor (Dependency Injection).
 * Registers global WordPress hooks and boots enabled modules.
 *
 * Dependency graph:
 *   Plugin
 *     ├── Logger          (no deps)
 *     ├── OptionManager   (no deps)
 *     ├── AssetManager    (base_url, version)
 *     ├── CronManager     (no deps)
 *     ├── ModuleRegistry  (OptionManager, Logger)
 *     ├── Dashboard       (ModuleRegistry, AssetManager, OptionManager, Logger)
 *     └── MenuManager     (ModuleRegistry, Dashboard)
 *
 * @package StrykeWP\Core
 */
class Plugin {

	public function __construct(
		private readonly Logger         $logger,
		private readonly OptionManager  $options,
		private readonly AssetManager   $assets,
		private readonly CronManager    $cron,
		private readonly ModuleRegistry $registry,
		private readonly MenuManager    $menu,
		private readonly Dashboard      $dashboard,
	) {}

	// ---------------------------------------------------------------------------
	// Boot
	// ---------------------------------------------------------------------------

	/**
	 * Registers all WordPress hooks and boots enabled modules.
	 *
	 * Called once from `stryke_wp_init()` on `plugins_loaded`.
	 */
	public function boot(): void {
		$this->maybe_flush_rewrites();
		$this->maybe_upgrade_schema();

		// Run one-time migration from individual plugins BEFORE booting modules,
		// so any newly-enabled module flags are picked up by boot_enabled_modules().
		Migrator::maybe_run( $this->options, $this->logger );

		// Core services — run on every request.
		$this->cron->register_hooks();
		$this->assets->register_hooks();

		if ( is_admin() ) {
			$this->menu->register_hooks();
			$this->dashboard->register_hooks();

			// Show a WP admin notice on ALL admin pages if individual plugins
			// are still active alongside the master plugin.
			add_action( 'admin_notices', [ $this, 'render_conflict_notice' ] );
		}

		// Boot all enabled modules (they register their own hooks).
		$this->registry->boot_enabled_modules();

		$this->logger->info( 'STRYKE WP booted.', [ 'version' => STRYKE_WP_VERSION ] );
	}

	// ---------------------------------------------------------------------------
	// Helpers
	// ---------------------------------------------------------------------------

	/**
	 * Flushes rewrite rules once after activation if the flag is set.
	 */
	private function maybe_flush_rewrites(): void {
		if ( $this->options->get( 'flush_rewrite_rules' ) ) {
			flush_rewrite_rules();
			$this->options->delete( 'flush_rewrite_rules' );
		}
	}

	/**
	 * Runs DB schema upgrades when the plugin version changes.
	 */
	private function maybe_upgrade_schema(): void {
		SchemaManager::maybe_upgrade( $this->options );
	}

	// ---------------------------------------------------------------------------
	// Admin Notices
	// ---------------------------------------------------------------------------

	/**
	 * Outputs a WP admin notice when individual STRYKE plugins are still active
	 * alongside the master plugin.
	 *
	 * Running both causes duplicate hooks, doubled admin menus, and undefined
	 * behaviour. The notice persists until all conflicting plugins are deactivated.
	 *
	 * Hooked to `admin_notices` from boot().
	 *
	 * @return void
	 */
	public function render_conflict_notice(): void {
		$conflicts = Migrator::get_conflicts();

		if ( empty( $conflicts ) ) {
			return;
		}

		// Map module IDs to human-readable plugin names.
		$names = [
			'connector' => 'STRYKE Hub Connector',
			'branding'  => 'STRYKE Marketing Branding',
			'backup'    => 'STRYKE Backup – Google Drive',
			'wip_mode'  => 'STRYKE WIP Mode',
		];

		$plugin_list = implode(
			', ',
			array_map(
				static fn( string $id ) => '<strong>' . esc_html( $names[ $id ] ?? $id ) . '</strong>',
				array_keys( $conflicts )
			)
		);

		$deactivate_url = admin_url( 'plugins.php' );
		?>
		<div class="notice notice-warning">
			<p>
				<strong><?php esc_html_e( 'STRYKE WP — Konflikt erkannt', 'stryke-wp' ); ?></strong>
			</p>
			<p>
				<?php
				printf(
					/* translators: %s: comma-separated list of plugin names */
					wp_kses(
						__( 'Die folgenden Einzel-Plugins sind noch aktiv und überschneiden sich mit STRYKE WP: %s. Bitte deaktiviere sie, um Konflikte und doppelte Funktionen zu vermeiden.', 'stryke-wp' ),
						[ 'strong' => [] ]
					),
					$plugin_list // Already escaped above via esc_html() inside each item.
				);
				?>
			</p>
			<p>
				<a href="<?php echo esc_url( $deactivate_url ); ?>" class="button button-primary">
					<?php esc_html_e( 'Plugins verwalten', 'stryke-wp' ); ?>
				</a>
			</p>
		</div>
		<?php
	}

	// ---------------------------------------------------------------------------
	// Service Accessors (for modules that need shared services)
	// ---------------------------------------------------------------------------

	public function logger(): Logger {
		return $this->logger;
	}

	public function options(): OptionManager {
		return $this->options;
	}

	public function assets(): AssetManager {
		return $this->assets;
	}

	public function registry(): ModuleRegistry {
		return $this->registry;
	}
}
