<?php

namespace Kylin\Modules\Console\Commands;

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

/**
 * 模块统计命令
 *
 * 统计模块的各种信息
 */
class ModuleStatsCommand extends Command
{
    /**
     * 命令名称和签名
     *
     * @var string
     * 
     * 命令参数说明：
     * 1. {modules?*} - 模块名称列表（可选）
     *    - 数据类型：字符串数组
     *    - 用途：指定要统计信息的模块名称列表，不指定则统计所有模块
     *    - 示例：php artisan module:stats game user
     * 
     * 命令选项说明：
     * 1. {--all} - 统计所有模块
     *    - 完整形式：--all
     *    - 用途：统计所有模块的信息
     *    - 示例：php artisan module:stats --all
     * 
     * 2. {--files} - 统计文件数量
     *    - 完整形式：--files
     *    - 用途：统计模块的文件数量
     *    - 示例：php artisan module:stats game --files
     * 
     * 3. {--lines} - 统计代码行数
     *    - 完整形式：--lines
     *    - 用途：统计模块的代码行数
     *    - 示例：php artisan module:stats game --lines
     * 
     * 4. {--size} - 统计模块大小
     *    - 完整形式：--size
     *    - 用途：统计模块的大小
     *    - 示例：php artisan module:stats game --size
     * 
     * 5. {--dependencies} - 统计依赖关系
     *    - 完整形式：--dependencies
     *    - 用途：统计模块的依赖关系
     *    - 示例：php artisan module:stats game --dependencies
     * 
     * 6. {--detailed} - 显示详细统计信息
     *    - 完整形式：--detailed
     *    - 用途：显示详细的统计信息
     *    - 示例：php artisan module:stats game --detailed
     */
    protected $signature = 'module:stats {modules?* : 模块名称列表} {--all : 统计所有模块} {--files : 统计文件数量} {--lines : 统计代码行数} {--size : 统计模块大小} {--dependencies : 统计依赖关系} {--detailed : 显示详细统计信息}';

    /**
     * 命令描述
     *
     * @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');
        $countFiles = $this->option('files');
        $countLines = $this->option('lines');
        $countSize = $this->option('size');
        $countDependencies = $this->option('dependencies');
        $detailed = $this->option('detailed');

        // 如果没有指定具体的统计选项，默认统计所有
        $defaultStats = !$countFiles && !$countLines && !$countSize && !$countDependencies;

        // 确定要统计的模块
        $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('');

        // 总体统计
        $totalStats = [
            'modules' => count($targetModules),
            'files' => 0,
            'lines' => 0,
            'size' => 0,
            'dependencies' => 0,
        ];

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

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

            // 统计文件数量
            if ($countFiles || $defaultStats) {
                $fileCount = $this->countFiles($modulePath);
                $totalStats['files'] += $fileCount;
                $this->line("  文件数量: {$fileCount}");
            }

            // 统计代码行数
            if ($countLines || $defaultStats) {
                $lineCount = $this->countLines($modulePath);
                $totalStats['lines'] += $lineCount;
                $this->line("  代码行数: {$lineCount}");
            }

            // 统计模块大小
            if ($countSize || $defaultStats) {
                $size = $this->calculateSize($modulePath);
                $totalStats['size'] += $size;
                $this->line("  模块大小: " . $this->formatSize($size));
            }

            // 统计依赖关系
            if ($countDependencies || $defaultStats) {
                $dependencies = $this->countDependencies($module);
                $dependencyCount = count($dependencies);
                $totalStats['dependencies'] += $dependencyCount;
                $this->line("  依赖数量: {$dependencyCount}");

                if ($detailed && $dependencyCount > 0) {
                    $this->line("  依赖列表:");
                    foreach ($dependencies as $dependency) {
                        $this->line("    - {$dependency}");
                    }
                }
            }

            // 详细统计
            if ($detailed) {
                $this->line("  详细信息:");
                $this->line("    路径: {$modulePath}");
                $this->line("    状态: " . ($module->isEnabled() ? '启用' : '禁用'));
                $this->line("    命名空间: " . $this->getModuleNamespace($module));
            }

            $this->line('');
        }

        // 显示总体统计
        $this->info('总体统计:');
        $this->line("  模块数量: {$totalStats['modules']}");
        if ($countFiles || $defaultStats) {
            $this->line("  总文件数: {$totalStats['files']}");
        }
        if ($countLines || $defaultStats) {
            $this->line("  总代码行数: {$totalStats['lines']}");
        }
        if ($countSize || $defaultStats) {
            $this->line("  总大小: " . $this->formatSize($totalStats['size']));
        }
        if ($countDependencies || $defaultStats) {
            $this->line("  总依赖数: {$totalStats['dependencies']}");
        }

        return 0;
    }

    /**
     * 统计文件数量
     *
     * @param  string  $directory  目录路径
     * @return int  文件数量
     */
    protected function countFiles(string $directory): int
    {
        $count = 0;

        if ($this->files->exists($directory)) {
            $files = $this->files->allFiles($directory);
            $count = count($files);
        }

        return $count;
    }

