<?php

/**
 * Фасад для роботи з маршрутизацією
 *
 * @package Flowaxy\Support\Facades
 * @version 1.0.0 Alpha prerelease
 */

declare(strict_types=1);

namespace Flowaxy\Support\Facades;

use Flowaxy\Core\Routing\RouterManager;
use Flowaxy\Core\Routing\Router as RouterInstance;
use Flowaxy\Infrastructure\Security\RequestFilter;
use Flowaxy\Interface\Http\Response as ResponseInstance;

final class Router extends Facade
{
    protected static function getFacadeAccessor(): string
    {
        return RouterManager::class;
    }

    /**
     * Отримати менеджер маршрутів
     *
     * @return RouterManager
     */
    public static function manager(): RouterManager
    {
        return static::getFacadeRoot();
    }

    /**
     * Отримати об'єкт Router
     *
     * @return RouterInstance
     */
    private static function router(): RouterInstance
    {
        return static::manager()->getRouter();
    }

    /**
     * Додати GET маршрут
     *
     * @param string $path
     * @param callable|string $handler
     * @return void
     */
    public static function get(string $path, callable|string $handler): void
    {
        static::router()->get($path, $handler);
    }

    /**
     * Додати POST маршрут
     *
     * @param string $path
     * @param callable|string $handler
     * @return void
     */
    public static function post(string $path, callable|string $handler): void
    {
        static::router()->post($path, $handler);
    }

    /**
     * Додати PUT маршрут
     *
     * @param string $path
     * @param callable|string $handler
     * @return void
     */
    public static function put(string $path, callable|string $handler): void
    {
        static::router()->put($path, $handler);
    }

    /**
     * Додати DELETE маршрут
     *
     * @param string $path
     * @param callable|string $handler
     * @return void
     */
    public static function delete(string $path, callable|string $handler): void
    {
        static::router()->delete($path, $handler);
    }

    /**
     * Додати PATCH маршрут
     *
     * @param string $path
     * @param callable|string $handler
     * @return void
     */
    public static function patch(string $path, callable|string $handler): void
    {
        static::router()->add('PATCH', $path, $handler);
    }

    /**
     * Додати маршрут для будь-якого методу
     *
     * @param string $path
     * @param callable|string $handler
     * @return void
     */
    public static function any(string $path, callable|string $handler): void
    {
        static::router()->any($path, $handler);
    }

    /**
     * Групувати маршрути
     *
     * @param array<string, mixed> $attributes
     * @param callable $callback
     * @return void
     */
    public static function group(array $attributes, callable $callback): void
    {
        $prefix = $attributes['prefix'] ?? '';
        $options = $attributes;
        unset($options['prefix']);
        static::router()->group($prefix, $callback, $options);
    }

    /**
     * Отримати URL маршруту
     *
     * @param string $name
     * @param array<string, mixed> $params
     * @return string
     */
    public static function route(string $name, array $params = []): string
    {
        $url = static::router()->url($name, $params);
        return $url ?? '';
    }

    /**
     * Отримати URL
     *
     * @param string $path
     * @return string
     */
    public static function url(string $path = ''): string
    {
        $basePath = static::manager()->getBasePath();
        return rtrim($basePath, '/') . '/' . ltrim($path, '/');
    }

    /**
     * Отримати поточний маршрут
     *
     * @return string
     */
    public static function current(): string
    {
        return RequestFilter::server('REQUEST_URI', '/');
    }

    /**
     * Виконати редірект
     *
     * @param string $url
     * @param int $statusCode
     * @return void
     */
    public static function redirect(string $url, int $statusCode = 302): void
    {
        ResponseInstance::redirectStatic($url, $statusCode);
    }

    /**
     * Повернутися назад
     *
     * @param int $statusCode
     * @return void
     */
    public static function back(int $statusCode = 302): void
    {
        $referer = $_SERVER['HTTP_REFERER'] ?? '/';
        self::redirect($referer, $statusCode);
    }
}
