<?php

declare(strict_types=1);

namespace Fennec\Console;

use Fennec\Container\Container;
use Fennec\Reflection\DirectoryClassFinder;

/**
 * Découvre les commandes disponibles par scan Reflection, et les résout via le Container
 * (autowiring possible dans une commande, comme pour un controller).
 */
final class CommandRegistry
{
    /** @var array<string, CommandInterface> */
    private array $commands = [];

    public function __construct(
        private readonly Container $container,
        private readonly DirectoryClassFinder $classFinder,
    ) {
    }

    /**
     * Scanne un répertoire à la recherche de classes implémentant CommandInterface.
     *
     * @throws \ReflectionException Si une classe trouvée n'est pas réflectible.
     */
    public function discover(string $namespacePrefix, string $baseDirectory): void
    {
        foreach ($this->classFinder->findClasses($namespacePrefix, $baseDirectory) as $className) {
            $reflection = new \ReflectionClass($className);

            if ($reflection->isAbstract() || !$reflection->implementsInterface(CommandInterface::class)) {
                continue;
            }

            /** @var CommandInterface $command */
            $command = $this->container->get($className);
            $this->commands[$command->getName()] = $command;
        }
    }

    public function has(string $name): bool
    {
        return isset($this->commands[$name]);
    }

    /**
     * @throws CommandNotFoundException
     */
    public function get(string $name): CommandInterface
    {
        return $this->commands[$name] ?? throw new CommandNotFoundException($name);
    }

    /**
     * @return list<CommandInterface>
     */
    public function all(): array
    {
        return \array_values($this->commands);
    }
}
