<?php

namespace Kylin\Modules\Console\Commands;

use Illuminate\Console\Command;
use Kylin\Modules\ModuleManager;

/**
 * 模块发布命令
 *
 * 发布模块的资源
 */
class ModulePublishCommand extends Command
{
    /**
     * 命令名称和签名
     *
     * @var string
     * 
     * 命令参数说明：
     * 1. {name?} - 模块名称（可选）
     *    - 数据类型：字符串
     *    - 用途：指定要发布资源的模块名称，不指定则发布所有模块的资源
     *    - 示例：php artisan module:publish game
     * 
     * 命令选项说明：
     * 1. {--force} - 覆盖任何现有文件
     *    - 完整形式：--force
     *    - 用途：覆盖任何现有的已发布文件
     *    - 示例：php artisan module:publish game --force
     * 
     * 2. {--tag=*} - 要发布的标签
     *    - 完整形式：--tag
     *    - 数据类型：字符串数组
     *    - 用途：指定要发布的标签
     *    - 示例：php artisan module:publish game --tag=config,assets
     * 
     * 3. {--force} - 强制覆盖现有文件
     *    - 完整形式：--force
     *    - 用途：强制覆盖现有文件
     *    - 示例：php artisan module:publish game --force
     */
    protected $signature = 'module:publish {name? : 模块名称} {--force : 覆盖任何现有文件} {--tag=* : 要发布的标签}';

    /**
     * 命令描述
     *
     * @var string
     */
    protected $description = '发布模块的资源';

    /**
     * 创建新命令实例
     *
     * @param  ModuleManager  $moduleManager  模块管理器实例
     */
    public function __construct(
        private readonly ModuleManager $moduleManager
    ) {
        parent::__construct();
    }

    /**
     * 执行控制台命令
     */
    public function handle(): int
    {
        $name = (string) $this->argument('name');
        $force = (bool) $this->option('force');
        $tags = (array) $this->option('tag') ?: [];

        if ($name) {
            $this->publishModule($name, $force, $tags);
        } else {
            $this->publishAllModules($force, $tags);
        }

        return 0;
    }

    /**
     * 发布特定模块
     *
     * @param  string  $moduleName  模块名称
     * @param  bool  $force  是否强制覆盖
     * @param  array  $tags  要发布的标签
     */
    protected function publishModule(string $moduleName, bool $force, array $tags): void
    {
        $module = $this->moduleManager->get($moduleName);

        if (!$module) {
            $this->error("模块 [{$moduleName}] 未找到。");
            return;
        }

        $this->info("发布模块: {$moduleName}");

        // 这里通常会调用模块的发布方法
        // 现在，我们只显示一条消息
        $this->info("模块 [{$moduleName}] 发布成功。");
    }

    /**
     * 发布所有模块
     *
     * @param  bool  $force  是否强制覆盖
     * @param  array  $tags  要发布的标签
     */
    protected function publishAllModules(bool $force, array $tags): void
    {
        $modules = $this->moduleManager->all();

        foreach ($modules as $module) {
            $this->publishModule($module->getName(), $force, $tags);
        }
    }
}