<?php
/**
 * Asset Manager Class
 *
 * Handles enqueueing of compiled CSS and JavaScript assets.
 *
 * @package RedFoxWP\RedFoxTabManager
 * @since 1.0.0
 */

namespace RedFoxWP\RedFoxTabManager;

use RedFoxWP\RedFoxTabManager\Abstracts\Abstract_Singleton;

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

/**
 * Asset Manager class
 *
 * Manages the loading and enqueueing of plugin assets (CSS and JavaScript).
 *
 * @since 1.0.0
 */
class Asset_Manager extends Abstract_Singleton {

	/**
	 * Plugin version for cache busting
	 *
	 * @since 1.0.0
	 * @access private
	 *
	 * @var string
	 */
	private $version;

	/**
	 * Plugin URL
	 *
	 * @since 1.0.0
	 * @access private
	 *
	 * @var string
	 */
	private $plugin_url;

	/**
	 * Build directory path
	 *
	 * @since 1.0.0
	 * @access private
	 *
	 * @var string
	 */
	private $build_dir;

	/**
	 * Constructor
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @return void
	 */
	protected function __construct() {
		$this->version    = REDFOX_TAB_MANAGER_VERSION;
		$this->plugin_url = REDFOX_TAB_MANAGER_PLUGIN_URL;
		$this->build_dir  = REDFOX_TAB_MANAGER_PLUGIN_DIR . 'build/';

		$this->init_hooks();
	}

