<?php

declare(strict_types=1);

namespace AllCoach\Modules;

defined( 'ABSPATH' ) || exit;

use AllCoach\Core\Container;
use AllCoach\Traits\Hooks;

abstract class AbstractModule implements ModuleInterface {

	use Hooks;

	protected Container $container;
	protected bool $enabled       = true;
	protected string $id          = '';
	protected string $name        = '';
	protected string $description = '';
	protected string $version     = '1.0.0';
	protected array $dependencies = [];

	public function __construct( Container $container ) {
		$this->container = $container;
		$this->loadModuleState();
	}

	/**
	 * {@inheritdoc}
	 */
	public function register(): void {
		// Override in child classes.
	}

	/**
	 * {@inheritdoc}
	 */
	public function boot(): void {
		if ( ! $this->isEnabled() ) {
			return;
		}

		// Override in child classes.
	}

	/**
	 * {@inheritdoc}
	 */
	public function isEnabled(): bool {
		return $this->enabled && $this->checkDependencies();
	}

	/**
	 * {@inheritdoc}
	 */
	public function getId(): string {
		return $this->id;
	}

	/**
	 * {@inheritdoc}
	 */
	public function getName(): string {
		return $this->name;
	}

	/**
	 * {@inheritdoc}
	 */
	public function getDescription(): string {
		return $this->description;
	}

	/**
	 * {@inheritdoc}
	 */
	public function getVersion(): string {
		return $this->version;
	}

	/**
	 * {@inheritdoc}
	 */
	public function getDependencies(): array {
		return $this->dependencies;
	}

	/**
	 * {@inheritdoc}
	 */
	public function enable(): void {
		$this->enabled = true;
		$this->saveModuleState();
		$this->doAction( "allcoach:module:{$this->id}:enabled" );
	}

	/**
	 * {@inheritdoc}
	 */
	public function disable(): void {
		$this->enabled = false;
		$this->saveModuleState();
		$this->doAction( "allcoach:module:{$this->id}:disabled" );
	}

	protected function checkDependencies(): bool {
		$registry = ModuleRegistry::getInstance();

		foreach ( $this->dependencies as $dependencyId ) {
			$dependency = $registry->getModule( $dependencyId );

			if ( ! $dependency || ! $dependency->isEnabled() ) {
				return false;
			}
		}

		return true;
	}

	protected function loadModuleState(): void {
		$enabledModules = get_option( '_allcoach_enabled_modules', [] );
		$this->enabled  = in_array( $this->id, $enabledModules, true );
	}

	protected function saveModuleState(): void {
		$enabledModules = get_option( '_allcoach_enabled_modules', [] );

		if ( $this->enabled ) {
			if ( ! in_array( $this->id, $enabledModules, true ) ) {
				$enabledModules[] = $this->id;
			}
		} else {
			$enabledModules = array_diff( $enabledModules, [ $this->id ] );
		}

		update_option( '_allcoach_enabled_modules', array_values( $enabledModules ) );
	}

	protected function get( string $id ): mixed {
		return $this->container->get( $id );
	}

	protected function has( string $id ): bool {
		return $this->container->has( $id );
	}
}
