<?php

namespace Kylin\Modules\Console\Commands;

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

/**
 * 模块版本管理命令
 *
 * 管理模块的版本号，支持版本升级、降级等操作
 */
class ModuleVersionCommand extends Command
{
    /**
     * 命令名称和签名
     *
     * @var string
     * 
     * 命令参数说明：
     * 1. {module} - 模块名称（必填）
     *    - 数据类型：字符串
     *    - 用途：指定要管理版本的模块名称
     *    - 示例：php artisan module:version game
     * 
     * 命令选项说明：
     * 1. {--set=} - 设置版本号
     *    - 完整形式：--set
     *    - 数据类型：字符串
     *    - 用途：直接设置模块的版本号
     *    - 示例：php artisan module:version game --set=1.2.3
     * 
     * 2. {--major} - 主版本号+1
     *    - 完整形式：--major
     *    - 用途：将模块的主版本号加1，重置次版本号和补丁版本号为0
     *    - 示例：php artisan module:version game --major
     * 
     * 3. {--minor} - 次版本号+1
     *    - 完整形式：--minor
     *    - 用途：将模块的次版本号加1，重置补丁版本号为0
     *    - 示例：php artisan module:version game --minor
     * 
     * 4. {--patch} - 补丁版本号+1
     *    - 完整形式：--patch
     *    - 用途：将模块的补丁版本号加1
     *    - 示例：php artisan module:version game --patch
     * 
     * 5. {--pre=} - 预发布版本号
     *    - 完整形式：--pre
     *    - 数据类型：字符串
     *    - 用途：设置模块的预发布版本号
     *    - 示例：php artisan module:version game --pre=beta
     * 
     * 6. {--build=} - 构建版本号
     *    - 完整形式：--build
     *    - 数据类型：字符串
     *    - 用途：设置模块的构建版本号
     *    - 示例：php artisan module:version game --build=123
     * 
     * 7. {--reset} - 重置版本号为 1.0.0
     *    - 完整形式：--reset
     *    - 用途：将模块的版本号重置为 1.0.0
     *    - 示例：php artisan module:version game --reset
     */
    protected $signature = 'module:version {module : 模块名称} {--set= : 设置版本号} {--major : 主版本号+1} {--minor : 次版本号+1} {--patch : 补丁版本号+1} {--pre= : 预发布版本号} {--build= : 构建版本号} {--reset : 重置版本号为 1.0.0}';

    /**
     * 命令描述
     *
     * @var string
     */
    protected $description = '管理模块的版本号';

    /**
     * 文件系统实例
     *
     * @var Filesystem
     */
    private readonly Filesystem $files;

    /**
     * 创建新命令实例
     *
     * @param  ModuleManager  $moduleManager  模块管理器实例
     * @param  Filesystem  $files  文件系统实例
     */
    public function __construct(
        private readonly ModuleManager $moduleManager,
        Filesystem $files
    ) {
        parent::__construct();
        $this->files = $files;
    }

    /**
     * 执行控制台命令
     */
    public function handle(): int
    {
        $moduleName = (string) $this->argument('module');
        $setVersion = $this->option('set');
        $major = $this->option('major');
        $minor = $this->option('minor');
        $patch = $this->option('patch');
        $pre = $this->option('pre');
        $build = $this->option('build');
        $reset = $this->option('reset');

        // 检查模块是否存在
        $module = $this->moduleManager->get($moduleName);
        if (!$module) {
            $this->error("模块 [{$moduleName}] 未找到。");
            return 1;
        }

        $modulePath = $module->getPath();
        $composerPath = "{$modulePath}/composer.json";

        // 检查 composer.json 文件是否存在
        if (!file_exists($composerPath)) {
            $this->error("模块 [{$moduleName}] 缺少 composer.json 文件。");
            return 1;
        }

        // 读取当前版本号
        $composer = json_decode($this->files->get($composerPath), true);
        $currentVersion = $composer['version'] ?? '1.0.0';

        // 处理版本号操作
        $newVersion = $currentVersion;

        if ($reset) {
            $newVersion = '1.0.0';
        } elseif ($setVersion) {
            $newVersion = (string) $setVersion;
        } else {
            $versionParts = $this->parseVersion($currentVersion);
            
            if ($major) {
                $versionParts['major']++;
                $versionParts['minor'] = 0;
                $versionParts['patch'] = 0;
            }
            
            if ($minor) {
                $versionParts['minor']++;
                $versionParts['patch'] = 0;
            }
            
            if ($patch) {
                $versionParts['patch']++;
            }
            
            if ($pre) {
                $versionParts['pre'] = (string) $pre;
            }
            
            if ($build) {
                $versionParts['build'] = (string) $build;
            }
            
            $newVersion = $this->buildVersion($versionParts);
        }

        // 更新版本号
        $composer['version'] = $newVersion;
        $this->files->put($composerPath, json_encode($composer, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));

        $this->info("模块 [{$moduleName}] 的版本号已从 {$currentVersion} 更新为 {$newVersion}");

        return 0;
    }

    /**
     * 解析版本号
     *
     * @param  string  $version  版本号字符串
     * @return array  版本号部分
     */
    protected function parseVersion(string $version): array
    {
        $parts = [
            'major' => 1,
            'minor' => 0,
            'patch' => 0,
            'pre' => null,
            'build' => null,
        ];

        // 解析版本号
        if (preg_match('/^(\d+)\.(\d+)\.(\d+)(?:-(.+))?(?:\+(.*))?$/', $version, $matches)) {
            $parts['major'] = (int) $matches[1];
            $parts['minor'] = (int) $matches[2];
            $parts['patch'] = (int) $matches[3];
            $parts['pre'] = $matches[4] ?? null;
            $parts['build'] = $matches[5] ?? null;
        }

        return $parts;
    }

    /**
     * 构建版本号
     *
     * @param  array  $parts  版本号部分
     * @return string  版本号字符串
     */
    protected function buildVersion(array $parts): string
    {
        $version = "{$parts['major']}.{$parts['minor']}.{$parts['patch']}";
        
        if ($parts['pre']) {
            $version .= "-{$parts['pre']}";
        }
        
        if ($parts['build']) {
            $version .= "+{$parts['build']}";
        }
        
        return $version;
    }
}
