<?php
/**
 * Compatibility Handler - Main Loader
 *
 * Automatically detects and loads compatibility files for third-party themes and plugins.
 *
 * @since   4.4.5
 * @package Extra_Product_Options_For_WooCommerce
 */

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

/**
 * EPOFW Compatibility Class
 *
 * @since 4.4.5
 *
 * Handles loading of theme and plugin compatibility files.
 */
class EPOFW_Compatibility {

	/**
	 * Instance of this class.
	 *
	 * @since 4.4.5
	 *
	 * @var EPOFW_Compatibility
	 */
	private static $instance = null;

	/**
	 * Compatibility directory path.
	 *
	 * @since 4.4.5
	 *
	 * @var string
	 */
	private $compatibility_path;

	/**
	 * List of loaded compatibility modules.
	 *
	 * @since 4.4.5
	 *
	 * @var array
	 */
	private $loaded_modules = array();

	/**
	 * Theme compatibility mappings.
	 * Key: theme slug (or parent theme slug), Value: compatibility class file.
	 *
	 * @since 4.4.5
	 *
	 * @var array
	 */
	private $theme_mappings = array(
		// Flavor theme and child themes.
		'flavor'             => 'class-epofw-theme-flavor.php',
		// Elessi theme and child themes.
		'elessi-theme'       => 'class-epofw-theme-flavor.php',
		'elessi-theme-child' => 'class-epofw-theme-flavor.php',
		// Add more theme mappings here.
		// 'theme-slug' => 'class-epofw-theme-themename.php'.
	);

	/**
	 * Plugin compatibility mappings.
	 * Key: plugin file path, Value: compatibility class file.
	 *
	 * @since 4.4.5
	 *
	 * @var array
	 */
	private $plugin_mappings = array(
		// Add plugin mappings here.
		// 'plugin-folder/plugin-file.php' => 'class-epofw-plugin-name.php'.
	);

	/**
	 * Constructor.
	 *
	 * @since 4.4.5
	 */
	private function __construct() {
		$this->compatibility_path = plugin_dir_path( __FILE__ );
		$this->init();
	}

	/**
	 * Initialize compatibility loading.
	 *
	 * @since 4.4.5
	 */
	private function init() {
		/**
		 * Filter theme compatibility mappings before loading.
		 *
		 * @since 4.4.5
		 *
		 * @param array $theme_mappings Theme slug to file mappings.
		 */
		$this->theme_mappings = apply_filters( 'epofw_compatibility_theme_mappings', $this->theme_mappings );

		/**
		 * Filter plugin compatibility mappings before loading.
		 *
		 * @since 4.4.5
		 *
		 * @param array $plugin_mappings Plugin file to compatibility file mappings.
		 */
		$this->plugin_mappings = apply_filters( 'epofw_compatibility_plugin_mappings', $this->plugin_mappings );

		// Load theme compatibility.
		$this->load_theme_compatibility();

		// Load plugin compatibility.
		$this->load_plugin_compatibility();

		/**
		 * Fires after all compatibility modules are loaded.
		 *
		 * @since 4.4.5
		 *
		 * @param array $loaded_modules List of loaded compatibility modules.
		 */
		do_action( 'epofw_compatibility_loaded', $this->loaded_modules );
	}

	/**
	 * Load a theme compatibility file if the current theme is supported.
	 *
	 * @since 4.4.5
	 */
	private function load_theme_compatibility() {
		$theme        = wp_get_theme();
		$theme_slug   = $theme->get_stylesheet();
		$parent_theme = $theme->parent();

		// Check current theme.
		if ( isset( $this->theme_mappings[ $theme_slug ] ) ) {
			$this->load_theme_file( $this->theme_mappings[ $theme_slug ], $theme_slug );

			return;
		}

		// Check parent theme if child theme is active.
		if ( $parent_theme ) {
			$parent_slug = $parent_theme->get_stylesheet();
			if ( isset( $this->theme_mappings[ $parent_slug ] ) ) {
				$this->load_theme_file( $this->theme_mappings[ $parent_slug ], $parent_slug );

				return;
			}
		}

		// Check by theme name (case-insensitive).
		$theme_name = strtolower( $theme->get( 'Name' ) );
		foreach ( $this->theme_mappings as $mapped_slug => $file ) {
			if ( strpos( $theme_name, strtolower( $mapped_slug ) ) !== false ) {
				$this->load_theme_file( $file, $mapped_slug );

				return;
			}
		}
	}

