<?php

namespace Kylin\Modules\Console\Commands;

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

/**
 * 模块生成测试命令
 *
 * 为模块生成新的测试类
 */
class ModuleMakeTestCommand extends Command
{
    /**
     * 命令名称和签名
     *
     * @var string
     * 
     * 命令参数说明：
     * 1. {module} - 模块名称（必填）
     *    - 数据类型：字符串
     *    - 用途：指定测试类所属的模块名称
     *    - 示例：php artisan module:make-test game UserTest
     * 
     * 2. {name} - 测试类名称（必填）
     *    - 数据类型：字符串
     *    - 用途：指定要创建的测试类名称
     *    - 示例：php artisan module:make-test game UserTest
     * 
     * 命令选项说明：
     * 1. {--u|unit} - 生成单元测试
     *    - 简写：-u
     *    - 完整形式：--unit
     *    - 用途：生成一个单元测试类
     *    - 示例：php artisan module:make-test game UserTest --unit
     * 
     * 2. {--f|feature} - 生成功能测试
     *    - 简写：-f
     *    - 完整形式：--feature
     *    - 用途：生成一个功能测试类
     *    - 示例：php artisan module:make-test game UserTest --feature
     */
    protected $signature = 'module:make-test {module : 模块名称} {name : 测试类名称} {--u|unit : 生成单元测试} {--f|feature : 生成功能测试}';


    /**
     * 命令描述
     *
     * @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');
        $name = (string) $this->argument('name');
        $unit = $this->option('unit');
        $feature = $this->option('feature');

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

        $modulePath = $module->getPath();
        $testsPath = "{$modulePath}/tests";

        // 确定测试类型
        if ($unit) {
            $testType = 'Unit';
        } elseif ($feature) {
            $testType = 'Feature';
        } else {
            $testType = 'Feature'; // 默认生成功能测试
        }

        $testPath = "{$testsPath}/{$testType}";

        // 确保目录存在
        if (!($this->files->exists($testPath))) {
            $this->files->makeDirectory($testPath, 0755, true);
            $this->info("创建测试目录: {$testPath}");
        }

        // 生成测试类
        $testClass = $this->buildTestClass($moduleName, $name, $testType);
        $testFile = "{$testPath}/{$name}.php";

        if ($this->files->exists($testFile)) {
            $this->error("测试 [{$name}] 已存在");
            return 1;
        }

        $this->files->put($testFile, $testClass);
        $this->info("创建测试: {$testFile}");

        return 0;
    }

    /**
     * 构建测试类
     *
     * @param  string  $moduleName  模块名称
     * @param  string  $name  测试名称
     * @param  string  $testType  测试类型
     * @return string  测试类代码
     */
    protected function buildTestClass(string $moduleName, string $name, string $testType): string
    {
        if ($testType === 'Unit') {
            $stubPath = __DIR__ . '/../../../stubs/test.unit.stub';
        } else {
            $stubPath = __DIR__ . '/../../../stubs/test.feature.stub';
        }
        $stub = $this->files->get($stubPath);
        return str_replace(
            ['{{ namespace }}', '{{ class }}'],
            ["Tests\\{$testType}", $name],
            $stub
        );
    }
}