import { StateToReportConverter } from '../state/state-to-report-converter.js';
/**
 * 优化分析器
 * 分析构建状态并提供优化建议
 */
export class OptimizationAnalyzer {
    constructor(state) {
        this.suggestions = [];
        this.state = state;
    }
    /**
     * 执行优化分析
     */
    analyze() {
        this.suggestions = [];
        // 检测各种优化机会
        this.detectLargeUncompressedFiles();
        this.detectFormatConversionOpportunities();
        this.detectMergeableSmallFiles();
        this.detectUnusedAssets();
        this.detectMissingMinification();
        this.detectMissingImageCompression();
        this.detectInlineLimitIssues();
        // 计算总节省
        const totalEstimatedSavings = this.suggestions.reduce((sum, s) => sum + s.estimatedSavings, 0);
        const totalSize = Object.values(this.state.assets).reduce((sum, asset) => sum + asset.finalSize, 0);
        const estimatedOptimizationRate = totalSize > 0
            ? totalEstimatedSavings / totalSize
            : 0;
        // 按严重程度分组
        const bySeverity = {
            high: this.suggestions.filter(s => s.severity === 'high'),
            medium: this.suggestions.filter(s => s.severity === 'medium'),
            low: this.suggestions.filter(s => s.severity === 'low'),
        };
        return {
            totalSuggestions: this.suggestions.length,
            totalEstimatedSavings,
            totalEstimatedSavingsFormatted: StateToReportConverter.formatBytes(totalEstimatedSavings),
            estimatedOptimizationRate,
            suggestions: this.suggestions,
            bySeverity,
        };
    }
    /**
     * 检测未压缩的大文件
     */
    detectLargeUncompressedFiles() {
        const threshold = 100 * 1024; // 100KB
        const minCompressionRatio = 0.1; // 10%
        const largeUncompressed = Object.values(this.state.assets).filter(asset => asset.finalSize > threshold &&
            asset.totalCompressionRatio < minCompressionRatio);
        if (largeUncompressed.length > 0) {
            const totalSize = largeUncompressed.reduce((sum, a) => sum + a.finalSize, 0);
            const estimatedSavings = totalSize * 0.5; // 假设可以压缩 50%
            this.suggestions.push({
                type: 'large-uncompressed',
                severity: 'high',
                description: `发现 ${largeUncompressed.length} 个大文件（> 100KB）未进行有效压缩`,
                affectedAssets: largeUncompressed.map(a => a.originalName),
                estimatedSavings,
                estimatedSavingsFormatted: StateToReportConverter.formatBytes(estimatedSavings),
                recommendation: '建议对这些文件启用压缩或使用更高效的压缩算法',
                configExample: `// 在 Vite 配置中启用压缩
build: {
  minify: 'terser',
  terserOptions: {
    compress: {
      drop_console: true,
      drop_debugger: true
    }
  }
}`,
            });
        }
    }
    /**
     * 检测可以转换格式的资源
     */
    detectFormatConversionOpportunities() {
        const pngAssets = Object.values(this.state.assets).filter(asset => asset.type === 'texture' &&
            asset.originalName.toLowerCase().endsWith('.png') &&
            asset.finalSize > 50 * 1024 // > 50KB
        );
        if (pngAssets.length > 0) {
            const totalSize = pngAssets.reduce((sum, a) => sum + a.finalSize, 0);
            const estimatedSavings = totalSize * 0.3; // WebP 通常可以节省 30%
            this.suggestions.push({
                type: 'format-conversion',
                severity: 'medium',
                description: `发现 ${pngAssets.length} 个 PNG 图片可以转换为 WebP 格式`,
                affectedAssets: pngAssets.map(a => a.originalName),
                estimatedSavings,
                estimatedSavingsFormatted: StateToReportConverter.formatBytes(estimatedSavings),
                recommendation: '建议将 PNG 图片转换为 WebP 格式以减小文件大小',
                configExample: `// 使用 vite-plugin-imagemin
import viteImagemin from 'vite-plugin-imagemin';

plugins: [
  viteImagemin({
    webp: {
      quality: 75
    }
  })
]`,
            });
        }
    }
    /**
     * 检测可以合并的小文件
     */
    detectMergeableSmallFiles() {
        const smallThreshold = 10 * 1024; // 10KB
        const smallScripts = Object.values(this.state.assets).filter(asset => asset.type === 'script' && asset.finalSize < smallThreshold);
        if (smallScripts.length >= 5) {
            const totalSize = smallScripts.reduce((sum, a) => sum + a.finalSize, 0);
            const estimatedSavings = smallScripts.length * 500; // 每个文件节省约 500 字节的 HTTP 开销
            this.suggestions.push({
                type: 'merge-small-files',
                severity: 'low',
                description: `发现 ${smallScripts.length} 个小脚本文件（< 10KB）可以合并`,
                affectedAssets: smallScripts.map(a => a.originalName),
                estimatedSavings,
                estimatedSavingsFormatted: StateToReportConverter.formatBytes(estimatedSavings),
                recommendation: '建议合并这些小文件以减少 HTTP 请求数量',
                configExample: `// Vite 会自动进行代码分割和合并
// 如果需要手动控制，可以使用 manualChunks
build: {
  rollupOptions: {
    output: {
      manualChunks: {
        'vendor': ['module1', 'module2']
      }
    }
  }
}`,
            });
        }
    }
    /**
     * 检测未使用的资源
     */
    detectUnusedAssets() {
        // 检测在处理历史中标记为未使用的资源
        const unusedAssets = Object.values(this.state.assets).filter(asset => {
            // 检查是否有任何处理步骤标记为 'unused'
            return asset.processingHistory.some(step => step.optimizations.includes('unused'));
        });
        if (unusedAssets.length > 0) {
            const totalSize = unusedAssets.reduce((sum, a) => sum + a.finalSize, 0);
            this.suggestions.push({
                type: 'unused-asset',
                severity: 'high',
                description: `发现 ${unusedAssets.length} 个未使用的资源`,
                affectedAssets: unusedAssets.map(a => a.originalName),
                estimatedSavings: totalSize,
                estimatedSavingsFormatted: StateToReportConverter.formatBytes(totalSize),
                recommendation: '建议从项目中移除这些未使用的资源',
            });
        }
    }
    /**
     * 检测缺少代码压缩
     */
    detectMissingMinification() {
        const unminifiedScripts = Object.values(this.state.assets).filter(asset => {
            if (asset.type !== 'script')
                return false;
            // 检查是否应用了 minify 优化
            const hasMinify = asset.processingHistory.some(step => step.optimizations.includes('minify'));
            return !hasMinify && asset.finalSize > 10 * 1024; // > 10KB
        });
        if (unminifiedScripts.length > 0) {
            const totalSize = unminifiedScripts.reduce((sum, a) => sum + a.finalSize, 0);
            const estimatedSavings = totalSize * 0.4; // 压缩通常可以节省 40%
            this.suggestions.push({
                type: 'enable-minify',
                severity: 'high',
                description: `发现 ${unminifiedScripts.length} 个脚本文件未进行代码压缩`,
                affectedAssets: unminifiedScripts.map(a => a.originalName),
                estimatedSavings,
                estimatedSavingsFormatted: StateToReportConverter.formatBytes(estimatedSavings),
                recommendation: '建议启用代码压缩以减小脚本文件大小',
                configExample: `// 在 Vite 配置中启用 minify
build: {
  minify: 'terser', // 或 'esbuild'
}`,
            });
        }
    }
    /**
     * 检测缺少图片压缩
     */
    detectMissingImageCompression() {
        const uncompressedImages = Object.values(this.state.assets).filter(asset => {
            if (asset.type !== 'texture')
                return false;
            // 检查是否应用了图片压缩
            const hasCompression = asset.processingHistory.some(step => step.optimizations.includes('image-compress'));
            return !hasCompression && asset.finalSize > 50 * 1024; // > 50KB
        });
        if (uncompressedImages.length > 0) {
            const totalSize = uncompressedImages.reduce((sum, a) => sum + a.finalSize, 0);
            const estimatedSavings = totalSize * 0.3; // 图片压缩通常可以节省 30%
            this.suggestions.push({
                type: 'enable-image-compression',
                severity: 'medium',
                description: `发现 ${uncompressedImages.length} 个图片未进行压缩`,
                affectedAssets: uncompressedImages.map(a => a.originalName),
                estimatedSavings,
                estimatedSavingsFormatted: StateToReportConverter.formatBytes(estimatedSavings),
                recommendation: '建议启用图片压缩插件以减小图片大小',
                configExample: `// 使用 vite-plugin-imagemin
import viteImagemin from 'vite-plugin-imagemin';

plugins: [
  viteImagemin({
    gifsicle: { optimizationLevel: 7 },
    optipng: { optimizationLevel: 7 },
    mozjpeg: { quality: 80 },
    pngquant: { quality: [0.8, 0.9] },
    svgo: { plugins: [{ name: 'removeViewBox' }] }
  })
]`,
            });
        }
    }
    /**
     * 检测内联限制问题
     */
    detectInlineLimitIssues() {
        const inlinedAssets = Object.values(this.state.assets).filter(asset => {
            const lastStep = asset.processingHistory[asset.processingHistory.length - 1];
            return lastStep?.inlined;
        });
        // 检测过大的内联资源
        const largeInlined = inlinedAssets.filter(a => a.finalSize > 10 * 1024); // > 10KB
        if (largeInlined.length > 0) {
            const totalSize = largeInlined.reduce((sum, a) => sum + a.finalSize, 0);
            const estimatedSavings = totalSize * 0.33; // Base64 编码增加约 33%
            this.suggestions.push({
                type: 'adjust-inline-limit',
                severity: 'medium',
                description: `发现 ${largeInlined.length} 个较大的资源被内联（> 10KB）`,
                affectedAssets: largeInlined.map(a => a.originalName),
                estimatedSavings,
                estimatedSavingsFormatted: StateToReportConverter.formatBytes(estimatedSavings),
                recommendation: '建议降低内联限制，将大文件作为外部资源加载',
                configExample: `// 调整 Vite 的内联限制
build: {
  assetsInlineLimit: 4096, // 4KB
}`,
            });
        }
        // 检测可以内联的小资源
        const notInlined = Object.values(this.state.assets).filter(asset => {
            const lastStep = asset.processingHistory[asset.processingHistory.length - 1];
            return !lastStep?.inlined && asset.finalSize < 4 * 1024; // < 4KB
        });
        if (notInlined.length >= 5) {
            const totalSize = notInlined.reduce((sum, a) => sum + a.finalSize, 0);
            const estimatedSavings = notInlined.length * 500; // 每个文件节省约 500 字节的 HTTP 开销
            this.suggestions.push({
                type: 'adjust-inline-limit',
                severity: 'low',
                description: `发现 ${notInlined.length} 个小资源（< 4KB）未被内联`,
                affectedAssets: notInlined.map(a => a.originalName),
                estimatedSavings,
                estimatedSavingsFormatted: StateToReportConverter.formatBytes(estimatedSavings),
                recommendation: '建议提高内联限制，将小文件内联以减少 HTTP 请求',
                configExample: `// 调整 Vite 的内联限制
build: {
  assetsInlineLimit: 8192, // 8KB
}`,
            });
        }
    }
}