	/**
	 * Load a theme compatibility file.
	 *
	 * @since 4.4.5
	 *
	 * @param string $file       File name.
	 * @param string $theme_slug Theme slug for logging.
	 */
	private function load_theme_file( $file, $theme_slug ) {
		// Sanitize file name to prevent directory traversal.
		$file      = basename( $file );
		$file_path = $this->compatibility_path . 'themes/' . $file;

		// Validate path is within expected directory using realpath.
		$real_path     = realpath( $file_path );
		$expected_base = realpath( $this->compatibility_path . 'themes' );

		// Only load if file exists and is within the themes directory.
		// nosemgrep: audit.php.lang.security.file.inclusion-arg -- File path is validated: basename() prevents traversal, realpath() confirms location.
		if ( $real_path && $expected_base && strpos( $real_path, $expected_base ) === 0 ) {
			require_once $file_path;
			$this->loaded_modules[] = array(
				'type' => 'theme',
				'slug' => $theme_slug,
				'file' => $file,
			);
		}
	}

	/**
	 * Load plugin compatibility files for active plugins.
	 *
	 * @since 4.4.5
	 */
	private function load_plugin_compatibility() {
		if ( empty( $this->plugin_mappings ) ) {
			return;
		}

		$active_plugins = get_option( 'active_plugins', array() );

		foreach ( $this->plugin_mappings as $plugin_file => $compat_file ) {
			if ( in_array( $plugin_file, $active_plugins, true ) ) {
				$this->load_plugin_file( $compat_file, $plugin_file );
			}
		}
	}

	/**
	 * Load a plugin compatibility file.
	 *
	 * @since 4.4.5
	 *
	 * @param string $file        File name.
	 * @param string $plugin_file Plugin file for logging.
	 */
	private function load_plugin_file( $file, $plugin_file ) {
		// Sanitize file name to prevent directory traversal.
		$file      = basename( $file );
		$file_path = $this->compatibility_path . 'plugins/' . $file;

		// Validate path is within expected directory using realpath.
		$real_path     = realpath( $file_path );
		$expected_base = realpath( $this->compatibility_path . 'plugins' );

		// Only load if file exists and is within the plugins directory.
		// nosemgrep: audit.php.lang.security.file.inclusion-arg -- File path is validated: basename() prevents traversal, realpath() confirms location.
		if ( $real_path && $expected_base && strpos( $real_path, $expected_base ) === 0 ) {
			require_once $file_path;
			$this->loaded_modules[] = array(
				'type' => 'plugin',
				'slug' => $plugin_file,
				'file' => $file,
			);
		}
	}

	/**
	 * Get instance of this class.
	 *
	 * @since 4.4.5
	 *
	 * @return EPOFW_Compatibility
	 */
	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * Get a list of loaded compatibility modules.
	 *
	 * @since 4.4.5
	 *
	 * @return array
	 */
	public function get_loaded_modules() {
		return $this->loaded_modules;
	}

	/**
	 * Check if a specific compatibility module is loaded.
	 *
	 * @since 4.4.5
	 *
	 * @param string $slug Theme or plugin slug.
	 *
	 * @return bool
	 */
	public function is_module_loaded( $slug ) {
		foreach ( $this->loaded_modules as $module ) {
			if ( $module['slug'] === $slug ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Register a new theme compatibility mapping.
	 *
	 * @since 4.4.5
	 *
	 * @param string $theme_slug Theme slug.
	 * @param string $file       Compatibility file name.
	 */
	public function register_theme( $theme_slug, $file ) {
		$this->theme_mappings[ $theme_slug ] = $file;
	}

	/**
	 * Register a new plugin compatibility mapping.
	 *
	 * @since 4.4.5
	 *
	 * @param string $plugin_file Plugin file path.
	 * @param string $file        Compatibility file name.
	 */
	public function register_plugin( $plugin_file, $file ) {
		$this->plugin_mappings[ $plugin_file ] = $file;
	}
}

// Initialize compatibility.
EPOFW_Compatibility::instance();
