import fs from 'fs/promises';
import path from 'path';
/**
 * 引擎检测映射表 - 从 package.json 的 dependencies 检测引擎类型
 * 复用后端 ExternalImportService 的逻辑
 */
const ENGINE_DETECTION_MAP = [
    // PlayCanvas - 优先检测（通过文件名而非 package.json）
    { match: (n) => n === 'phaser', engine: 'phaser', priority: 100 },
    { match: (n) => n === 'pixi.js' || n.startsWith('@pixi/'), engine: 'pixijs', priority: 100 },
    { match: (n) => n === 'three', engine: 'threejs', priority: 100 },
    { match: (n) => n === 'cocos-creator' || n === 'cc', engine: 'cocos', priority: 100 },
    { match: (n) => n === 'playcanvas', engine: 'playcanvas', priority: 100 },
    { match: (n) => n === 'babylonjs' || n.startsWith('@babylonjs/'), engine: 'babylonjs', priority: 100 },
    { match: (n) => n.startsWith('laya-') || n.startsWith('@layabox/'), engine: 'layaair', priority: 100 },
    { match: (n) => n === 'egret', engine: 'egret', priority: 100 },
];
/**
 * 构建工具检测映射表 - 优先级高于引擎检测
 * 当检测到特定构建工具或 SDK 时，可以隐含引擎类型和构建工具
 *
 * 注意：@playcraft/devkit 是 PlayCraft 平台内置的构建工具（已集成到 @playcraft/cli）。
 * 用户项目只需依赖 @playcraft/adsdk（运行时 SDK），不需要安装构建工具。
 * 检测到 adsdk 时，自动使用平台内置的 devkit 进行构建。
 */
const BUILD_TOOL_DETECTION_MAP = [
    {
        // 检测 @playcraft/adsdk（运行时 SDK）- 使用平台内置的 devkit 构建
        // 或旧的内部包名 @tencent/playable-sdk
        match: (n) => n === '@playcraft/adsdk' || n === '@tencent/playable-sdk',
        buildTool: 'playable-scripts',
        impliedEngine: 'phaser', // adsdk 项目通常是 Phaser 游戏
        priority: 200, // 高于引擎检测优先级（200 > 100）
    },
    {
        // 向后兼容：检测旧的 devkit 包名（用户项目可能还在使用）
        match: (n) => n === '@playcraft/devkit' || n === '@tencent/playable-scripts',
        buildTool: 'playable-scripts',
        impliedEngine: 'generic',
        priority: 200,
    },
];
/**
 * 引擎检测器
 * 根据项目文件结构自动检测引擎类型和构建工具
 */
