"use strict";
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2024-2026 Gracker (Chris)
// This file is part of SmartPerfetto. See LICENSE for details.
Object.defineProperty(exports, "__esModule", { value: true });
exports.EnhancedSQLTemplateEngine = exports.SQLTemplateEngine = exports.PERFETTO_SQL_TEMPLATES = void 0;
exports.getEnhancedSQLTemplateEngine = getEnhancedSQLTemplateEngine;
/**
 * Perfetto SQL 模板库
 */
exports.PERFETTO_SQL_TEMPLATES = {
    // 1. 应用启动时间
    APP_LAUNCH_TIME: {
        name: 'APP_LAUNCH_TIME',
        sql: `SELECT slice.name AS phase, MIN(slice.ts) / 1e9 AS start_time_s, slice.dur / 1e6 AS duration_ms FROM slice JOIN thread_track ON slice.track_id = thread_track.id JOIN thread USING (utid) JOIN process USING (upid) WHERE process.name = '{app_package}' AND (slice.name = 'activityStart' OR slice.name = 'activityResume') ORDER BY slice.ts ASC;`,
        params: ['app_package'],
        description: '获取应用启动的activityStart和activityResume阶段时间',
        category: 'launch',
        examples: {
            app_package: 'com.example.app'
        }
    },
    // 2. 总启动时间
    TOTAL_LAUNCH_TIME: {
        name: 'TOTAL_LAUNCH_TIME',
        sql: `SELECT MIN(slice.ts) / 1e9 AS launch_start_s, MAX(slice.ts + slice.dur) / 1e9 AS launch_end_s, (MAX(slice.ts + slice.dur) - MIN(slice.ts)) / 1e6 AS total_launch_time_ms FROM slice JOIN thread_track ON slice.track_id = thread_track.id JOIN thread USING (utid) JOIN process USING (upid) WHERE process.name = '{app_package}' AND (slice.name = 'activityStart' OR slice.name = 'activityResume');`,
        params: ['app_package'],
        description: '计算应用的总启动时间',
        category: 'launch',
        examples: {
            app_package: 'com.example.app'
        }
    },
    // 3. Top耗时操作
    TOP_OPERATIONS: {
        name: 'TOP_OPERATIONS',
        sql: `SELECT slice.name AS operation, slice.dur / 1e6 AS duration_ms, slice.ts / 1e9 AS timestamp_s, thread.name AS thread_name FROM slice JOIN thread_track ON slice.track_id = thread_track.id JOIN thread USING (utid) JOIN process USING (upid) WHERE process.name = '{app_package}' AND slice.ts >= {start_ts} AND slice.ts <= {end_ts} AND slice.dur > {min_duration_ns} ORDER BY slice.dur DESC LIMIT {limit};`,
        params: ['app_package', 'start_ts', 'end_ts', 'min_duration_ns', 'limit'],
        description: '获取指定时间范围内的Top耗时操作',
        category: 'general',
        examples: {
            app_package: 'com.example.app',
            start_ts: '40919970000000',
            end_ts: '40920200000000',
            min_duration_ns: '1000000',
            limit: '20'
        }
    },
    // 4. 主线程CPU核心分布
    MAIN_THREAD_CPU_DISTRIBUTION: {
        name: 'MAIN_THREAD_CPU_DISTRIBUTION',
        sql: `SELECT sched.cpu AS cpu_core, COUNT(*) AS schedule_count, SUM(sched.dur) / 1e6 AS total_time_ms, AVG(sched.dur) / 1e6 AS avg_time_ms FROM sched JOIN thread USING (utid) JOIN process USING (upid) WHERE process.name = '{app_package}' AND thread.is_main_thread = 1 AND sched.ts >= {start_ts} AND sched.ts <= {end_ts} GROUP BY sched.cpu ORDER BY sched.cpu;`,
        params: ['app_package', 'start_ts', 'end_ts'],
        description: '分析主线程在各CPU核心上的运行时间分布',
        category: 'cpu',
        examples: {
            app_package: 'com.example.app',
            start_ts: '40919970000000',
            end_ts: '40920200000000'
        }
    },
    // 5. CPU频率分布
    CPU_FREQUENCY_DISTRIBUTION: {
        name: 'CPU_FREQUENCY_DISTRIBUTION',
        sql: `SELECT counter_track.name AS cpu, AVG(counter.value) / 1000000 AS avg_freq_ghz, MIN(counter.value) / 1000000 AS min_freq_ghz, MAX(counter.value) / 1000000 AS max_freq_ghz FROM counter JOIN counter_track ON counter.track_id = counter_track.id WHERE counter_track.name LIKE 'cpufreq%' AND counter.ts >= {start_ts} AND counter.ts <= {end_ts} GROUP BY counter_track.name ORDER BY counter_track.name;`,
        params: ['start_ts', 'end_ts'],
        description: '获取指定时间范围内的CPU频率统计',
        category: 'cpu',
        examples: {
            start_ts: '40919970000000',
            end_ts: '40920200000000'
        }
    },
    // 6. CPU负载
    CPU_LOAD: {
        name: 'CPU_LOAD',
        sql: `SELECT cpu AS cpu_core, COUNT(*) AS total_schedules, SUM(dur) / 1e6 AS total_run_time_ms, ROUND((SUM(dur) * 100.0 / {window_ns}), 2) AS utilization_percent FROM sched WHERE ts >= {start_ts} AND ts <= {end_ts} GROUP BY cpu ORDER BY cpu;`,
        params: ['start_ts', 'end_ts', 'window_ns'],
        description: '分析各CPU核心的负载情况',
        category: 'cpu',
        examples: {
            start_ts: '40919970000000',
            end_ts: '40920200000000',
            window_ns: '230000000'
        }
    },
    // 7. 查找应用的所有slice
    APP_ALL_SLICES: {
        name: 'APP_ALL_SLICES',
        sql: `SELECT slice.name, COUNT(*) AS count, AVG(slice.dur) / 1e6 AS avg_duration_ms, MAX(slice.dur) / 1e6 AS max_duration_ms FROM slice JOIN thread_track ON slice.track_id = thread_track.id JOIN thread USING (utid) JOIN process USING (upid) WHERE process.name = '{app_package}' GROUP BY slice.name HAVING COUNT(*) > {min_count} ORDER BY avg_duration_ms DESC LIMIT {limit};`,
        params: ['app_package', 'min_count', 'limit'],
        description: '获取应用的所有slice及其统计信息',
        category: 'general',
        examples: {
            app_package: 'com.example.app',
            min_count: '5',
            limit: '50'
        }
    },
    // 8. 帧渲染分析
    FRAME_RENDERING: {
        name: 'FRAME_RENDERING',
        sql: `SELECT slice.name, slice.ts / 1e9 AS timestamp_s, slice.dur / 1e6 AS duration_ms FROM slice JOIN thread_track ON slice.track_id = thread_track.id JOIN thread USING (utid) JOIN process USING (upid) WHERE process.name = '{app_package}' AND (slice.name LIKE '%DrawFrame%' OR slice.name LIKE '%Choreographer%') AND slice.ts >= {start_ts} AND slice.ts <= {end_ts} ORDER BY slice.ts ASC;`,
        params: ['app_package', 'start_ts', 'end_ts'],
        description: '分析应用的帧渲染性能',
        category: 'render',
        examples: {
            app_package: 'com.example.app',
            start_ts: '40919970000000',
            end_ts: '40920200000000'
        }
    }
};
/**
 * SQL模板引擎类
 */
