<?php

namespace App\Core;

class Router
{
    private array $routes = [];

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

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

    private function add(string $method, string $path, string $handler): void
    {
        $pattern = preg_replace('#\{[a-zA-Z_]+\}#', '([^/]+)', trim($path, '/'));

        $this->routes[$method][] = [
            'pattern' => '#^' . $pattern . '$#',
            'handler' => $handler,
        ];
    }

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

        // Buang prefix folder jika aplikasi diakses dari subfolder (mis. /fakultas-cms/public)
        $basePath = trim((string) parse_url(APP_URL, PHP_URL_PATH), '/');
        if ($basePath !== '' && str_starts_with($uri, $basePath)) {
            $uri = trim(substr($uri, strlen($basePath)), '/');
        }

        foreach ($this->routes[$method] ?? [] as $route) {
            if (preg_match($route['pattern'], $uri, $matches)) {
                array_shift($matches);
                [$controllerName, $action] = explode('@', $route['handler']);
                $controllerClass = "App\\Controllers\\{$controllerName}";

                if (!class_exists($controllerClass)) {
                    $this->abort(500, "Controller {$controllerClass} belum dibuat.");
                }

                $controller = new $controllerClass();

                if (!method_exists($controller, $action)) {
                    $this->abort(500, "Method {$action} tidak ditemukan di {$controllerClass}.");
                }

                call_user_func_array([$controller, $action], $matches);
                return;
            }
        }

        $this->abort(404, 'Halaman tidak ditemukan.');
    }

    private function abort(int $code, string $message): void
    {
        http_response_code($code);
        $viewPath = BASE_PATH . "/app/Views/errors/{$code}.php";

        if (file_exists($viewPath)) {
            require $viewPath;
        } else {
            echo "<h1>{$code}</h1><p>{$message}</p>";
        }
        exit;
    }
}
