<?php
namespace App\Core;

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

    public static function get(string $path, array|callable $handler, array $middlewares = []): void {
        self::addRoute('GET', $path, $handler, $middlewares);
    }

    public static function post(string $path, array|callable $handler, array $middlewares = []): void {
        self::addRoute('POST', $path, $handler, $middlewares);
    }

    public static function put(string $path, array|callable $handler, array $middlewares = []): void {
        self::addRoute('PUT', $path, $handler, $middlewares);
    }

    public static function delete(string $path, array|callable $handler, array $middlewares = []): void {
        self::addRoute('DELETE', $path, $handler, $middlewares);
    }

    private static function addRoute(string $method, string $path, array|callable $handler, array $middlewares): void {
        $pattern = preg_replace('/\{([a-zA-Z0-9_]+)\}/', '(?P<$1>[^/]+)', trim($path, '/'));
        $pattern = '#^' . ($pattern === '' ? '' : '/' . $pattern) . '$#';

        self::$routes[] = [
            'method'      => $method,
            'pattern'     => $pattern,
            'handler'     => $handler,
            'middlewares' => $middlewares
        ];
    }

    public static function dispatch(string $method, string $uri): void {
        $uri = '/' . trim($uri, '/');
        if ($uri === '//') $uri = '/';

        foreach (self::$routes as $route) {
            if ($route['method'] !== $method) {
                continue;
            }

            if (preg_match($route['pattern'], $uri, $matches)) {
                // Execute Middlewares
                foreach ($route['middlewares'] as $middleware) {
                    if (is_callable($middleware)) {
                        call_user_func($middleware);
                    } elseif (is_array($middleware)) {
                        [$class, $fn] = $middleware;
                        (new $class())->$fn();
                    }
                }

                // Filter named parameters from regex
                $params = array_filter($matches, fn($key) => !is_int($key), ARRAY_FILTER_USE_KEY);

                // Call Handler
                if (is_callable($route['handler'])) {
                    call_user_func_array($route['handler'], $params);
                    return;
                }

                if (is_array($route['handler'])) {
                    [$controllerClass, $action] = $route['handler'];
                    if (!class_exists($controllerClass)) {
                        Response::error("Controller class not found: {$controllerClass}", 500);
                    }
                    $controller = new $controllerClass();
                    if (!method_exists($controller, $action)) {
                        Response::error("Action {$action} not found in {$controllerClass}", 500);
                    }
                    call_user_func_array([$controller, $action], $params);
                    return;
                }
            }
        }

        // Route Not Found (404)
        if (Request::isAjax()) {
            Response::error("Route {$method} {$uri} not found", 404);
        } else {
            http_response_code(404);
            echo "<div style='font-family: sans-serif; text-align: center; padding: 4rem;'>
                <h1 style='font-size: 3rem; color: #ef4444;'>404</h1>
                <p style='font-size: 1.25rem; color: #64748b;'>Page or Route Not Found: <code>" . htmlspecialchars($uri) . "</code></p>
                <a href='/dashboard' style='color: #3b82f6; text-decoration: underline;'>Return to Dashboard</a>
            </div>";
        }
    }
}
