<?php
class Router
{
    const PUBLIC_CONTROLLERS = ['Login', 'Logout', 'Home', 'GpsIngest', 'Cron', 'Api', 'Verify', 'Install'];
    const PUBLIC_ACTIONS     = [];

    public static function route($url)
    {
        $rawController   = (isset($url[0]) && $url[0] != '') ? $url[0] : DEFAULT_CONTROLLER;
        $controller_name = self::resolveControllerName($rawController);
        $controller      = $controller_name . 'Controller';
        array_shift($url);

        $action_name = (isset($url[0]) && $url[0] != '') ? $url[0] : 'index';
        $action      = $action_name . 'Action';
        array_shift($url);

        $query_params = $url;

        $is_public = false;
        foreach (self::PUBLIC_CONTROLLERS as $pc) {
            if (strcasecmp($controller_name, $pc) === 0) { $is_public = true; break; }
        }

        if (!$is_public) {
            if (empty($_SESSION['user_id'])) {
                self::redirect('Login');
                return;
            }
            Session::checkActivity();
            // Reload perms every request so new grants take effect without re-login.
            // Cheap: one indexed SELECT per role.
            UserGroups::loadPermsIntoSession(
                (int)($_SESSION['user_group_id'] ?? 0),
                (int)($_SESSION['user_id']       ?? 0)
            );
        }

        if (!class_exists($controller)) {
            self::renderError("Controller <strong>{$controller_name}</strong> not found.");
            return;
        }

        $dispatch = new $controller($controller_name, $action);

        if (!method_exists($controller, $action)) {
            self::renderError("Action <strong>{$action_name}</strong> not found in <strong>{$controller_name}</strong>.");
            return;
        }

        if ($is_public) {
            call_user_func_array([$dispatch, $action], $query_params);
            return;
        }

        // Perm check — Administrator sees all; others gated by user_groups_perms
        $group = strtolower(trim($_SESSION['user_group_name'] ?? ''));
        if ($group === 'administrator' || UserGroups::sessionCanAccess($controller_name, $action_name)) {
            call_user_func_array([$dispatch, $action], $query_params);
            return;
        }

        self::renderError("You do not have permission to access this page.", 'warning');
    }

    public static function redirect($location)
    {
        if (!headers_sent()) {
            header("Location: " . PROOT . $location);
            exit();
        } else {
            echo '<script>window.location.href="' . PROOT . $location . '";</script>';
        }
    }

    private static function renderError(string $msg, string $type = 'danger'): void
    {
        $view = new View();
        $view->setLayout(empty($_SESSION['user_id']) ? 'l_auth' : DEFAULT_ADMIN_LAYOUT);
        $view->render('generals/fb_page', ['fb_msg' => "<p class='alert alert-{$type} text-center'>{$msg}</p>"]);
    }

    private static ?array $controllerMap = null;
    private static function resolveControllerName(string $raw): string
    {
        if (self::$controllerMap === null) {
            self::$controllerMap = [];
            $dir = ROOT . DS . 'app' . DS . 'controllers';
            if (is_dir($dir)) {
                foreach (scandir($dir) as $f) {
                    if (substr($f, -14) === 'Controller.php') {
                        $canonical = substr($f, 0, -14);
                        self::$controllerMap[strtolower($canonical)] = $canonical;
                    }
                }
            }
        }
        $key = strtolower($raw);
        return self::$controllerMap[$key] ?? ucwords($raw);
    }
}