class SQLTemplateEngine {
    constructor() {
        this.templates = new Map();
        this.loadTemplates();
    }
    /**
     * 加载所有模板
     */
    loadTemplates() {
        Object.entries(exports.PERFETTO_SQL_TEMPLATES).forEach(([key, template]) => {
            this.templates.set(key, template);
        });
    }
    /**
     * 根据名称获取模板
     */
    getTemplate(name) {
        return this.templates.get(name);
    }
    /**
     * 根据分类获取模板
     */
    getTemplatesByCategory(category) {
        return Array.from(this.templates.values()).filter(t => t.category === category);
    }
    /**
     * 列出所有模板
     */
    listTemplates() {
        return Array.from(this.templates.values());
    }
    /**
     * 渲染模板 - 将参数替换到SQL中
     */
    render(templateName, params) {
        const template = this.getTemplate(templateName);
        if (!template) {
            throw new Error(`Template not found: ${templateName}`);
        }
        // 检查所需参数
        const missingParams = template.params.filter(p => !(p in params));
        if (missingParams.length > 0) {
            throw new Error(`Missing parameters: ${missingParams.join(', ')}`);
        }
        // 替换参数
        let sql = template.sql;
        template.params.forEach(param => {
            const value = params[param];
            sql = sql.replace(new RegExp(`\\{${param}\\}`, 'g'), value.toString());
        });
        return sql;
    }
    /**
     * 智能匹配模板 - 根据用户查询匹配最合适的模板
     */
    matchTemplate(userQuery) {
        const query = userQuery.toLowerCase();
        // 关键词匹配规则
        const matchRules = {
            'APP_LAUNCH_TIME': ['启动时间', '启动阶段', 'launch time', 'activity start'],
            'TOTAL_LAUNCH_TIME': ['总启动时间', '完整启动', 'total launch'],
            'TOP_OPERATIONS': ['耗时操作', '慢操作', 'slow operations', 'top operations'],
            'MAIN_THREAD_CPU_DISTRIBUTION': ['主线程', '核心分布', 'main thread', 'cpu distribution'],
            'CPU_FREQUENCY_DISTRIBUTION': ['cpu频率', 'frequency', '频率分布'],
            'CPU_LOAD': ['cpu负载', 'cpu load', 'cpu utilization'],
            'FRAME_RENDERING': ['帧渲染', '渲染性能', 'frame', 'rendering']
        };
        // 遍历规则，找到匹配的模板
        for (const [templateName, keywords] of Object.entries(matchRules)) {
            if (keywords.some(keyword => query.includes(keyword))) {
                return this.getTemplate(templateName) || null;
            }
        }
        return null;
    }
    /**
     * 验证SQL
     */
    validateSQL(sql) {
        const result = {
            isValid: true,
            errors: [],
            warnings: [],
            suggestions: []
        };
        // 1. 检查是否为空
        if (!sql || sql.trim().length === 0) {
            result.isValid = false;
            result.errors.push('SQL不能为空');
            return result;
        }
        // 2. 检查是否包含多行（trace_processor要求单行）
        if (sql.includes('\n') && sql.split('\n').filter(l => l.trim()).length > 1) {
            result.warnings.push('SQL包含多行，trace_processor可能不支持');
            result.suggestions.push('请将SQL合并为单行');
        }
        // 3. 检查表名
        const validTables = ['slice', 'thread', 'process', 'thread_track', 'sched', 'counter', 'counter_track', 'track'];
        const sqlLower = sql.toLowerCase();
        const invalidTables = ['app_launch', 'performance', 'metrics']; // 常见错误
        invalidTables.forEach(table => {
            if (sqlLower.includes(`from ${table}`) || sqlLower.includes(`join ${table}`)) {
                result.isValid = false;
                result.errors.push(`表 '${table}' 不存在于Perfetto schema中`);
                result.suggestions.push(`可能需要使用 'slice' 或其他有效表: ${validTables.join(', ')}`);
            }
        });
        // 4. 检查时间单位转换
        if (sqlLower.includes('ts') && !sqlLower.includes('/ 1e')) {
            result.warnings.push('时间戳(ts)的单位是纳秒，建议转换单位');
            result.suggestions.push('使用 ts / 1e9 转换为秒，或 ts / 1e6 转换为毫秒');
        }
        if (sqlLower.includes('dur') && !sqlLower.includes('/ 1e')) {
            result.warnings.push('持续时间(dur)的单位是纳秒，建议转换单位');
            result.suggestions.push('使用 dur / 1e6 转换为毫秒，或 dur / 1e9 转换为秒');
        }
        // 5. 检查JOIN语法
        if (sqlLower.includes('join slice') && !sqlLower.includes('thread_track')) {
            result.warnings.push('直接JOIN slice可能缺少中间表');
            result.suggestions.push('slice通常需要通过thread_track -> thread -> process来JOIN');
        }
        // 6. 检查常见字段错误
        if (sqlLower.includes('cpu') && sqlLower.includes('from counter')) {
            result.errors.push('counter表没有cpu字段');
            result.suggestions.push('CPU信息在sched表中，或从counter_track.name中提取');
            result.isValid = false;
        }
        return result;
    }
    /**
     * 尝试修正SQL错误
     */
    suggestFix(sql, error) {
        // 简单的错误修正规则
        let fixed = sql;
        // 修正常见表名错误
        fixed = fixed.replace(/FROM\s+app_launch/gi, 'FROM slice');
        fixed = fixed.replace(/JOIN\s+app_launch/gi, 'JOIN slice');
        // 添加时间单位转换
        if (error.includes('时间戳') || error.includes('timestamp')) {
            fixed = fixed.replace(/SELECT\s+ts\s/gi, 'SELECT ts / 1e9 AS timestamp_s ');
            fixed = fixed.replace(/SELECT\s+dur\s/gi, 'SELECT dur / 1e6 AS duration_ms ');
        }
        return fixed !== sql ? fixed : null;
    }
}
exports.SQLTemplateEngine = SQLTemplateEngine;
// ============================================================================
// 官方 SQL 库集成的增强模板
// ============================================================================
const sqlKnowledgeBase_1 = require("./sqlKnowledgeBase");
/**
 * 增强的 SQL 模板引擎 - 集成官方 SQL 库
 */
