<?php

declare(strict_types=1);

class Router
{
    private $routes = [];

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

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

    public function dispatch(string $uri, string $method): void
    {
        $method = strtoupper((string) $method);
        $path = $this->resolvePath($uri);
        $handler = isset($this->routes[$method][$path]) ? $this->routes[$method][$path] : null;

        if (!$handler) {
            http_response_code(404);
            echo 'Página não encontrada.';
            return;
        }

        $controller = $handler[0];
        $action = $handler[1];

        if (!class_exists($controller)) {
            throw new RuntimeException('Controller não encontrado: ' . $controller);
        }

        $instance = new $controller();

        if (!method_exists($instance, $action)) {
            throw new RuntimeException('Método não encontrado: ' . $controller . '::' . $action);
        }

        $instance->$action();
    }

    private function resolvePath(string $uri): string
    {
        if (!empty($_GET['route'])) {
            return $this->normalizeRoute((string) $_GET['route']);
        }

        $path = parse_url($uri, PHP_URL_PATH);
        if (!is_string($path) || $path === '') {
            $path = '/';
        }

        $basePath = function_exists('app_base_path') ? (string) app_base_path() : '';
        if ($basePath !== '' && strpos($path, $basePath) === 0) {
            $path = substr($path, strlen($basePath));
        }

        if (strpos($path, '/index.php') === 0) {
            $path = substr($path, strlen('/index.php'));
        }

        return $this->normalizeRoute($path);
    }

    private function normalizeRoute(string $path): string
    {
        $path = trim($path);

        if ($path === '' || $path === '/') {
            return '/';
        }

        $path = '/' . ltrim($path, '/');
        $path = preg_replace('#/+#', '/', $path);

        if ($path !== '/' && substr($path, -1) === '/') {
            $path = rtrim($path, '/');
        }

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