<?php
namespace Api\Core;

class Router {
    private $routes = [];
    private $container;

    public function __construct(Container $container) {
        $this->container = $container;
    }

    public function register($method, $path, $handler) {
        $this->routes[$method][$path] = $handler;
    }

    public function get($path, $handler) { $this->register('GET', $path, $handler); }
    public function post($path, $handler) { $this->register('POST', $path, $handler); }

    private function normalizePath(string $path): string {
        $path = '/' . trim($path, '/');
        $path = preg_replace('#^/api(?=/|$)#i', '', $path);
        $path = '/' . trim($path, '/');

        return $path === '' ? '/' : $path;
    }

    public function dispatch(Request $req, Response $res) {
        $method = $req->method();
        $path = $this->normalizePath($req->path());

        // extract version prefix /v1/...
        if (preg_match('#^/v([0-9]+)(/.*)?$#', $path, $m)) {
            $version = $m[1];
            $pathWithoutVersion = $m[2] ?? '/';
        } else {
            $version = '1';
            $pathWithoutVersion = $path;
        }

        // try exact route with versioned namespace
        $routeKey = $pathWithoutVersion;
        if (!isset($this->routes[$method][$routeKey])) {
            return $res->json(['error' => 'Not found'], 404);
        }

        $handler = $this->routes[$method][$routeKey];
        // handler can be 'UsersController@index' or 'Controllers\\UsersController@index'
        if (strpos($handler, '@') !== false) {
            list($class, $function) = explode('@', $handler);
            // if class not namespaced, prefix with Api\\Controllers\\V{n}\\
            if (strpos($class, '\\') === false) {
                $class = "Api\\Controllers\\V{$version}\\" . $class;
            }
        } else {
            return $res->json(['error' => 'Invalid handler'], 500);
        }

        if (!class_exists($class)) {
            return $res->json(['error' => 'Controller not found'], 500);
        }

        $controller = $this->container->make($class);
        return $controller->$function($req, $res);
    }
}