    /**
     * 统计代码行数
     *
     * @param  string  $directory  目录路径
     * @return int  代码行数
     */
    protected function countLines(string $directory): int
    {
        $count = 0;

        if ($this->files->exists($directory)) {
            $files = $this->files->allFiles($directory);
            foreach ($files as $file) {
                if ($this->isCodeFile($file->getFilename())) {
                    try {
                        $content = $this->files->get($file->getPathname());
                        $lines = explode("\n", $content);
                        $count += count($lines);
                    } catch (\Exception $e) {
                        // 忽略无法读取的文件
                    }
                }
            }
        }

        return $count;
    }

    /**
     * 计算目录大小
     *
     * @param  string  $directory  目录路径
     * @return int  大小（字节）
     */
    protected function calculateSize(string $directory): int
    {
        $size = 0;

        if ($this->files->exists($directory)) {
            $files = $this->files->allFiles($directory);
            foreach ($files as $file) {
                $size += $file->getSize();
            }
        }

        return $size;
    }

    /**
     * 统计依赖关系
     *
     * @param  mixed  $module  模块实例
     * @return array  依赖列表
     */
    protected function countDependencies($module): array
    {
        try {
            $composerPath = $module->getPath() . '/composer.json';
            if (!file_exists($composerPath)) {
                return [];
            }

            $composer = json_decode(file_get_contents($composerPath), true);
            return $composer['require'] ?? [];
        } catch (\Exception $e) {
            return [];
        }
    }

    /**
     * 获取模块命名空间
     *
     * @param  mixed  $module  模块实例
     * @return string  命名空间
     */
    protected function getModuleNamespace($module): string
    {
        try {
            $composerPath = $module->getPath() . '/composer.json';
            if (!file_exists($composerPath)) {
                return '未知';
            }

            $composer = json_decode(file_get_contents($composerPath), true);
            $autoload = $composer['autoload'] ?? [];
            $psr4 = $autoload['psr-4'] ?? [];

            return array_key_first($psr4) ?: '未知';
        } catch (\Exception $e) {
            return '未知';
        }
    }

    /**
     * 判断是否为代码文件
     *
     * @param  string  $filename  文件名
     * @return bool  是否为代码文件
     */
    protected function isCodeFile(string $filename): bool
    {
        $codeExtensions = [
            'php', 'js', 'ts', 'jsx', 'tsx', 'vue', 'blade.php',
            'css', 'scss', 'sass', 'less', 'styl',
            'json', 'yaml', 'yml', 'xml', 'md', 'txt'
        ];

        $extension = pathinfo($filename, PATHINFO_EXTENSION);
        return in_array($extension, $codeExtensions) || str_ends_with($filename, '.blade.php');
    }

    /**
     * 格式化文件大小
     *
     * @param  int  $size  大小（字节）
     * @return string  格式化后的大小
     */
    protected function formatSize(int $size): string
    {
        $units = ['B', 'KB', 'MB', 'GB'];
        $unitIndex = 0;

        while ($size > 1024 && $unitIndex < count($units) - 1) {
            $size /= 1024;
            $unitIndex++;
        }

        return round($size, 2) . ' ' . $units[$unitIndex];
    }
}
