<?php
/**
 * Admin module registry.
 *
 * @package Noesia_Commerce_Suite
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Registry for admin modules/tabs.
 *
 * This is the source of truth for tab order, labels, icons and views.
 */
class Noesia_CS_Module_Registry {
	/**
	 * Registered modules keyed by module slug.
	 *
	 * @var array<string,object>
	 */
	private $modules = array();

	/**
	 * Optional service container passed to modules that support it.
	 *
	 * @var Noesia_CS_Container|null
	 */
	private $container = null;

	/**
	 * Constructor.
	 *
	 * @param mixed $container Optional service container.
	 */
	public function __construct( $container = null ) {
		if ( $container instanceof Noesia_CS_Container ) {
			$this->container = $container;
		}
		$this->register_defaults();
	}

	/**
	 * Register the default admin modules.
	 *
	 * @return void
	 */
	private function register_defaults() {
		$classes = array(
			'dashboard'               => 'Noesia_CS_Dashboard_Module',
			'order-care-hub'          => 'Noesia_CS_Order_Care_Hub_Module',
			'reorder-reminders'       => 'Noesia_CS_Reorder_Reminders_Module',
			'reviews-support'         => 'Noesia_CS_Reviews_Support_Module',
			'intelligence-analytics'  => 'Noesia_CS_Intelligence_Analytics_Module',
			'impact-map'              => 'Noesia_CS_Impact_Map_Module',
			'ecommerce-doctor'        => 'Noesia_CS_Ecommerce_Doctor_Module',
			'emails'                  => 'Noesia_CS_Emails_Module',
			'settings'                => 'Noesia_CS_Settings_Module',
			'upgrade-pro'             => 'Noesia_CS_Upgrade_Pro_Module',
		);

		foreach ( $classes as $key => $class_name ) {
			if ( class_exists( $class_name ) ) {
				$module = new $class_name();
				$this->register( $module );
			}
		}
	}

	/**
	 * Register a module object.
	 *
	 * @param object $module Module instance.
	 * @return void
	 */
	public function register( $module ) {
		if ( ! $module || ! is_object( $module ) || ! method_exists( $module, 'key' ) ) {
			return;
		}

		if ( $this->container && method_exists( $module, 'set_container' ) ) {
			$module->set_container( $this->container );
		}

		$key = sanitize_key( $module->key() );
		if ( ! $key ) {
			return;
		}

		$this->modules[ $key ] = $module;
	}

	/**
	 * Return all modules.
	 *
	 * @return array<string,object>
	 */
	public function all() {
		return $this->modules;
	}

	/**
	 * Return tab labels keyed by module slug.
	 *
	 * @return array<string,string>
	 */
	public function tabs() {
		$tabs = array();
		foreach ( $this->modules as $key => $module ) {
			$tabs[ $key ] = $module->label();
		}
		return $tabs;
	}

	/**
	 * Check whether a module exists.
	 *
	 * @param string $key Module key.
	 * @return bool
	 */
	public function has( $key ) {
		$key = sanitize_key( $key );
		return isset( $this->modules[ $key ] );
	}

	/**
	 * Get a module by key.
	 *
	 * @param string $key Module key.
	 * @return object|null
	 */
	public function get( $key ) {
		$key = sanitize_key( $key );
		return $this->has( $key ) ? $this->modules[ $key ] : null;
	}

	/**
	 * Return a module label.
	 *
	 * @param string $key Module key.
	 * @return string
	 */
	public function label( $key ) {
		$module = $this->get( $key );
		return $module ? $module->label() : '';
	}

	/**
	 * Return a module icon.
	 *
	 * @param string $key Module key.
	 * @return string
	 */
	public function icon( $key ) {
		$module = $this->get( $key );
		return $module ? $module->icon() : '•';
	}

	/**
	 * Return a module description.
	 *
	 * @param string $key Module key.
	 * @return string
	 */
	public function description( $key ) {
		$module = $this->get( $key );
		return $module ? $module->description() : '';
	}

	/**
	 * Check whether a module is a primary module.
	 *
	 * @param string $key Module key.
	 * @return bool
	 */
	public function is_primary( $key ) {
		$module = $this->get( $key );
		return $module ? $module->is_primary() : false;
	}

	/**
	 * Return a module view path.
	 *
	 * @param string $key Module key.
	 * @return string
	 */
	public function view_path( $key ) {
		$module = $this->get( $key );
		return $module ? $module->view_path() : '';
	}

	/**
	 * Render a module view.
	 *
	 * @param string $key     Module key.
	 * @param array  $context Render context.
	 * @return bool True when rendered, false otherwise.
	 */
	public function render( $key, $context = array() ) {
		$module = $this->get( $key );
		if ( ! $module ) {
			return false;
		}

		$module->render( $context );
		return true;
	}
}
