<?php

declare(strict_types=1);

namespace App\Support;

final class Router
{
    private array $routes = [];

    public function __construct(private readonly Request $request)
    {
    }

    public function get(string $path, callable $handler): void
    {
        $this->map('GET', $path, $handler);
    }

    public function post(string $path, callable $handler): void
    {
        $this->map('POST', $path, $handler);
    }

    public function patch(string $path, callable $handler): void
    {
        $this->map('PATCH', $path, $handler);
    }

    public function delete(string $path, callable $handler): void
    {
        $this->map('DELETE', $path, $handler);
    }

    public function dispatch(): void
    {
        $method = $this->request->method();
        $path = $this->request->path();

        foreach ($this->routes[$method] ?? [] as $route) {
            $pattern = preg_replace('#\{([a-zA-Z_][a-zA-Z0-9_]*)\}#', '(?P<$1>[^/]+)', $route['path']);
            $pattern = '#^' . $pattern . '$#';

            if (!preg_match($pattern, $path, $matches)) {
                continue;
            }

            $params = array_filter($matches, static fn (string|int $key): bool => is_string($key), ARRAY_FILTER_USE_KEY);
            $route['handler']($this->request, $params);
            return;
        }

        Response::json(['message' => 'Route not found', 'path' => $path], 404);
    }

    private function map(string $method, string $path, callable $handler): void
    {
        $this->routes[$method][] = [
            'path' => rtrim($path, '/') ?: '/',
            'handler' => $handler,
        ];
    }
}
