<?php

namespace Kylin\Modules\Console\Commands;

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

/**
 * 模块路由管理命令
 *
 * 管理模块的路由，帮助开发者更好地管理模块的路由配置
 */
class ModuleRouteCommand extends Command
{
    /**
     * 命令名称和签名
     *
     * @var string
     * 
     * 命令参数说明：
     * 1. {module} - 模块名称（必填）
     *    - 数据类型：字符串
     *    - 用途：指定要管理路由的模块名称
     *    - 示例：php artisan module:route game
     * 
     * 命令选项说明：
     * 1. {--list} - 列出模块的所有路由
     *    - 完整形式：--list
     *    - 用途：列出模块的所有路由
     *    - 示例：php artisan module:route game --list
     * 
     * 2. {--cache} - 缓存模块的路由
     *    - 完整形式：--cache
     *    - 用途：缓存模块的路由，提高加载速度
     *    - 示例：php artisan module:route game --cache
     * 
     * 3. {--clear} - 清除模块的路由缓存
     *    - 完整形式：--clear
     *    - 用途：清除模块的路由缓存，确保路由变更能够生效
     *    - 示例：php artisan module:route game --clear
     * 
     * 4. {--export=} - 导出模块的路由为文件
     *    - 完整形式：--export
     *    - 数据类型：字符串
     *    - 用途：导出模块的路由为文件
     *    - 示例：php artisan module:route game --export=routes.json
     * 
     * 5. {--import=} - 从文件导入模块的路由
     *    - 完整形式：--import
     *    - 数据类型：字符串
     *    - 用途：从文件导入模块的路由
     *    - 示例：php artisan module:route game --import=routes.json
     * 
     * 6. {--generate} - 生成模块的路由文件
     *    - 完整形式：--generate
     *    - 用途：生成模块的路由文件
     *    - 示例：php artisan module:route game --generate
     */
    protected $signature = 'module:route {module : 模块名称} {--list : 列出模块的所有路由} {--cache : 缓存模块的路由} {--clear : 清除模块的路由缓存} {--export= : 导出模块的路由为文件} {--import= : 从文件导入模块的路由} {--generate : 生成模块的路由文件}';

    /**
     * 命令描述
     *
     * @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');
        $list = $this->option('list');
        $cache = $this->option('cache');
        $clear = $this->option('clear');
        $export = $this->option('export');
        $import = $this->option('import');
        $generate = $this->option('generate');

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

        $modulePath = $module->getPath();
        $routesPath = "{$modulePath}/routes";

        // 检查路由目录是否存在
        if (!($this->files->exists($routesPath))) {
            $this->files->makeDirectory($routesPath, 0755, true);
            $this->info("创建路由目录: {$routesPath}");
        }

        // 列出模块的所有路由
        if ($list) {
            return $this->listRoutes($moduleName);
        }

        // 缓存模块的路由
        if ($cache) {
            return $this->cacheRoutes($moduleName);
        }

        // 清除模块的路由缓存
        if ($clear) {
            return $this->clearRoutesCache($moduleName);
        }

        // 导出模块的路由为文件
        if ($export) {
            return $this->exportRoutes($routesPath, (string) $export);
        }

        // 从文件导入模块的路由
        if ($import) {
            return $this->importRoutes($routesPath, (string) $import);
        }

        // 生成模块的路由文件
        if ($generate) {
            return $this->generateRoutes($routesPath);
        }

        // 默认列出模块的所有路由
        return $this->listRoutes($moduleName);
    }

    /**
     * 列出模块的所有路由
     *
     * @param  string  $moduleName  模块名称
     * @return int  退出码
     */
    protected function listRoutes(string $moduleName): int
    {
        $this->info("模块 [{$moduleName}] 的路由:");

        // 获取所有路由
        $routes = app('router')->getRoutes();

        $moduleRoutes = [];

        // 过滤出模块的路由
        foreach ($routes as $route) {
            $action = $route->getAction();
            if (isset($action['namespace']) && str_contains($action['namespace'], ucfirst($moduleName))) {
                $moduleRoutes[] = $route;
            }
        }

        if (empty($moduleRoutes)) {
            $this->info('  没有找到路由');
            return 0;
        }

        // 显示路由
        $headers = ['方法', '路径', '名称', '操作'];
        $rows = [];

        foreach ($moduleRoutes as $route) {
            $methods = implode(',', $route->methods());
            $uri = $route->uri();
            $name = $route->getName() ?: '-';
            $action = $this->getActionName($route);

            $rows[] = [$methods, $uri, $name, $action];
        }

        $this->table($headers, $rows);

        return 0;
    }

