public function addCommand(string $name, $handler = null, array $options = []): RouterInterface
    {
        /**
         * @var Command $name name is an command class
         */
        if (!$handler && \class_exists($name)) {
            $handler = $name;
            $name    = $name::getName();
        }

        if (!$name || !$handler) {
            Helper::throwInvalidArgument("Command 'name' and 'handler' cannot be empty! name: $name");
        }

        $this->validateName($name);

        if (isset($this->commands[$name])) {
            Helper::throwInvalidArgument("Command '$name' have been registered!");
        }

        $options['aliases'] = isset($options['aliases']) ? (array)$options['aliases'] : [];

        if (\is_string($handler)) {
            if (!\class_exists($handler)) {
                Helper::throwInvalidArgument("The console command class [$handler] not exists!");
            }

            if (!\is_subclass_of($handler, Command::class)) {
                Helper::throwInvalidArgument('The console command class must is subclass of the: ' . Command::class);
            }

            // not enable
            /** @var Command $handler */
            if (!$handler::isEnabled()) {
                return $this;
            }

            // allow define aliases in Command class by Command::aliases()
            if ($aliases = $handler::aliases()) {
                $options['aliases'] = \array_merge($options['aliases'], $aliases);
            }
        } elseif (!\is_object($handler) || !\method_exists($handler, '__invoke')) {
            Helper::throwInvalidArgument(
                'The console command handler must is an subclass of %s OR a Closure OR a object have method __invoke()',
                Command::class
            );
        }

        // is an class name string
        $this->commands[$name] = [
            'type'    => self::TYPE_SINGLE,
            'handler' => $handler,
            'options' => $options,
        ];

        // has alias option
        if (isset($options['aliases'])) {
            $this->setAlias($name, $options['aliases'] ?? []);
        }

        return $this;
    }