/**
 * 状态到报告数据转换器
 * 将 BuildState 转换为统一的报告数据格式
 */
export class StateToReportConverter {
    /**
     * 转换为统一报告数据
     */
    static convertToUnifiedReport(state) {
        const assets = Object.values(state.assets);
        // 计算总体统计
        const totalOriginalSize = assets.reduce((sum, asset) => sum + asset.originalSize, 0);
        const totalFinalSize = assets.reduce((sum, asset) => sum + asset.finalSize, 0);
        const totalCompressionRatio = totalOriginalSize > 0
            ? 1 - (totalFinalSize / totalOriginalSize)
            : 0;
        // 转换资产数据
        const reportAssets = assets.map(asset => this.convertAsset(asset));
        // 按类型统计
        const byType = this.calculateTypeStatistics(assets);
        // 按分类统计
        const byCategory = this.calculateCategoryStatistics(assets, totalFinalSize);
        // 转换阶段信息
        const stages = state.stages.map(stage => ({
            name: stage.stage,
            startTime: stage.startTime,
            endTime: stage.endTime,
            duration: stage.endTime ? stage.endTime - stage.startTime : undefined,
        }));
        return {
            totalAssets: assets.length,
            totalOriginalSize,
            totalFinalSize,
            totalCompressionRatio,
            assets: reportAssets,
            byType,
            byCategory,
            stages,
        };
    }
    /**
     * 转换单个资产
     */
    static convertAsset(asset) {
        const lastProcessing = asset.processingHistory[asset.processingHistory.length - 1];
        return {
            id: asset.id,
            originalName: asset.originalName,
            finalName: lastProcessing?.name || asset.originalName,
            type: asset.type,
            originalSize: asset.originalSize,
            finalSize: asset.finalSize,
            compressionRatio: asset.totalCompressionRatio,
            inlined: lastProcessing?.inlined || false,
            inlineLocation: lastProcessing?.inlineLocation,
            optimizations: this.collectOptimizations(asset),
            processingSteps: asset.processingHistory.map(step => ({
                stage: step.stage,
                name: step.name,
                size: step.size,
                compressionRatio: step.compressionRatio,
                optimizations: step.optimizations,
            })),
        };
    }
    /**
     * 收集所有优化类型
     */
    static collectOptimizations(asset) {
        const optimizations = new Set();
        for (const step of asset.processingHistory) {
            for (const opt of step.optimizations) {
                optimizations.add(opt);
            }
        }
        return Array.from(optimizations);
    }
    /**
     * 计算按类型统计
     */
    static calculateTypeStatistics(assets) {
        const stats = {};
        for (const asset of assets) {
            if (!stats[asset.type]) {
                stats[asset.type] = {
                    count: 0,
                    originalSize: 0,
                    finalSize: 0,
                    avgCompressionRatio: 0,
                };
            }
            stats[asset.type].count++;
            stats[asset.type].originalSize += asset.originalSize;
            stats[asset.type].finalSize += asset.finalSize;
        }
        // 计算平均压缩率
        for (const type in stats) {
            const stat = stats[type];
            stat.avgCompressionRatio = stat.originalSize > 0
                ? 1 - (stat.finalSize / stat.originalSize)
                : 0;
        }
        return stats;
    }
    /**
     * 计算按分类统计
     */
    static calculateCategoryStatistics(assets, totalSize) {
        const categories = {
            engine: { name: '引擎', count: 0, size: 0, percentage: 0 },
            scripts: { name: '脚本', count: 0, size: 0, percentage: 0 },
            textures: { name: '纹理', count: 0, size: 0, percentage: 0 },
            audio: { name: '音频', count: 0, size: 0, percentage: 0 },
            models: { name: '模型', count: 0, size: 0, percentage: 0 },
            config: { name: '配置', count: 0, size: 0, percentage: 0 },
            other: { name: '其他', count: 0, size: 0, percentage: 0 },
        };
        for (const asset of assets) {
            let category = 'other';
            // 根据资产 ID 或类型判断分类
            if (asset.id.includes('engine') || asset.id.includes('playcanvas')) {
                category = 'engine';
            }
            else if (asset.type === 'script') {
                category = 'scripts';
            }
            else if (asset.type === 'texture') {
                category = 'textures';
            }
            else if (asset.type === 'audio') {
                category = 'audio';
            }
            else if (asset.type === 'model') {
                category = 'models';
            }
            else if (asset.type === 'json' || asset.id.includes('config')) {
                category = 'config';
            }
            categories[category].count++;
            categories[category].size += asset.finalSize;
        }
        // 计算百分比
        for (const category in categories) {
            categories[category].percentage = totalSize > 0
                ? (categories[category].size / totalSize) * 100
                : 0;
        }
        return categories;
    }
    /**
     * 格式化字节数
     */
    static formatBytes(bytes) {
        if (bytes === 0)
            return '0 B';
        const k = 1024;
        const sizes = ['B', 'KB', 'MB', 'GB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
    }
    /**
     * 格式化百分比
     */
    static formatPercentage(ratio) {
        return `${(ratio * 100).toFixed(1)}%`;
    }
    /**
     * 获取压缩率颜色
     */
    static getCompressionColor(ratio) {
        if (ratio > 0.5)
            return 'green';
        if (ratio > 0.2)
            return 'yellow';
        return 'red';
    }
}
