<?php
declare(strict_types=1);


/**
 * Module Loader
 *
 * Loads FREE tier modules only. Premium modules are in prorank-seo plugin.
 *
 * @package ProRankSEO\Core
 */

namespace ProRank\SEO\Core;

use ProRank\SEO\Contracts\ModuleInterface;

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


/**
 * ModuleLoader class
 */


class ModuleLoader {
    /**
     * Module manager instance
     *
     * @var ModuleManager
     */
    private ModuleManager $module_manager;

    /**
     * Constructor
     *
     * @param ModuleManager $module_manager Module manager instance.
     */
    public function __construct(ModuleManager $module_manager) {
        $this->module_manager = $module_manager;
    }

    /**
     * Load all FREE modules
     */
    public function load(): void {
        $modules_dir = PRORANK_PLUGIN_DIR . 'includes/Modules';
        
        if (!is_dir($modules_dir)) {
            return;
        }

        $this->scan_directory($modules_dir);
    }

    /**
     * Recursively scan directory for module classes
     *
     * @param string $dir Directory to scan.
     */
    private function scan_directory(string $dir): void {
        $items = scandir($dir);
        
        foreach ($items as $item) {
            if ($item === '.' || $item === '..') {
                continue;
            }
            
            $path = $dir . '/' . $item;
            
            if (is_dir($path)) {
                $this->scan_directory($path);
            } elseif (is_file($path) && str_ends_with($item, 'Module.php')) {
                $this->load_module_file($path);
            }
        }
    }

    /**
     * Load a module file and register it
     *
     * @param string $file_path Path to module file.
     */
    private function load_module_file(string $file_path): void {
        // Get relative path from includes directory
        $relative_path = str_replace(PRORANK_PLUGIN_DIR . 'includes/', '', $file_path);
        $relative_path = str_replace('.php', '', $relative_path);
        $relative_path = str_replace('/', '\\', $relative_path);
        
        // Build class name
        $class_name = 'ProRank\\SEO\\' . $relative_path;
        
        // Skip if class doesn't exist
        if (!class_exists($class_name)) {
            return;
        }
        
        // Skip if not a module
        $reflection = new \ReflectionClass($class_name);
        if (!$reflection->implementsInterface(ModuleInterface::class)) {
            return;
        }
        
        // Skip abstract classes
        if ($reflection->isAbstract()) {
            return;
        }
        
        // Only register modules that declare free tier in class defaults.
        // This keeps paid module classes inert even if files exist locally.
        $defaults = $reflection->getDefaultProperties();
        $tier = isset($defaults['feature_tier']) ? (string) $defaults['feature_tier'] : 'free';
        if ($tier === 'core') {
            $tier = 'pro';
        }
        if ($tier !== 'free') {
            return;
        }

        try {
            $module = new $class_name();

            // Runtime safety net: enforce free-only tier requirement as well.
            $required_tier = method_exists($module, 'tier_required')
                ? (string) $module->tier_required()
                : 'free';
            if ($required_tier === 'core') {
                $required_tier = 'pro';
            }
            if ($required_tier !== 'free') {
                return;
            }

            $this->module_manager->register_module($module);
        } catch (\Exception $e) {
            prorank_log('[ProRank SEO] Failed to load module ' . $class_name . ': ' . $e->getMessage());
        }
    }
}
