<?php
/**
 * @package Hafenstudios\Core
 */

namespace Hafenstudios\Core;

use Hafenstudios\Core\Admin\DesignSystem;
use Hafenstudios\Core\Ai\AiClient;
use Hafenstudios\Core\Consent\ConsentLog;
use Hafenstudios\Core\Db\Migrator;
use Hafenstudios\Core\Hans\Hans;
use Hafenstudios\Core\Logging\Logger;
use Hafenstudios\Core\Mail\Mailer;
use Hafenstudios\Core\Privacy\PrivacyManager;
use Hafenstudios\Core\Settings\Settings;
use Hafenstudios\Core\Support\Capabilities;

defined( 'ABSPATH' ) || exit;

/**
 * Zentraler Einstiegspunkt der gewaehlten Core-Kopie.
 *
 * Bootet die geteilten Subsysteme und dient als schlanke Service-Registry, ueber
 * die die Plugins der Flotte (Leadlotse, Kurato, ...) auf gemeinsame Dienste
 * zugreifen. Es gibt genau eine aktive Instanz pro Request.
 */
final class Core {

	/**
	 * Singleton-Instanz.
	 *
	 * @var Core|null
	 */
	private static ?Core $instance = null;

	/**
	 * Gemeinsam genutzte Dienst-Instanzen (lazy).
	 *
	 * @var array<string, object>
	 */
	private array $services = array();

	/**
	 * Bereits registrierte Plugins der Flotte.
	 *
	 * @var array<string, array<string, mixed>>
	 */
	private array $plugins = array();

	/**
	 * Ob boot() bereits gelaufen ist.
	 *
	 * @var bool
	 */
	private bool $booted = false;

	/**
	 * Nicht direkt instanziieren.
	 */
	private function __construct() {}

	/**
	 * Liefert die aktive Core-Instanz.
	 *
	 * @return Core
	 */
	public static function instance(): Core {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Bootet die geteilten Subsysteme. Idempotent.
	 *
	 * @return void
	 */
	public function boot(): void {
		if ( $this->booted ) {
			return;
		}
		$this->booted = true;

		$this->load_textdomain();

		Capabilities::instance()->boot();
		$this->consent()->boot();
		$this->hans()->boot();
		$this->privacy()->boot();

		if ( is_admin() ) {
			DesignSystem::instance()->boot();
		}

		/**
		 * Signalisiert, dass der Core einsatzbereit ist. Plugins koennen hier
		 * ihre Core-abhaengige Initialisierung anschliessen.
		 *
		 * @param Core $core Aktive Core-Instanz.
		 */
		do_action( 'hafenstudios/core_booted', $this );
	}

	/**
	 * Registriert ein Plugin der Flotte fuer die geteilten Ansichten (z.B. Kompass).
	 *
	 * @param string               $slug Plugin-Slug.
	 * @param array<string, mixed> $args Metadaten (name, version, menu_slug, ...).
	 * @return void
	 */
	public function register_plugin( string $slug, array $args = array() ): void {
		$this->plugins[ $slug ] = $args;
	}

	/**
	 * Liefert alle registrierten Plugins.
	 *
	 * @return array<string, array<string, mixed>>
	 */
	public function plugins(): array {
		return $this->plugins;
	}

	/**
	 * Liefert (oder erzeugt) einen Settings-Speicher fuer einen Namespace.
	 *
	 * @param string               $namespace Plugin-Slug, z.B. "leadlotse".
	 * @param array<string, mixed> $defaults  Standardwerte.
	 * @return Settings
	 */
	public function settings( string $namespace, array $defaults = array() ): Settings {
		$key = 'settings:' . $namespace;
		if ( ! isset( $this->services[ $key ] ) ) {
			$this->services[ $key ] = new Settings( $namespace, $defaults );
		}
		return $this->services[ $key ];
	}

	/**
	 * Liefert einen Migrator fuer eigene Tabellen eines Plugins.
	 *
	 * @param string $namespace      Plugin-Slug.
	 * @param string $target_version Ziel-Schemaversion.
	 * @return Migrator
	 */
	public function migrator( string $namespace, string $target_version ): Migrator {
		return new Migrator( $namespace, $target_version );
	}

	/**
	 * Liefert das Consent-Log (plugin-uebergreifend).
	 *
	 * @return ConsentLog
	 */
	public function consent(): ConsentLog {
		return $this->services['consent'] ??= new ConsentLog();
	}

	/**
	 * Liefert den Transaktions-Mailer.
	 *
	 * @return Mailer
	 */
	public function mailer(): Mailer {
		return $this->services['mailer'] ??= new Mailer();
	}

	/**
	 * Liefert das Hans-Framework.
	 *
	 * @return Hans
	 */
	public function hans(): Hans {
		return $this->services['hans'] ??= new Hans();
	}

	/**
	 * Liefert die KI-Fassade (HANS-KI-KONZEPT Abschnitt 3). Waehlt anhand der
	 * Option `hs_core_ai` den Treiber (BYO Anthropic/OpenAI-kompatibel oder
	 * Hafenstudios-Proxy); liefert bei abgeschalteter KI oder Fehlern immer ein
	 * AiResult mit ok=false, nie eine Ausnahme.
	 *
	 * @return AiClient
	 */
	public function ai(): AiClient {
		return $this->services['ai'] ??= new AiClient();
	}

	/**
	 * Liefert die Privacy-Integration.
	 *
	 * @return PrivacyManager
	 */
	public function privacy(): PrivacyManager {
		return $this->services['privacy'] ??= new PrivacyManager();
	}

	/**
	 * Liefert einen (opt-in) Logger fuer einen Namespace.
	 *
	 * @param string $namespace Plugin-Slug.
	 * @return Logger
	 */
	public function logger( string $namespace = 'core' ): Logger {
		$key = 'logger:' . $namespace;
		return $this->services[ $key ] ??= new Logger( $namespace );
	}

	/**
	 * Laedt die Uebersetzungen der Core-Bibliothek (Textdomain hafenstudios-core)
	 * aus dem languages-Ordner der gewaehlten Kopie.
	 *
	 * @return void
	 */
	private function load_textdomain(): void {
		if ( ! defined( 'HAFENSTUDIOS_CORE_DIR' ) ) {
			return;
		}
		$locale = determine_locale();
		$mofile = HAFENSTUDIOS_CORE_DIR . '/languages/hafenstudios-core-' . $locale . '.mo';
		if ( is_readable( $mofile ) ) {
			load_textdomain( 'hafenstudios-core', $mofile );
		}
	}

	/**
	 * Version der aktiven Core-Kopie.
	 *
	 * @return string
	 */
	public function version(): string {
		return defined( 'HAFENSTUDIOS_CORE_VERSION' ) ? HAFENSTUDIOS_CORE_VERSION : '1.0.0';
	}
}
