<?php

class Router
{
    private array $routes = [];

    public function __construct()
    {
        $this->routes = require APP_ROOT . '/config/routes.php';
    }

    public function dispatch(string $method, string $uri): void
    {
        $uri = trim($uri, '/');
        $method = strtoupper($method);

        if (!isset($this->routes[$method])) {
            $this->sendNotFound();
            return;
        }

        foreach ($this->routes[$method] as $route => $handler) {
            $pattern = $this->routeToRegex($route);

            if (preg_match($pattern, $uri, $matches)) {
                $params = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY);

                [$controllerName, $methodName] = $handler;

                $controllerFile = APP_ROOT . '/controllers/' . $controllerName . '.php';

                if (!file_exists($controllerFile)) {
                    $this->sendNotFound();
                    return;
                }

                require_once $controllerFile;

                $controller = new $controllerName();

                if (!method_exists($controller, $methodName)) {
                    $this->sendNotFound();
                    return;
                }
                call_user_func_array([$controller, $methodName], $params);
                return;
            }
        }

                $this->sendNotFound();
    }

    private function routeToRegex(string $route): string
    {
        // Handle path parameters that can contain slashes
        $pattern = preg_replace('/\{path\}/', '(?P<path>.+)', $route);
        // Handle regular parameters that cannot contain slashes
        $pattern = preg_replace('/\{(\w+)\}/', '(?P<$1>[^/]+)', $pattern);
        return '#^' . $pattern . '$#';
    }

    private function sendNotFound(): void
    {
        http_response_code(404);
        require APP_ROOT . '/views/pages/404.php';
    }
}
