<?php

declare(strict_types=1);

namespace Fennec\Routing;

use Fennec\Reflection\DirectoryClassFinder;

/**
 * Construit la table de routage par scan Reflection d'un répertoire de controllers.
 *
 * Même principe que Fennec\Autoload\Autoloader : un préfixe de namespace et un répertoire
 * de base, sans aucune connaissance en dur du projet qui l'utilise.
 */
final class RouteScanner
{
    public function __construct(private readonly DirectoryClassFinder $classFinder)
    {
    }

    /**
     * @return list<RouteDefinition>
     *
     * @throws \ReflectionException Si une classe trouvée n'est pas réflectible.
     */
    public function scanDirectory(string $namespacePrefix, string $baseDirectory): array
    {
        $definitions = [];

        foreach ($this->classFinder->findClasses($namespacePrefix, $baseDirectory) as $className) {
            $definitions = [...$definitions, ...$this->scanClass($className)];
        }

        return $definitions;
    }

    /**
     * @param class-string $className
     *
     * @return list<RouteDefinition>
     */
    private function scanClass(string $className): array
    {
        $definitions = [];
        $reflectionClass = new \ReflectionClass($className);

        foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
            foreach ($method->getAttributes(Route::class) as $attribute) {
                /** @var Route $route */
                $route = $attribute->newInstance();

                $definitions[] = new RouteDefinition(
                    $route->path,
                    $route->methods,
                    $className,
                    $method->getName(),
                );
            }
        }

        return $definitions;
    }
}
