<?php

namespace Kylin\Modules\Console\Commands;

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

/**
 * 模块健康检查命令
 *
 * 检查模块的健康状态，包括目录结构、文件完整性、依赖关系等
 */
class ModuleHealthCommand extends Command
{
    /**
     * 命令名称和签名
     *
     * @var string
     * 
     * 命令参数说明：
     * 1. {modules?*} - 模块名称列表（可选）
     *    - 数据类型：字符串数组
     *    - 用途：指定要检查健康状态的模块名称列表，不指定则检查所有模块
     *    - 示例：php artisan module:health game user
     * 
     * 命令选项说明：
     * 1. {--all} - 检查所有模块
     *    - 完整形式：--all
     *    - 用途：检查所有模块的健康状态
     *    - 示例：php artisan module:health --all
     * 
     * 2. {--detailed} - 显示详细检查结果
     *    - 完整形式：--detailed
     *    - 用途：显示详细的健康检查结果
     *    - 示例：php artisan module:health game --detailed
     * 
     * 3. {--fix} - 尝试自动修复问题
     *    - 完整形式：--fix
     *    - 用途：尝试自动修复模块的健康问题
     *    - 示例：php artisan module:health game --fix
     */
    protected $signature = 'module:health {modules?* : 模块名称列表} {--all : 检查所有模块} {--detailed : 显示详细检查结果} {--fix : 尝试自动修复问题}';

    /**
     * 命令描述
     *
     * @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
    {
        $modules = $this->argument('modules') ?: [];
        $all = $this->option('all');
        $detailed = $this->option('detailed');
        $fix = $this->option('fix');

        // 确定要检查的模块
        $targetModules = [];
        if ($all) {
            $targetModules = $this->moduleManager->all();
        } elseif (!empty($modules)) {
            foreach ($modules as $moduleName) {
                $module = $this->moduleManager->get($moduleName);
                if ($module) {
                    $targetModules[] = $module;
                } else {
                    $this->warn("模块 [{$moduleName}] 未找到，将被跳过。");
                }
            }
        } else {
            $this->error('请指定模块名称或使用 --all 选项');
            return 1;
        }

        if (empty($targetModules)) {
            $this->error('没有找到要检查的模块');
            return 1;
        }

        $this->info('正在检查模块健康状态...');
        $this->line('');

        $overallHealth = 0;
        $totalModules = count($targetModules);
        $healthyModules = 0;

        foreach ($targetModules as $module) {
            $modulePath = $module->getPath();
            $moduleName = $module->getName();

            $this->info("检查模块 [{$moduleName}]:");

            // 检查目录结构
            $directoryCheck = $this->checkDirectoryStructure($modulePath, $detailed, $fix);

            // 检查文件完整性
            $fileCheck = $this->checkFileIntegrity($modulePath, $detailed, $fix);

            // 检查依赖关系
            $dependencyCheck = $this->checkDependencies($module, $detailed, $fix);

            // 计算模块健康状态
            $moduleHealth = $directoryCheck + $fileCheck + $dependencyCheck;
            $overallHealth += $moduleHealth;

            // 显示模块健康状态
            if ($moduleHealth === 3) {
                $this->line("  健康状态: <fg=green>健康</fg=green>");
                $healthyModules++;
            } elseif ($moduleHealth >= 2) {
                $this->line("  健康状态: <fg=yellow>基本健康</fg=yellow>");
            } else {
                $this->line("  健康状态: <fg=red>不健康</fg=red>");
            }

            $this->line('');
        }

        // 显示总体健康状态
        $averageHealth = $totalModules > 0 ? $overallHealth / $totalModules : 0;
        $this->info('总体健康状态:');
        $this->line("  检查模块数: {$totalModules}");
        $this->line("  健康模块数: {$healthyModules}");
        $this->line("  平均健康得分: " . round($averageHealth, 2) . "/3");

        if ($averageHealth === 3) {
            $this->info('所有模块都处于健康状态');
        } elseif ($averageHealth >= 2) {
            $this->warn('部分模块需要关注');
        } else {
            $this->error('多个模块存在严重问题');
        }

        return $averageHealth < 2 ? 1 : 0;
    }

    /**
     * 检查目录结构
     *
     * @param  string  $modulePath  模块路径
     * @param  bool  $detailed  是否显示详细信息
     * @param  bool  $fix  是否尝试修复
     * @return int  检查结果（0-1）
     */
    protected function checkDirectoryStructure(string $modulePath, bool $detailed, bool $fix): int
    {
        $requiredDirectories = [
            'app/Console/Commands',
            'app/Http/Controllers',
            'app/Http/Middleware',
            'app/Http/Requests',
            'app/Models',
            'app/Providers',
            'config',
            'database/migrations',
            'database/seeders',
            'resources/views',
            'resources/lang',
            'routes',
        ];

        $missingDirectories = [];

        foreach ($requiredDirectories as $directory) {
            $dirPath = "{$modulePath}/{$directory}";
            if (!$this->files->exists($dirPath)) {
                $missingDirectories[] = $directory;
            }
        }

        if (empty($missingDirectories)) {
            if ($detailed) {
                $this->line("  目录结构: <fg=green>完整</fg=green>");
            }
            return 1;
        }

        if ($detailed) {
            $this->line("  目录结构: <fg=red>不完整</fg=red>");
            foreach ($missingDirectories as $directory) {
                $this->line("    - 缺少目录: {$directory}");
            }
        }

        if ($fix) {
            foreach ($missingDirectories as $directory) {
                $dirPath = "{$modulePath}/{$directory}";
                $this->files->makeDirectory($dirPath, 0755, true);
                $this->line("    - 创建目录: {$directory}");
            }
            return 1;
        }

        return 0;
    }