	/**
	 * Initialize WordPress hooks
	 *
	 * @since 1.0.0
	 * @access private
	 *
	 * @return void
	 */
	private function init_hooks() {
		// Register assets early.
		add_action( 'init', array( $this, 'register_all_assets' ) );

		// Enqueue admin assets.
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) );
	}

	/**
	 * Register all plugin assets
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @return void
	 */
	public function register_all_assets() {
		// Register admin assets.
		$this->register_assets(
			'admin',
			array(
				'register_style' => false,
			)
		);
	}

	/**
	 * Register assets.
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @param string $name Asset name to register assets for.
	 * @param array  $args {
	 *     Optional. Array of arguments for registering assets.
	 *
	 *     @type bool   $register_style      Whether to register the style asset. Default true.
	 *     @type array  $script_dependencies Additional script dependencies to merge with asset file dependencies. Default empty array.
	 *     @type array  $style_dependencies  Style dependencies. Default empty array.
	 *     @type string $style_prefix        Prefix for style filename. Default ''.
	 *     @type bool   $script_in_footer    Whether to enqueue script in footer. Default true.
	 * }
	 *
	 * @return void
	 */
	public function register_assets( $name = '', $args = array() ) {
		// Parse arguments with defaults.
		$args = wp_parse_args(
			$args,
			array(
				'register_style'      => true,
				'script_dependencies' => array(),
				'style_dependencies'  => array(),
				'style_prefix'        => '',
				'script_in_footer'    => true,
			)
		);

		$min = defined( 'REDFOXWP_DEBUG' ) && REDFOXWP_DEBUG ? '' : '.min';

		$prefixed_name = 'redfox-tab-manager-' . $name;

		// Register script.
		$asset_file_path = $this->build_dir . 'js/' . $name . $min . '.asset.php';
		$asset_file      = array();

		if ( file_exists( $asset_file_path ) && is_readable( $asset_file_path ) ) {
			$asset_file = include $asset_file_path;
		}

		$asset_file = $asset_file ?? array(
			'dependencies' => array(),
			'version'      => $this->version,
		);

		// Merge asset file dependencies with additional script dependencies.
		$script_dependencies = array_merge(
			$asset_file['dependencies'] ?? array(),
			$args['script_dependencies']
		);

		$js_file_path = $this->build_dir . 'js/' . $name . $min . '.js';
		if ( file_exists( $js_file_path ) ) {
			$script_registered = wp_register_script(
				$prefixed_name,
				$this->plugin_url . 'build/js/' . $name . $min . '.js',
				$script_dependencies,
				$asset_file['version'] ?? $this->version,
				$args['script_in_footer']
			);
		}

		if ( $args['register_style'] ) {
			// Register styles.
			$style_filename = ! empty( $args['style_prefix'] ) ? $args['style_prefix'] . $name : $name;
			$css_file_path  = $this->build_dir . 'css/' . $style_filename . $min . '.css';

			if ( file_exists( $css_file_path ) ) {
				$style_registered = wp_register_style(
					$prefixed_name,
					$this->plugin_url . 'build/css/' . $style_filename . $min . '.css',
					$args['style_dependencies'],
					( defined( 'WP_DEBUG' ) && WP_DEBUG ) ? filemtime( $css_file_path ) : $this->version
				);
			}
		}
	}

	/**
	 * Enqueue admin assets
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @param string $hook_suffix The current admin page hook suffix.
	 * @return void
	 */
	public function enqueue_admin_assets( $hook_suffix ) {
		// Check for Tab Manager page.
		if ( $this->is_tab_manager_page( $hook_suffix ) ) {
			$this->enqueue_tab_manager_assets( $hook_suffix );
			return;
		}
	}



	/**
	 * Check if current page is the Tab Manager page
	 *
	 * @since 1.0.0
	 * @access private
	 *
	 * @param string $hook_suffix Current admin page hook suffix.
	 * @return bool True if it's the Tab Manager page.
	 */
	private function is_tab_manager_page( $hook_suffix ) {
		return false !== strpos( $hook_suffix, 'redfox-tab-manager' );
	}

	/**
	 * Enqueue Tab Manager assets
	 *
	 * @since 1.0.0
	 * @access private
	 *
	 * @param string $hook_suffix Current admin page hook suffix.
	 * @return void
	 */
	private function enqueue_tab_manager_assets( $hook_suffix ) {
		// Only load on Tab Manager page.
		if ( ! $this->is_tab_manager_page( $hook_suffix ) ) {
			return;
		}

		// Enqueue admin assets (registered in register_all_assets).
		wp_enqueue_script( 'redfox-tab-manager-admin' );

		// Preload API requests to optimize initial page load.
		$this->preload_api_requests();

		// Localize script with WordPress settings.
		wp_localize_script(
			'redfox-tab-manager-admin',
			'redfoxTabManagerSettings',
			array(
				'dateFormat'     => $this->get_wordpress_date_format(),
				'timeFormat'     => $this->get_wordpress_time_format(),
				'pluginName'     => $this->get_plugin_name(),
				'pluginVersion'  => $this->get_plugin_version(),
				'duplicateNonce' => wp_create_nonce( 'redfox_tab_manager_duplicate_tab' ),
				'adminUrl'       => admin_url(),
			)
		);
	}

	/**
	 * Get WordPress date format from options
	 *
	 * @since 1.0.0
	 * @access private
	 *
	 * @return string WordPress date format or default fallback.
	 */
	private function get_wordpress_date_format() {
		return get_option( 'date_format' ) ?? 'F j, Y';
	}

	/**
	 * Get WordPress time format from options
	 *
	 * @since 1.0.0
	 * @access private
	 *
	 * @return string WordPress time format or default fallback.
	 */
	private function get_wordpress_time_format() {
		return get_option( 'time_format' ) ?? 'g:i a';
	}

	/**
	 * Get plugin data from WordPress plugin headers
	 *
	 * @since 1.0.0
	 * @access private
	 *
	 * @param string $field The plugin data field to retrieve (Name, Version, etc.).
	 * @param string $fallback Optional. Fallback value if field is not found. Default empty string.
	 *
	 * @return string Plugin data field value or fallback.
	 */
	private function get_plugin_data( $field, $fallback = '' ) {
		// Include plugin.php if not already loaded.
		if ( ! function_exists( 'get_plugin_data' ) ) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}

		$plugin_data = get_plugin_data( REDFOX_TAB_MANAGER_PLUGIN_FILE );
		return $plugin_data[ $field ] ?? $fallback;
	}

	/**
	 * Get plugin name from WordPress plugin data
	 *
	 * @since 1.0.0
	 * @access private
	 *
	 * @return string Plugin name or default fallback.
	 */
	private function get_plugin_name() {
		return $this->get_plugin_data( 'Name', __( 'RedFox Tab Manager', 'redfox-tab-manager' ) );
	}

	/**
	 * Get plugin version from constant or plugin data
	 *
	 * @since 1.0.0
	 * @access private
	 *
	 * @return string Plugin version or default fallback.
	 */
	private function get_plugin_version() {
		// First try to get from constant (preferred method).
		if ( defined( 'REDFOX_TAB_MANAGER_VERSION' ) ) {
			return REDFOX_TAB_MANAGER_VERSION;
		}

		// Fallback to plugin data.
		return $this->get_plugin_data( 'Version', '1.0.0' );
	}

	/**
	 * Preload API requests for initial page load optimization
	 *
	 * Uses rest_preload_api_request to preload commonly needed API data,
	 * reducing the number of HTTP requests when the page loads.
	 *
	 * @since 1.0.0
	 * @access private
	 *
	 * @return void
	 */
	private function preload_api_requests() {
		// Only preload if the function exists (WordPress 4.7+).
		if ( ! function_exists( 'rest_preload_api_request' ) ) {
			return;
		}

		// Check if user has permissions to access the endpoints.
		if ( ! current_user_can( 'manage_options' ) && ! current_user_can( 'edit_posts' ) ) {
			return;
		}

		// Preload global tabs data (most critical for the admin interface).
		if ( current_user_can( 'manage_options' ) ) {
			rest_preload_api_request(
				array(),
				'/wp-json/redfox-tab-manager/v1/global-tabs'
			);

			// Preload RedFox tabs for the modal dropdown.
			rest_preload_api_request(
				array(),
				'/wp-json/redfox-tab-manager/v1/available-tabs?' . http_build_query(
					array(
						'posts_per_page'  => -1,
						'orderby'         => 'date',
						'order'           => 'DESC',
						'include_content' => false,
					)
				)
			);
		}

		// Preload available tabs with initial parameters (for tab list).
		if ( current_user_can( 'edit_posts' ) ) {
			// Preload first page of available tabs with common settings.
			rest_preload_api_request(
				array(),
				'/wp-json/redfox-tab-manager/v1/available-tabs?' . http_build_query(
					array(
						'posts_per_page'  => 10,
						'page'            => 1,
						'orderby'         => 'date',
						'order'           => 'DESC',
						'include_content' => true,
						'all_statuses'    => true,
					)
				)
			);

			// Preload empty search for pagination info.
			rest_preload_api_request(
				array(),
				'/wp-json/redfox-tab-manager/v1/available-tabs?' . http_build_query(
					array(
						'search'          => '',
						'posts_per_page'  => 10,
						'page'            => 1,
						'orderby'         => 'date',
						'order'           => 'DESC',
						'include_content' => true,
						'all_statuses'    => true,
					)
				)
			);
		}
	}
}
