<?php

namespace Kylin\Modules\Console\Commands;

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

/**
 * 模块生成组件命令
 *
 * 为模块生成新的组件类
 */
class ModuleMakeComponentCommand extends Command
{
    /**
     * 命令名称和签名
     *
     * @var string
     * 
     * 命令参数说明：
     * 1. {module} - 模块名称（必填）
     *    - 数据类型：字符串
     *    - 用途：指定组件所属的模块名称
     *    - 示例：php artisan module:make-component game Alert
     * 
     * 2. {name} - 组件名称（必填）
     *    - 数据类型：字符串
     *    - 用途：指定要创建的组件名称
     *    - 示例：php artisan module:make-component game Alert
     * 
     * 命令选项说明：
     * 1. {--v|view=} - 组件的视图文件
     *    - 简写：-v
     *    - 完整形式：--view
     *    - 数据类型：字符串
     *    - 用途：指定组件的视图文件路径
     *    - 示例：php artisan module:make-component game Alert --view=components.alert
     */
    protected $signature = 'module:make-component {module : 模块名称} {name : 组件名称} {--v|view= : 组件的视图文件}';

    /**
     * 命令描述
     *
     * @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');
        $view = $this->option('view');

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

        $modulePath = $module->getPath();
        $srcPath = "{$modulePath}/src";
        $componentsPath = "{$srcPath}/View/Components";

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

        // 生成组件类
        $componentClass = $this->buildComponentClass($moduleName, $name);
        $componentFile = "{$componentsPath}/{$name}.php";

        if ($this->files->exists($componentFile)) {
            $this->error("组件 [{$name}] 已存在");
            return 1;
        }

        $this->files->put($componentFile, $componentClass);
        $this->info("创建组件: {$componentFile}");

        // 生成组件视图文件
        $this->generateComponentView($modulePath, $name, $view);

        return 0;
    }

    /**
     * 构建组件类
     *
     * @param  string  $moduleName  模块名称
     * @param  string  $name  组件名称
     * @return string  组件类代码
     */
    protected function buildComponentClass(string $moduleName, string $name): string
    {
        $namespace = "{$moduleName}\View\Components";
        $stubPath = __DIR__ . '/../../../stubs/component.stub';
        $stub = $this->files->get($stubPath);
        return str_replace(
            ['{{ namespace }}', '{{ class }}', '{{ module }}'],
            [$namespace, $name, $moduleName],
            $stub
        );
    }

    /**
     * 生成组件视图文件
     *
     * @param  string  $modulePath  模块路径
     * @param  string  $name  组件名称
     * @param  string|null  $view  组件的视图文件
     */
    protected function generateComponentView(string $modulePath, string $name, ?string $view): void
    {
        $viewsPath = "{$modulePath}/resources/views/components";
        $viewFile = "{$viewsPath}/{$name}.blade.php";

        // 确保目录存在
        if (!($this->files->exists($viewsPath))) {
            $this->files->makeDirectory($viewsPath, 0755, true);
            $this->info("创建组件视图目录: {$viewsPath}");
        }

        if (!($this->files->exists($viewFile))) {
            $stubPath = __DIR__ . '/../../../stubs/component.view.stub';
            $stub = $this->files->get($stubPath);
            $content = str_replace('{{ class }}', $name, $stub);

            $this->files->put($viewFile, $content);
            $this->info("创建组件视图: {$viewFile}");
        }
    }
}