    /**
     * 缓存模块的路由
     *
     * @param  string  $moduleName  模块名称
     * @return int  退出码
     */
    protected function cacheRoutes(string $moduleName): int
    {
        $this->info("缓存模块 [{$moduleName}] 的路由...");

        // 运行全局路由缓存命令
        $this->call('route:cache');

        $this->info("模块 [{$moduleName}] 的路由缓存完成");

        return 0;
    }

    /**
     * 清除模块的路由缓存
     *
     * @param  string  $moduleName  模块名称
     * @return int  退出码
     */
    protected function clearRoutesCache(string $moduleName): int
    {
        $this->info("清除模块 [{$moduleName}] 的路由缓存...");

        // 运行全局路由缓存清除命令
        $this->call('route:clear');

        $this->info("模块 [{$moduleName}] 的路由缓存清除完成");

        return 0;
    }

    /**
     * 导出模块的路由为文件
     *
     * @param  string  $routesPath  路由文件路径
     * @param  string  $exportPath  导出路径
     * @return int  退出码
     */
    protected function exportRoutes(string $routesPath, string $exportPath): int
    {
        // 收集所有路由文件
        $routeFiles = $this->files->files($routesPath);

        if (empty($routeFiles)) {
            $this->error('没有找到路由文件');
            return 1;
        }

        $exportContent = "<?php\n\n";

        foreach ($routeFiles as $file) {
            $exportContent .= "// 从 {$file->getFilename()} 导出\n";
            $exportContent .= $this->files->get($file);
            $exportContent .= "\n\n";
        }

        $this->files->put($exportPath, $exportContent);

        $this->info("路由已导出到: {$exportPath}");

        return 0;
    }

    /**
     * 从文件导入模块的路由
     *
     * @param  string  $routesPath  路由文件路径
     * @param  string  $importPath  导入路径
     * @return int  退出码
     */
    protected function importRoutes(string $routesPath, string $importPath): int
    {
        if (!($this->files->exists($importPath))) {
            $this->error("导入文件不存在: {$importPath}");
            return 1;
        }

        $importContent = $this->files->get($importPath);

        // 写入到 web.php 文件
        $this->files->put("{$routesPath}/web.php", $importContent);

        $this->info("路由已从 {$importPath} 导入到 {$routesPath}/web.php");

        return 0;
    }

    /**
     * 生成模块的路由文件
     *
     * @param  string  $routesPath  路由文件路径
     * @return int  退出码
     */
    protected function generateRoutes(string $routesPath): int
    {
        // 生成 web.php 文件
        $webContent = "<?php\n\nuse Illuminate\\Support\\Facades\\Route;\n\nRoute::group([\n    'middleware' => 'web',\n], function () {\n    // 模块的 Web 路由\n});\n";

        $this->files->put("{$routesPath}/web.php", $webContent);

        // 生成 api.php 文件
        $apiContent = "<?php\n\nuse Illuminate\\Support\\Facades\\Route;\n\nRoute::group([\n    'middleware' => 'api',\n    'prefix' => 'api',\n], function () {\n    // 模块的 API 路由\n});\n";

        $this->files->put("{$routesPath}/api.php", $apiContent);

        $this->info("生成路由文件:");
        $this->line("  - {$routesPath}/web.php");
        $this->line("  - {$routesPath}/api.php");

        return 0;
    }

    /**
     * 获取路由的操作名称
     *
     * @param  mixed  $route  路由实例
     * @return string  操作名称
     */
    protected function getActionName($route): string
    {
        $action = $route->getAction();

        if (isset($action['controller'])) {
            return $action['controller'];
        }

        if (isset($action['uses'])) {
            return $action['uses'];
        }

        return 'Closure';
    }
}