    /**
     * 检查文件完整性
     *
     * @param  string  $modulePath  模块路径
     * @param  bool  $detailed  是否显示详细信息
     * @param  bool  $fix  是否尝试修复
     * @return int  检查结果（0-1）
     */
    protected function checkFileIntegrity(string $modulePath, bool $detailed, bool $fix): int
    {
        $requiredFiles = [
            'composer.json',
            'app/Providers/' . basename($modulePath) . 'ServiceProvider.php',
            'routes/web.php',
        ];

        $missingFiles = [];

        foreach ($requiredFiles as $file) {
            $filePath = "{$modulePath}/{$file}";
            if (!$this->files->exists($filePath)) {
                $missingFiles[] = $file;
            }
        }

        if (empty($missingFiles)) {
            if ($detailed) {
                $this->line("  文件完整性: <fg=green>完整</fg=green>");
            }
            return 1;
        }

        if ($detailed) {
            $this->line("  文件完整性: <fg=red>不完整</fg=red>");
            foreach ($missingFiles as $file) {
                $this->line("    - 缺少文件: {$file}");
            }
        }

        if ($fix) {
            foreach ($missingFiles as $file) {
                $filePath = "{$modulePath}/{$file}";
                $this->line("    - 无法自动创建文件: {$file}");
            }
        }

        return 0;
    }

    /**
     * 检查依赖关系
     *
     * @param  mixed  $module  模块实例
     * @param  bool  $detailed  是否显示详细信息
     * @param  bool  $fix  是否尝试修复
     * @return int  检查结果（0-1）
     */
    protected function checkDependencies($module, bool $detailed, bool $fix): int
    {
        try {
            $composerPath = "{$module->getPath()}/composer.json";
            if (!file_exists($composerPath)) {
                if ($detailed) {
                    $this->line("  依赖关系: <fg=red>无法检查</fg=red>");
                }
                return 0;
            }

            $composer = json_decode($this->files->get($composerPath), true);
            $dependencies = $composer['require'] ?? [];

            if ($detailed) {
                $this->line("  依赖关系: <fg=green>正常</fg=green>");
                if (!empty($dependencies)) {
                    $this->line("    依赖项数量: " . count($dependencies));
                }
            }

            return 1;
        } catch (\Exception $e) {
            if ($detailed) {
                $this->line("  依赖关系: <fg=red>异常</fg=red>");
                $this->line("    错误: {$e->getMessage()}");
            }
            return 0;
        }
    }
}
