<?php

namespace App\Core;

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

    public function add(string $method, string $path, $handler, array $middleware = []): void
    {
        $path = $this->formatPath($path);
        $this->routes[] = [
            'method' => $method,
            'path' => $path,
            'handler' => $handler,
            'middleware' => $middleware
        ];
    }

    public function get(string $path, $handler, array $middleware = []): void { $this->add('GET', $path, $handler, $middleware); }
    public function post(string $path, $handler, array $middleware = []): void { $this->add('POST', $path, $handler, $middleware); }
    public function put(string $path, $handler, array $middleware = []): void { $this->add('PUT', $path, $handler, $middleware); }
    public function delete(string $path, $handler, array $middleware = []): void { $this->add('DELETE', $path, $handler, $middleware); }

    public function handle(Request $request): Response
    {
        $method = $request->method();
        $path = $this->formatPath($request->path());

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

            if ($route['method'] === $method && preg_match($pattern, $path, $matches)) {
                $params = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY);
                
                // Execute middleware
                foreach ($route['middleware'] as $mwClass) {
                    $mw = new $mwClass();
                    $response = $mw->handle($request);
                    if ($response instanceof Response) return $response;
                }

                $handler = $route['handler'];
                if (is_array($handler)) {
                    $controller = new $handler[0]();
                    return call_user_func_array([$controller, $handler[1]], [$request, ...array_values($params)]);
                }
                return $handler($request, ...array_values($params));
            }
        }

        return new Response('404 Not Found', 404);
    }

    private function formatPath(string $path): string
    {
        return $path === '/' ? '/' : rtrim($path, '/');
    }
}
