<?php

/**
 * Матчер маршрутов Flowaxy CMS
 * Поиск соответствующего маршрута для URI
 *
 * @package Flowaxy\Core\Routing
 * @version 1.0.0 Alpha prerelease
 */

declare(strict_types=1);

namespace Flowaxy\Core\Routing;

class RouteMatcher
{
    /**
     * Поиск соответствующего маршрута
     *
     * @param string $uri URI для поиска
     * @param array<Route> $routes Массив маршрутов для поиска
     * @return array{route: Route, params: array}|null
     */
    public function match(string $uri, array $routes): ?array
    {
        $normalizedUri = trim($uri, '/');

        foreach ($routes as $route) {
            $params = [];
            $routePath = $route->getPath();

            // Точное совпадение (самое быстрое)
            if ($routePath === $normalizedUri) {
                return ['route' => $route, 'params' => $params];
            }

            // Regex pattern для маршрутов с параметрами
            if (!empty($route->getParams())) {
                $pattern = $route->getPattern();
                if (empty($pattern) || $pattern === '/^\/$/' || strlen($pattern) < 4) {
                    continue;
                }

                // Проверка валидности паттерна
                if (!str_starts_with($pattern, '/') || !str_ends_with($pattern, '/')) {
                    continue;
                }

                if (!preg_match('/^\/\^.*\$\/$/', $pattern)) {
                    continue;
                }

                // Попытка совпадения
                $uriPath = empty($normalizedUri) ? '/' : '/' . $normalizedUri;
                if (preg_match($pattern, $uriPath, $matches)) {
                    array_shift($matches); // Удаляем первый элемент (полное совпадение)
                    $routeParams = $route->getParams();
                    foreach ($routeParams as $index => $paramName) {
                        if (isset($matches[$index])) {
                            $params[$paramName] = $matches[$index];
                        }
                    }
                    return ['route' => $route, 'params' => $params];
                }
            }
        }

        return null;
    }

    /**
     * Проверка, соответствует ли URI маршруту
     *
     * @param string $uri URI для проверки
     * @param Route $route Маршрут для проверки
     * @return array{matched: bool, params: array}
     */
    public function matches(string $uri, Route $route): array
    {
        $normalizedUri = trim($uri, '/');
        $routePath = $route->getPath();
        $params = [];

        // Точное совпадение
        if ($routePath === $normalizedUri) {
            return ['matched' => true, 'params' => $params];
        }

        // Проверка паттерна
        if (!empty($route->getParams())) {
            $pattern = $route->getPattern();
            if (!empty($pattern) && preg_match('/^\/\^.*\$\/$/', $pattern)) {
                $uriPath = empty($normalizedUri) ? '/' : '/' . $normalizedUri;
                if (preg_match($pattern, $uriPath, $matches)) {
                    array_shift($matches);
                    $routeParams = $route->getParams();
                    foreach ($routeParams as $index => $paramName) {
                        if (isset($matches[$index])) {
                            $params[$paramName] = $matches[$index];
                        }
                    }
                    return ['matched' => true, 'params' => $params];
                }
            }
        }

        return ['matched' => false, 'params' => []];
    }
}