export class EngineDetector {
    /**
     * 完整检测：返回引擎类型 + 构建工具的二维检测结果
     * @param projectDir 项目目录
     * @returns 包含 engine 和 buildTool 的检测结果
     */
    static async detectFull(projectDir) {
        // 1. 优先检测 PlayCanvas / PlayCraft 特有文件（最快路径）
        const isPlayCanvas = await this.detectPlayCanvasFiles(projectDir);
        if (isPlayCanvas) {
            return { engine: 'playcanvas', buildTool: 'playcanvas-native' };
        }
        // 2. 检测 package.json
        const pkg = await this.readPackageJson(projectDir);
        if (!pkg) {
            throw new Error(`[EngineDetector] 无法识别项目类型：找不到 package.json 或 PlayCanvas 文件结构\n` +
                `项目目录: ${projectDir}\n` +
                `请确保这是一个有效的项目目录。`);
        }
        // 3. 优先检测构建工具（BUILD_TOOL_DETECTION_MAP，优先级 200）
        const buildToolResult = this.detectBuildToolFromPackageJson(pkg);
        if (buildToolResult) {
            console.log(`[EngineDetector] 检测到构建工具: ${buildToolResult.buildTool}（隐含引擎: ${buildToolResult.engine}）`);
            return buildToolResult;
        }
        // 4. 检测引擎类型（ENGINE_DETECTION_MAP，优先级 100）
        const engine = this.detectFromPackageJson(pkg);
        if (engine) {
            console.log(`[EngineDetector] 检测到引擎: ${engine}（通过 package.json）`);
            return { engine, buildTool: 'generic' };
        }
        // 5. 兜底
        console.log('[EngineDetector] 无法识别具体引擎，使用 generic 类型');
        return { engine: 'generic', buildTool: 'generic' };
    }
    /**
     * 检测项目的引擎类型（向后兼容）
     * @param projectDir 项目目录
     * @returns 引擎类型
     */
    static async detect(projectDir) {
        const result = await this.detectFull(projectDir);
        return result.engine;
    }
    /**
     * 检测 PlayCanvas 特有文件
     */
    static async detectPlayCanvasFiles(projectDir) {
        // 1. 先检查是否是 PlayCraft 项目（manifest.json + format === 'playcraft'）
        //    PlayCraft 项目也有 manifest.json，但不应被识别为 PlayCanvas Web Build
        try {
            const manifestPath = path.join(projectDir, 'manifest.json');
            await fs.access(manifestPath);
            const manifestContent = await fs.readFile(manifestPath, 'utf-8');
            const manifest = JSON.parse(manifestContent);
            if (manifest.format === 'playcraft' || Array.isArray(manifest.assets)) {
                // 这是 PlayCraft 格式项目，仍然属于 PlayCanvas 引擎体系
                console.log('[EngineDetector] 检测到 PlayCraft 项目格式（manifest.json format=playcraft）');
                return true;
            }
        }
        catch {
            // manifest.json 不存在或解析失败，继续其他检测
        }
        // 2. PlayCanvas Web Build 输出文件（构建产物）
        //    这些文件是 PlayCanvas 独有的，不会与其他引擎混淆
        const webBuildIndicators = [
            'config.json',
            '__start__.js',
            '__settings__.js',
        ];
        for (const file of webBuildIndicators) {
            try {
                await fs.access(path.join(projectDir, file));
                console.log(`[EngineDetector] 检测到 PlayCanvas Web Build 文件: ${file}`);
                return true;
            }
            catch {
                // 继续检查下一个
            }
        }
        // 3. PlayCanvas 编辑器导出格式（原始项目数据）
        //    必须同时存在这些文件才算是 PlayCanvas 编辑器项目
        const editorExportIndicators = [
            'assets.json',
            'scenes.json',
            'project.json',
        ];
        let editorExportCount = 0;
        for (const file of editorExportIndicators) {
            try {
                await fs.access(path.join(projectDir, file));
                editorExportCount++;
            }
            catch {
                // 继续检查下一个
            }
        }
        // 如果至少有 2 个编辑器导出文件存在，认为是 PlayCanvas 项目
        if (editorExportCount >= 2) {
            return true;
        }
        return false;
    }
    /**
     * 读取 package.json
     */
    static async readPackageJson(projectDir) {
        try {
            const pkgPath = path.join(projectDir, 'package.json');
            const content = await fs.readFile(pkgPath, 'utf-8');
            return JSON.parse(content);
        }
        catch {
            return null;
        }
    }
    /**
     * 从 package.json 检测构建工具（优先级 200，高于引擎检测）
     */
    static detectBuildToolFromPackageJson(pkg) {
        const allDeps = {
            ...pkg.dependencies,
            ...pkg.devDependencies,
        };
        // 收集所有匹配的构建工具，按优先级排序后返回最高优先级的项
        const matches = [];
        for (const [depName] of Object.entries(allDeps)) {
            for (const { match, buildTool, impliedEngine, priority } of BUILD_TOOL_DETECTION_MAP) {
                if (match(depName)) {
                    matches.push({ engine: impliedEngine, buildTool, priority });
                }
            }
        }
        if (matches.length === 0) {
            return null;
        }
        // 按优先级排序（数字越大优先级越高），返回最高优先级的项
        matches.sort((a, b) => b.priority - a.priority);
        const bestMatch = matches[0];
        return { engine: bestMatch.engine, buildTool: bestMatch.buildTool };
    }
    /**
     * 从 package.json 检测引擎类型
     */
    static detectFromPackageJson(pkg) {
        const allDeps = {
            ...pkg.dependencies,
            ...pkg.devDependencies,
        };
        // 收集所有匹配的引擎
        const matches = [];
        for (const [depName] of Object.entries(allDeps)) {
            for (const { match, engine, priority } of ENGINE_DETECTION_MAP) {
                if (match(depName)) {
                    matches.push({ engine, priority });
                }
            }
        }
        if (matches.length === 0) {
            return null;
        }
        // 按优先级排序，返回最高优先级的引擎
        matches.sort((a, b) => b.priority - a.priority);
        return matches[0].engine;
    }
    /**
     * 强制指定引擎类型（用于手动指定时验证）
     */
    static validateEngine(engine) {
        const validEngines = [
            'playcanvas', 'phaser', 'pixijs', 'threejs',
            'cocos', 'babylonjs', 'layaair', 'egret', 'generic'
        ];
        if (validEngines.includes(engine)) {
            return engine;
        }
        return null;
    }
    /**
     * 获取项目构建命令（从 package.json 的 scripts）
     */
    static async getBuildCommand(projectDir) {
        const pkg = await this.readPackageJson(projectDir);
        if (!pkg || !pkg.scripts) {
            return null;
        }
        // 优先查找常见的 build 命令
        const buildScripts = ['build', 'build:prod', 'build:production', 'dist', 'compile'];
        for (const script of buildScripts) {
            if (pkg.scripts[script]) {
                return script;
            }
        }
        return null;
    }
    /**
     * 检测包管理器（npm/pnpm/yarn）
     */
    static async detectPackageManager(projectDir) {
        // 按优先级检查锁文件
        const lockFiles = [
            { file: 'pnpm-lock.yaml', manager: 'pnpm' },
            { file: 'yarn.lock', manager: 'yarn' },
            { file: 'package-lock.json', manager: 'npm' },
        ];
        for (const { file, manager } of lockFiles) {
            try {
                await fs.access(path.join(projectDir, file));
                return manager;
            }
            catch {
                // 继续检查下一个
            }
        }
        // 默认使用 npm
        return 'npm';
    }
}