class EnhancedSQLTemplateEngine extends SQLTemplateEngine {
    constructor() {
        super();
        this.knowledgeBaseReady = false;
        this.officialTemplates = new Map();
    }
    /**
     * 初始化官方 SQL 库
     */
    async initializeOfficialLibrary() {
        if (this.knowledgeBaseReady)
            return;
        try {
            const kb = await (0, sqlKnowledgeBase_1.getExtendedKnowledgeBase)();
            const categories = kb.getIndexCategories();
            for (const category of categories) {
                const templates = kb.getIndexTemplatesByCategory(category);
                for (const template of templates) {
                    this.officialTemplates.set(template.id, template);
                }
            }
            this.knowledgeBaseReady = true;
            console.log(`EnhancedSQLTemplateEngine: 加载了 ${this.officialTemplates.size} 个官方模板`);
        }
        catch (error) {
            console.error('加载官方 SQL 库失败:', error);
        }
    }
    /**
     * 搜索官方模板
     */
    async searchOfficialTemplates(query, limit = 10) {
        if (!this.knowledgeBaseReady) {
            await this.initializeOfficialLibrary();
        }
        const kb = await (0, sqlKnowledgeBase_1.getExtendedKnowledgeBase)();
        const results = kb.smartMatch(query);
        return results.slice(0, limit).map(r => r.template);
    }
    /**
     * 获取官方推荐 SQL
     */
    async getRecommendedSQL(category) {
        if (!this.knowledgeBaseReady) {
            await this.initializeOfficialLibrary();
        }
        const kb = await (0, sqlKnowledgeBase_1.getExtendedKnowledgeBase)();
        return kb.getRecommendedQueries(category);
    }
    /**
     * 根据用户意图智能匹配（优先官方模板）
     */
    async smartMatchWithOfficial(userQuery) {
        // 1. 检查内置模板
        const builtinTemplate = this.matchTemplate(userQuery);
        // 2. 搜索官方模板
        const officialTemplates = await this.searchOfficialTemplates(userQuery, 5);
        // 3. 获取推荐 SQL
        const category = this.detectCategory(userQuery);
        const recommendedSQL = category ? await this.getRecommendedSQL(category) : [];
        return {
            builtinTemplate,
            officialTemplates,
            recommendedSQL
        };
    }
    /**
     * 检测查询意图对应的分类
     */
    detectCategory(query) {
        const categoryKeywords = {
            'startup': ['启动', 'launch', 'startup', 'start', 'cold', 'warm', 'hot'],
            'frame': ['帧', 'frame', 'jank', '卡顿', 'render', 'choreographer'],
            'cpu': ['cpu', '调度', 'sched', 'frequency', '频率'],
            'memory': ['内存', 'memory', 'heap', 'gc', 'dmabuf'],
            'binder': ['binder', 'ipc', '通信'],
            'battery': ['电池', 'battery', 'power', '功耗'],
            'gpu': ['gpu', 'graphics', '图形'],
            'io': ['io', 'disk', '磁盘', 'file']
        };
        const queryLower = query.toLowerCase();
        for (const [category, keywords] of Object.entries(categoryKeywords)) {
            if (keywords.some(kw => queryLower.includes(kw))) {
                return category;
            }
        }
        return null;
    }
    /**
     * 生成带有 INCLUDE 语句的完整 SQL
     */
    async generateFullSQL(templateId) {
        if (!this.knowledgeBaseReady) {
            await this.initializeOfficialLibrary();
        }
        const kb = await (0, sqlKnowledgeBase_1.getExtendedKnowledgeBase)();
        const fullTemplate = await kb.loadFullTemplate(templateId);
        if (!fullTemplate || !fullTemplate.sql) {
            return null;
        }
        return fullTemplate.sql;
    }
    /**
     * 获取为 AI 生成 SQL 提供的上下文
     */
    async getAIContext(query) {
        if (!this.knowledgeBaseReady) {
            await this.initializeOfficialLibrary();
        }
        const kb = await (0, sqlKnowledgeBase_1.getExtendedKnowledgeBase)();
        return kb.getContextForAI(query, 5);
    }
    /**
     * 列出所有分类
     */
    async listCategories() {
        if (!this.knowledgeBaseReady) {
            await this.initializeOfficialLibrary();
        }
        const kb = await (0, sqlKnowledgeBase_1.getExtendedKnowledgeBase)();
        return kb.getIndexCategories();
    }
    /**
     * 获取分类下的模板列表
     */
    async getTemplatesByOfficialCategory(category) {
        if (!this.knowledgeBaseReady) {
            await this.initializeOfficialLibrary();
        }
        const kb = await (0, sqlKnowledgeBase_1.getExtendedKnowledgeBase)();
        return kb.getIndexTemplatesByCategory(category);
    }
    /**
     * 获取统计信息
     */
    async getStats() {
        if (!this.knowledgeBaseReady) {
            await this.initializeOfficialLibrary();
        }
        const kb = await (0, sqlKnowledgeBase_1.getExtendedKnowledgeBase)();
        const stats = kb.getIndexStats();
        return {
            builtinTemplates: this.listTemplates().length,
            officialTemplates: stats?.totalTemplates || 0,
            categories: kb.getIndexCategories()
        };
    }
}
exports.EnhancedSQLTemplateEngine = EnhancedSQLTemplateEngine;
// 单例实例
let enhancedEngineInstance = null;
async function getEnhancedSQLTemplateEngine() {
    if (!enhancedEngineInstance) {
        enhancedEngineInstance = new EnhancedSQLTemplateEngine();
        await enhancedEngineInstance.initializeOfficialLibrary();
    }
    return enhancedEngineInstance;
}
exports.default = SQLTemplateEngine;
//# sourceMappingURL=sqlTemplateEngine.js.map