<?php
/**
 * API Registry Class
 *
 * Manages and registers all REST API endpoints for RedFox Tab Manager.
 *
 * @package RedFoxWP\RedFoxTabManager
 * @since 1.0.0
 */

namespace RedFoxWP\RedFoxTabManager\API;

use RedFoxWP\RedFoxTabManager\Abstracts\Abstract_Singleton;
use RedFoxWP\RedFoxTabManager\Abstracts\Abstract_API_Endpoint;

// Prevent direct access.
if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * API Registry class
 *
 * Central registry for managing all API endpoints.
 * Follows the singleton pattern for consistent initialization.
 *
 * @since 1.0.0
 */
class API_Registry extends Abstract_Singleton {

	/**
	 * Collection of registered API endpoints
	 *
	 * @since 1.0.0
	 * @access private
	 *
	 * @var Abstract_API_Endpoint[]
	 */
	private $endpoints = array();

	/**
	 * Constructor
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @return void
	 */
	protected function __construct() {
		$this->init_hooks();
		$this->register_endpoints();
	}

	/**
	 * Initialize WordPress hooks
	 *
	 * @since 1.0.0
	 * @access private
	 *
	 * @return void
	 */
	private function init_hooks() {
		add_action( 'rest_api_init', array( $this, 'register_routes' ) );
	}

	/**
	 * Register all API endpoints
	 *
	 * @since 1.0.0
	 * @access private
	 *
	 * @return void
	 */
	private function register_endpoints() {
		// Register Available Tabs API.
		$this->endpoints['available_tabs'] = new Available_Tabs_API();

		// Register Global Tabs API.
		$this->endpoints['global_tabs'] = new Global_Tabs_API();

		/**
		 * Filter to allow additional API endpoints to be registered
		 *
		 * @since 1.0.0
		 *
		 * @param Abstract_API_Endpoint[] $endpoints Array of API endpoint instances.
		 */
		$this->endpoints = apply_filters( 'redfox_tab_manager_api_endpoints', $this->endpoints );
	}

	/**
	 * Register all routes for registered endpoints
	 *
	 * Called on the 'rest_api_init' hook.
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @return void
	 */
	public function register_routes() {
		foreach ( $this->endpoints as $endpoint ) {
			if ( $endpoint instanceof Abstract_API_Endpoint ) {
				$endpoint->register_routes();
			}
		}
	}

	/**
	 * Get a specific registered endpoint
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @param string $endpoint_key The endpoint key.
	 * @return Abstract_API_Endpoint|null
	 */
	public function get_endpoint( $endpoint_key ) {
		return isset( $this->endpoints[ $endpoint_key ] ) ? $this->endpoints[ $endpoint_key ] : null;
	}

	/**
	 * Get all registered endpoints
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @return Abstract_API_Endpoint[]
	 */
	public function get_endpoints() {
		return $this->endpoints;
	}

	/**
	 * Add a new endpoint to the registry
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @param string                $key The endpoint key.
	 * @param Abstract_API_Endpoint $endpoint The endpoint instance.
	 * @return bool True if added successfully, false otherwise.
	 */
	public function add_endpoint( $key, Abstract_API_Endpoint $endpoint ) {
		if ( isset( $this->endpoints[ $key ] ) ) {
			return false; // Endpoint already exists.
		}

		$this->endpoints[ $key ] = $endpoint;
		return true;
	}

	/**
	 * Remove an endpoint from the registry
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @param string $key The endpoint key.
	 * @return bool True if removed successfully, false otherwise.
	 */
	public function remove_endpoint( $key ) {
		if ( ! isset( $this->endpoints[ $key ] ) ) {
			return false; // Endpoint doesn't exist.
		}

		unset( $this->endpoints[ $key ] );
		return true;
	}

	/**
	 * Check if an endpoint is registered
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @param string $key The endpoint key.
	 * @return bool True if endpoint exists, false otherwise.
	 */
	public function has_endpoint( $key ) {
		return isset( $this->endpoints[ $key ] );
	}

	/**
	 * Get the API namespace used by all endpoints
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @return string
	 */
	public function get_namespace() {
		return Abstract_API_Endpoint::NAMESPACE;
	}

	/**
	 * Get all registered route patterns
	 *
	 * Useful for debugging and documentation purposes.
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @return array Array of route patterns grouped by endpoint.
	 */
	public function get_route_patterns() {
		$patterns = array();

		foreach ( $this->endpoints as $key => $endpoint ) {
			if ( $endpoint instanceof Abstract_API_Endpoint ) {
				$patterns[ $key ] = array(
					'base'      => $endpoint->get_route_base(),
					'class'     => get_class( $endpoint ),
					'namespace' => $this->get_namespace(),
				);
			}
		}

		return $patterns;
	}
}
