<?php
/**
 * Classe Router
 * Localização: /app/core/Router.php
 */

class Router
{
    private array $routes = [];

    public function get(string $path, $handler): void
    {
        $this->routes['GET'][$this->normalize($path)] = $handler;
    }

    public function post(string $path, $handler): void
    {
        $this->routes['POST'][$this->normalize($path)] = $handler;
    }

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

    public function dispatch(string $uri, string $method): void
    {
        // Remove query string
        $uri = parse_url($uri, PHP_URL_PATH) ?? '/';

        // Remove subpasta se estiver em /office/public
        $scriptDir = rtrim(str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'])), '/');
        if ($scriptDir && $scriptDir !== '/' && str_starts_with($uri, $scriptDir)) {
            $uri = substr($uri, strlen($scriptDir));
        }

        $uri = $this->normalize($uri);
        $method = strtoupper($method);
        $routes = $this->routes[$method] ?? [];

        // Match exato
        if (isset($routes[$uri])) {
            $this->call($routes[$uri]);
            return;
        }

        // Match com parâmetros {param}
        foreach ($routes as $route => $handler) {
            $pattern = preg_replace('#\{([a-zA-Z_]+)\}#', '([^/]+)', $route);
            $pattern = "#^{$pattern}$#";

            if (preg_match($pattern, $uri, $matches)) {
                array_shift($matches);
                $this->call($handler, $matches);
                return;
            }
        }

        // 404
        http_response_code(404);
        $view404 = VIEWS_PATH . '/public/404.php';
        if (file_exists($view404)) {
            require $view404;
        } else {
            echo '<h1>404 - Página não encontrada</h1>';
        }
    }

    private function call($handler, array $params = []): void
    {
        if (is_callable($handler)) {
            call_user_func_array($handler, $params);
            return;
        }

        [$controllerName, $methodName] = explode('@', $handler);
        $file = APP_PATH . "/controllers/{$controllerName}.php";

        if (!file_exists($file)) {
            throw new Exception("Controller {$controllerName} não encontrado");
        }

        require_once $file;
        $controller = new $controllerName();
        call_user_func_array([$controller, $methodName], $params);
    }
}
