<?php

declare(strict_types=1);

namespace PpPhp\Core;

class Router
{
    private array $routes = [];

    public function __construct(private Container $container) {}

    /**
     * Add a route.
     *
     * @param string $method   HTTP method (GET, POST, etc.)
     * @param string $uri      URI pattern, e.g., "/dashboard"
     * @param string $handler  "ControllerClass@method"
     * @param string|null $name Route name (unused for now)
     */
    public function addRoute(string $method, string $uri, string $handler, ?string $name = null): void
    {
        $this->routes[] = [
            'method'  => strtoupper($method),
            'uri'     => $uri,
            'handler' => $handler,
            'name'    => $name,
        ];
    }

    /**
     * Match the current request and execute the handler.
     */
    public function dispatch(string $requestMethod, string $requestUri): void
    {
        $requestUri = parse_url($requestUri, PHP_URL_PATH);
        $requestMethod = strtoupper($requestMethod);

        foreach ($this->routes as $route) {
            // Check method
            if ($route['method'] !== $requestMethod) {
                continue;
            }

            // Convert route pattern to regex. A trailing-star param {name*}
            // captures the rest of the path (including slashes) — used for
            // file-path routes like custom-files/preview/{path*}. A plain
            // {param} still matches a single path segment.
            $pattern = preg_replace('/\{([a-zA-Z_]+)\*\}/', '(.+)', $route['uri']);
            $pattern = preg_replace('/\{([a-zA-Z_]+)\}/', '([^/]+)', $pattern);
            $pattern = '#^' . $pattern . '$#';

            if (preg_match($pattern, $requestUri, $matches)) {
                array_shift($matches); // remove full match
                // Call handler with matched parameters
                $this->executeHandler($route['handler'], $matches);
                return;
            }
        }

        http_response_code(404);
        if (!headers_sent()) {
            header('Content-Type: text/html; charset=utf-8');
        }
        $__notFound = constant('BASE_PATH') . '/core/views/error-404.php';
        if (is_file($__notFound)) {
            require $__notFound;
        } else {
            echo '404 Not Found';
        }
    }

    /**
     * Split handler string and call the method.
     */
    private function executeHandler(string $handler, array $params = []): void
    {
        [$class, $method] = explode('@', $handler);

        // Resolve the controller from the container
        $controller = $this->container->get($class);

        // Call the method with any route parameters
        $response = $controller->$method(...$params);

        // If response is a string, output it
        if (is_string($response)) {
            echo $response;
        }
    }
}