<?php

/**
 * Базовий клас для CLI команд
 *
 * @package Flowaxy\Interface\CLI
 * @version 1.0.0 Alpha prerelease
 */

declare(strict_types=1);

namespace Flowaxy\Interface\CLI;

abstract class Command implements CommandInterface
{
    /**
     * Виконання команди
     *
     * @param array<string> $args Аргументи командного рядка
     * @return int Код виходу (0 = успіх)
     */
    public function execute(array $args): int
    {
        $this->beforeExecute();
        $result = $this->handle($args);
        $this->afterExecute();
        return $result;
    }

    /**
     * Обробка команди (перевизначається в дочірніх класах)
     *
     * @param array<string> $args Аргументи командного рядка
     * @return int Код виходу (0 = успіх)
     */
    abstract protected function handle(array $args): int;

    /**
     * Викликається перед виконанням команди
     *
     * @return void
     */
    protected function beforeExecute(): void
    {
        // Перевизначається в дочірніх класах
    }

    /**
     * Викликається після виконання команди
     *
     * @return void
     */
    protected function afterExecute(): void
    {
        // Перевизначається в дочірніх класах
    }

    /**
     * Вивести повідомлення
     *
     * @param string $message
     * @return void
     */
    protected function output(string $message): void
    {
        echo $message . "\n";
    }

    /**
     * Вивести помилку
     *
     * @param string $message
     * @return void
     */
    protected function error(string $message): void
    {
        fwrite(STDERR, "Error: {$message}\n");
    }

    /**
     * Отримати назву команди
     *
     * @return string
     */
    public function getName(): string
    {
        $className = static::class;
        $parts = explode('\\', $className);
        $name = end($parts);
        return strtolower(str_replace('Command', '', $name));
    }

    /**
     * Отримати опис команди
     *
     * @return string
     */
    public function getDescription(): string
    {
        return 'No description available';
    }

    /**
     * Отримати довідку по команді
     *
     * @return string
     */
    public function getHelp(): string
    {
        return "Usage: {$this->getName()} [options]\n\n{$this->getDescription()}";
    }
}
