<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Router\RouteCollection;

/**
 * Module Loader Configuration
 * 
 * Handles automatic discovery and loading of module routes.
 * Each module can contain a Routes.php file that will be automatically loaded.
 */
class ModuleLoader extends BaseConfig
{
    /**
     * Base path for modules directory
     * 
     * @var string
     */
    protected string $modulesPath = APPPATH . 'Modules' . DIRECTORY_SEPARATOR;

    /**
     * Route file name to look for in each module
     * 
     * @var string
     */
    protected string $routeFileName = 'Routes.php';

    /**
     * Load all module routes automatically
     * 
     * Scans app/Modules/* directories and loads Routes.php from each module
     * if it exists.
     * 
     * @param RouteCollection $routes The route collection instance
     * @return void
     */
    public function loadModuleRoutes(RouteCollection $routes): void
    {
        if (!is_dir($this->modulesPath)) {
            return;
        }

        // Get all module directories
        $modules = $this->getModuleDirectories();

        foreach ($modules as $moduleName => $modulePath) {
            $routeFile = $modulePath . DIRECTORY_SEPARATOR . $this->routeFileName;

            if (file_exists($routeFile)) {
                $this->loadModuleRouteFile($routeFile, $routes, $moduleName);
            }
        }
    }

    /**
     * Get all module directories
     * 
     * @return array<string, string> Array of module name => module path
     */
    protected function getModuleDirectories(): array
    {
        $modules = [];
        $dirs = scandir($this->modulesPath);

        foreach ($dirs as $dir) {
            if ($dir === '.' || $dir === '..') {
                continue;
            }

            $modulePath = $this->modulesPath . $dir;

            if (is_dir($modulePath)) {
                $modules[$dir] = $modulePath;
            }
        }

        return $modules;
    }

    /**
     * Load a module route file
     * 
     * @param string $routeFile Full path to Routes.php file
     * @param RouteCollection $routes The route collection instance
     * @param string $moduleName Name of the module
     * @return void
     */
    protected function loadModuleRouteFile(string $routeFile, RouteCollection $routes, string $moduleName): void
    {
        // Include the route file
        // The route file should use the $routes variable passed to it
        if (file_exists($routeFile)) {
            // Make $routes available in the included file's scope
            // Extract to current scope so Routes.php can access $routes variable
            extract(['routes' => $routes], EXTR_SKIP);
            require $routeFile;
        }
    }

    /**
     * Get list of available modules
     * 
     * @return array<string> List of module names
     */
    public function getAvailableModules(): array
    {
        return array_keys($this->getModuleDirectories());
    }

    /**
     * Check if a module exists
     * 
     * @param string $moduleName Name of the module
     * @return bool
     */
    public function moduleExists(string $moduleName): bool
    {
        $modulePath = $this->modulesPath . $moduleName;
        return is_dir($modulePath);
    }

    /**
     * Get module path
     * 
     * @param string $moduleName Name of the module
     * @return string|null Module path or null if not found
     */
    public function getModulePath(string $moduleName): ?string
    {
        if (!$this->moduleExists($moduleName)) {
            return null;
        }

        return $this->modulesPath . $moduleName;
    }
}
