<?php
namespace Core;

/**
 * Custom Simple Router
 * Maps URL format: domain.com/{module}/{controller}/{method}/{id}
 * Routes them to the correct app/Modules
 */
class Router {
    protected $currentModule = 'Core'; // System Default Module
    protected $currentController = 'HomeController'; // System Default Controller
    protected $currentMethod = 'index';
    protected $params = [];

    public function __construct() {
        $url = $this->getUrl();
        $routeConfig = require_once ROOT_PATH . '/config/routes.php';

        // 1. Explicit Route Overrides Processing
        $fullPath = isset($_GET['url']) ? rtrim($_GET['url'], '/') : '';
        if (isset($routeConfig['explicit_routes'][$fullPath])) {
            [$expController, $expMethod] = explode('@', $routeConfig['explicit_routes'][$fullPath]);
            $this->currentController = $expController;
            $this->currentMethod = $expMethod;
            // The module should be extracted or mapped if strictly needed,
            // but we'll let it flow for now. If used, this needs more logic.
        }

        // 2. Module Mapping
        $moduleName = isset($url[0]) ? ucwords($url[0]) : 'Core';
        
        // 3. Middleware Protection Execution
        if (in_array($moduleName, $routeConfig['protected_modules']) && !in_array($moduleName, $routeConfig['public_modules'])) {
            if (isset($routeConfig['middlewares']['auth'])) {
                $authMiddleware = new $routeConfig['middlewares']['auth'];
                $authMiddleware->handle();
            }
        }

        // Module
        if (isset($url[0])) {
            if (is_dir(ROOT_PATH . '/app/Modules/' . $moduleName)) {
                $this->currentModule = $moduleName;
                unset($url[0]);
            }
        }

        // Controller
        if (isset($url[1])) {
            $controllerName = ucwords($url[1]) . 'Controller'; // e.g., 'login' -> 'LoginController'
            if (file_exists(ROOT_PATH . '/app/Modules/' . $this->currentModule . '/Controllers/' . $controllerName . '.php')) {
                $this->currentController = $controllerName;
                unset($url[1]);
            } else {
                // Fallback controller inside module (it means $url[1] is likely a method)
                $fallbackController = $this->currentModule . 'Controller'; 
                if (file_exists(ROOT_PATH . '/app/Modules/' . $this->currentModule . '/Controllers/' . $fallbackController . '.php')) {
                    $this->currentController = $fallbackController;
                }
            }
        } else {
            // Fallback controller inside module
            $controllerName = $this->currentModule . 'Controller'; 
            if (file_exists(ROOT_PATH . '/app/Modules/' . $this->currentModule . '/Controllers/' . $controllerName . '.php')) {
                $this->currentController = $controllerName;
            }
        }

        // Require Controller class (Fallback and load)
        $controllerFile = ROOT_PATH . '/app/Modules/' . $this->currentModule . '/Controllers/' . $this->currentController . '.php';
        
        if (file_exists($controllerFile)) {
            require_once $controllerFile;
        } else {
            $this->show404("تعذر العثور على المتحكم {$this->currentController} في موديول {$this->currentModule}");
        }

        $namespacedController = "\\App\\Modules\\{$this->currentModule}\\Controllers\\{$this->currentController}";

        if (!class_exists($namespacedController)) {
            // Fallback for non-namespaced legacy controllers just in case
            if (!class_exists($this->currentController)) {
                $this->show404("فشل في تحميل كلاس المتحكم {$namespacedController}");
            } else {
                $namespacedController = $this->currentController;
            }
        }

        $this->currentController = new $namespacedController;

        // 3. Method
        if (isset($url[1]) && method_exists($this->currentController, $url[1])) {
            $this->currentMethod = $url[1];
            unset($url[1]);
        } elseif (isset($url[2]) && method_exists($this->currentController, $url[2])) {
            $this->currentMethod = $url[2];
            unset($url[2]);
        }

        // Final check if method is callable
        if (!is_callable([$this->currentController, $this->currentMethod])) {
            $this->show404("الإجراء {$this->currentMethod} غير متوفر في {$this->currentController}");
        }

        // 4. Extract Param Array
        $this->params = $url ? array_values($url) : [];

        // 5. Execute Method in Controller payloading the params
        call_user_func_array([$this->currentController, $this->currentMethod], $this->params);
    }

    /**
     * Show a clean 404 error page (Legacy, now using abort helper)
     */
    protected function show404($message = "") {
        abort(404, $message);
    }

    /**
     * Sanitizes and parses raw request URL
     */
    public function getUrl() {
        if (isset($_GET['url'])) {
            $url = rtrim($_GET['url'], '/');
            $url = filter_var($url, FILTER_SANITIZE_URL);
            $url = explode('/', $url);
            return $url;
        }
        return [];
    }
}
