const fs = require('fs-extra');
const path = require('path');
const { syncSystemSubtitleSources } = require('./sync-system-subtitle-sources.cjs');

async function preparePackage() {
    console.log('📦 开始准备打包资源...\n');
    console.log('='.repeat(60));

    const extraDir = path.join(__dirname, '../electron/resources/extra');
    const commonDir = path.join(extraDir, 'common');

    // 0. 发布前同步系统字幕模板，避免安装包带入旧候选模板或旧音效配置
    console.log('\n0锔忊儯 鍚屾绯荤粺瀛楀箷妯℃澘...');
    const syncResult = syncSystemSubtitleSources();
    console.log(`   鉁?宸插悓姝? ${syncResult.count} 涓郴缁熷瓧骞曟ā鏉垮埌鍙戝竷閰嶇疆\n`);

    // 1. 确保目录存在
    console.log('\n1️⃣ 确保目录结构存在...');
    await fs.ensureDir(path.join(commonDir, 'python'));
    await fs.ensureDir(path.join(commonDir, 'chromium'));
    await fs.ensureDir(path.join(commonDir, 'python-scripts'));
    await fs.ensureDir(path.join(commonDir, 'models'));
    await fs.ensureDir(path.join(commonDir, 'fonts'));
    await fs.ensureDir(path.join(commonDir, 'bgm'));
    await fs.ensureDir(path.join(commonDir, 'demo'));
    await fs.ensureDir(path.join(commonDir, 'config'));
    await fs.ensureDir(path.join(commonDir, 'cover-templates'));
    await fs.ensureDir(path.join(extraDir, 'win-x86'));
    console.log('   ✅ 目录结构准备完成\n');

    // 2. 复制 Python 脚本
    console.log('2️⃣ 复制 Python 脚本...');
    const pythonSrc = path.join(__dirname, '../python');
    const pythonDest = path.join(commonDir, 'python-scripts');
    const pythonFilter = (src) => {
        const normalizedSrc = src.replace(/\\/g, '/');
        const fileName = path.basename(normalizedSrc).toLowerCase();

        if (normalizedSrc.includes('/__pycache__/') || fileName.endsWith('.pyc')) {
            return false;
        }

        if (
            fileName.includes('.backup') ||
            fileName.endsWith('.bak') ||
            fileName.includes('backup_') ||
            fileName.startsWith('test_')
        ) {
            return false;
        }

        return true;
    };

    if (fs.existsSync(pythonSrc)) {
        await copyWithLockTolerance(pythonSrc, pythonDest, {
            overwrite: true,
            filter: pythonFilter
        });
        const fileCount = await countFiles(pythonDest);
        console.log(`   ✅ Python 脚本复制到 python-scripts 完成 (${fileCount} 个文件)`);

        const pythonRuntimeDir = path.join(commonDir, 'python');
        await copyWithLockTolerance(pythonSrc, pythonRuntimeDir, {
            overwrite: true,
            filter: pythonFilter
        });
        console.log(`   ✅ Python 脚本复制到 python 运行时目录完成\n`);
    } else {
        console.log('   ⚠️  Python 脚本目录不存在，跳过\n');
    }

    // 3. 复制字体
    console.log('3️⃣ 复制字体文件...');
    const fontSrc = path.join(__dirname, '../ziti');
    const fontDest = path.join(commonDir, 'fonts/ziti');

    if (fs.existsSync(fontSrc)) {
        if (process.env.OEM_BATCH_BUILD === '1' && await fs.pathExists(fontDest)) {
            const existingFileCount = await countFiles(fontDest);
            if (existingFileCount > 0) {
                console.log(`   [SKIP] OEM batch build reuses prepared fonts (${existingFileCount} files)\n`);
            } else {
                await copyWithLockTolerance(fontSrc, fontDest, { overwrite: true });
            }
        } else {
            const sourceFileCount = await countFiles(fontSrc);
            const sourceTotalSize = await getDirSize(fontSrc);
            const destReady = await fs.pathExists(fontDest)
                && await countFiles(fontDest) === sourceFileCount
                && await getDirSize(fontDest) === sourceTotalSize;

            if (destReady) {
                console.log(`   [SKIP] Fonts already prepared (${sourceFileCount} files, ${(sourceTotalSize / 1024 / 1024).toFixed(2)} MB)\n`);
            } else {
                await copyWithLockTolerance(fontSrc, fontDest, { overwrite: true });
            }
        }
        const fileCount = await countFiles(fontDest);
        const totalSize = await getDirSize(fontDest);
        console.log(`   ✅ 字体复制完成 (${fileCount} 个文件, ${(totalSize / 1024 / 1024).toFixed(2)} MB)\n`);
    } else {
        console.log('   ⚠️  字体目录不存在，跳过\n');
    }

    // 4. 复制 BGM
    console.log('4️⃣ 复制背景音乐...');
    const bgmSrc = path.join(__dirname, '../bgm');
    const bgmDest = path.join(commonDir, 'bgm');

    if (fs.existsSync(bgmSrc)) {
        if (process.env.OEM_BATCH_BUILD === '1' && await fs.pathExists(bgmDest)) {
            const existingFileCount = await countFiles(bgmDest);
            if (existingFileCount > 0) {
                console.log(`   [SKIP] OEM batch build reuses prepared BGM (${existingFileCount} files)\n`);
            } else {
                await copyWithLockTolerance(bgmSrc, bgmDest, { overwrite: true });
            }
        } else {
            await copyWithLockTolerance(bgmSrc, bgmDest, { overwrite: true });
        }
        const fileCount = await countFiles(bgmDest);
        const totalSize = await getDirSize(bgmDest);
        console.log(`   ✅ BGM 复制完成 (${fileCount} 个文件, ${(totalSize / 1024 / 1024).toFixed(2)} MB)\n`);
    } else {
        console.log('   ⚠️  BGM 目录不存在，跳过\n');
    }

    // 5. 复制 Demo
    console.log('5️⃣ 复制演示文件...');
    const demoSrc = path.join(__dirname, '../demo');
    const demoDest = path.join(commonDir, 'demo');

    if (fs.existsSync(demoSrc)) {
        if (process.env.OEM_BATCH_BUILD === '1' && await fs.pathExists(demoDest)) {
            const existingFileCount = await countFiles(demoDest);
            if (existingFileCount > 0) {
                console.log(`   [SKIP] OEM batch build reuses prepared Demo (${existingFileCount} files)\n`);
            } else {
                await copyWithLockTolerance(demoSrc, demoDest, { overwrite: true });
            }
        } else {
            await copyWithLockTolerance(demoSrc, demoDest, { overwrite: true });
        }
        const fileCount = await countFiles(demoDest);
        const totalSize = await getDirSize(demoDest);
        console.log(`   ✅ Demo 复制完成 (${fileCount} 个文件, ${(totalSize / 1024 / 1024).toFixed(2)} MB)\n`);
    } else {
        console.log('   ⚠️  Demo 目录不存在，跳过\n');
    }

    // 6. 复制配置文件
    console.log('6️⃣ 复制配置文件...');
    const configDest = path.join(commonDir, 'config');

    const configFiles = [
        {
            src: path.join(__dirname, '../electron/config/default-templates.json'),
            dest: path.join(configDest, 'default-templates.json'),
            name: 'default-templates.json'
        },
        {
            src: path.join(__dirname, '../electron/config/default-subtitle-templates.json'),
            dest: path.join(configDest, 'default-subtitle-templates.json'),
            name: 'default-subtitle-templates.json'
        },
        {
            src: path.join(__dirname, '../python/preset_templates.json'),
            dest: path.join(configDest, 'preset_templates.json'),
            name: 'preset_templates.json'
        },
        {
            src: path.join(__dirname, '../electron/config/default-ipagent-config.json'),
            dest: path.join(configDest, 'default-ipagent-config.json'),
            name: 'default-ipagent-config.json'
        },
        {
            src: path.join(__dirname, '../electron/resources/extra/common/config/system-templates.json'),
            dest: path.join(configDest, 'system-templates.json'),
            name: 'system-templates.json (系统模板配置 - 8套字幕+8套封面)'
        }
    ];

    let copiedCount = 0;
    for (const file of configFiles) {
        if (fs.existsSync(file.src)) {
            const samePath = path.resolve(file.src) === path.resolve(file.dest);
            if (samePath) {
                const size = (await fs.stat(file.src)).size;
                console.log(`   ℹ️  ${file.name} 已在目标位置 (${(size / 1024).toFixed(2)} KB)`);
                copiedCount++;
                continue;
            }
            await copyWithLockTolerance(file.src, file.dest, { overwrite: true });
            const size = (await fs.stat(file.dest)).size;
            console.log(`   ✅ ${file.name} (${(size / 1024).toFixed(2)} KB)`);
            copiedCount++;
        } else {
            console.log(`   ⚠️  ${file.name} - 源文件不存在`);
        }
    }
    console.log(`   📊 配置文件复制完成 (${copiedCount}/${configFiles.length})\n`);

    // 7. 检查外部依赖
    console.log('7️⃣ 检查外部依赖...');

    // FFmpeg DLL 文件列表
    const ffmpegDlls = [
        'avcodec-61.dll',
        'avdevice-61.dll',
        'avfilter-10.dll',
        'avformat-61.dll',
        'avutil-59.dll',
        'postproc-58.dll',
        'swresample-5.dll',
        'swscale-8.dll'
    ];

    // 动态查找最新的 Playwright Chromium 版本
    const playwrightDir = path.join(commonDir, 'playwright');
    let playwrightChromiumCheck = null;
    if (await fs.pathExists(playwrightDir)) {
        const chromiumDirs = (await fs.readdir(playwrightDir))
            .filter(f => f.startsWith('chromium-'))
            .sort()
            .reverse();
        if (chromiumDirs.length > 0) {
            const latestChromium = chromiumDirs[0];
            const chromePath = path.join(playwrightDir, latestChromium, 'chrome-win64/chrome.exe');
            const chromePathAlt = path.join(playwrightDir, latestChromium, 'chrome-win/chrome.exe');
            playwrightChromiumCheck = {
                name: `Playwright Chromium (${latestChromium})`,
                path: await fs.pathExists(chromePath) ? chromePath : chromePathAlt
            };
        }
    }

    const checks = [
        { name: 'Python 环境', path: path.join(commonDir, 'python/python.exe') },
        { name: 'Python 依赖 (opencv)', path: path.join(commonDir, 'python/Lib/site-packages/cv2') },
        { name: 'FFmpeg (win-x86)', path: path.join(extraDir, 'win-x86/ffmpeg.exe') },
        { name: 'FFprobe (win-x86)', path: path.join(extraDir, 'win-x86/ffprobe.exe') },
        ...ffmpegDlls.map(dll => ({ name: `FFmpeg DLL (${dll})`, path: path.join(extraDir, `win-x86/${dll}`) })),
        ...(playwrightChromiumCheck ? [playwrightChromiumCheck] : []),
        { name: 'U2-Net 模型', path: path.join(commonDir, 'models/u2net.onnx') },
    ];

    let allOk = true;
    for (const check of checks) {
        const exists = await fs.pathExists(check.path);
        if (exists) {
            console.log(`   ✅ ${check.name}`);
        } else {
            console.log(`   ❌ ${check.name} - 缺失`);
            allOk = false;
        }
    }

    console.log('\n' + '='.repeat(60));

    if (!allOk) {
        console.log('⚠️  警告：某些外部依赖缺失');
        console.log('\n请先运行: node scripts/download-dependencies.js');
        console.log('参考文档: C:\\aigcpanel-main\\打包方案.md 的 "阶段 1: 准备外部依赖"\n');
        console.log('='.repeat(60));
        process.exit(1);
    } else {
        console.log('✅ 所有资源准备完成！可以开始打包了');
        console.log('\n下一步:');
        console.log('  npm run build:win    # 开始打包 Windows 版本');
        console.log('  npm run build:mac    # 开始打包 macOS 版本');
        console.log('\n📝 字幕模板说明:');
        console.log('  系统默认字幕模板配置:');
        console.log('  • 位置: electron/config/default-subtitle-templates.json');
        console.log('  • 功能: 包含所有参数（普通字幕、关键词特效、标题字幕、音效）');
        console.log('\n导出字幕模板功能:');
        console.log('  • 用户在应用中导出字幕模板为 JSON 文件');
        console.log('  • 其他用户可通过导入功能导入这些 JSON 文件');
        console.log('  • 支持备份、分享、版本控制');
        console.log('\n='.repeat(60));
    }
}

async function copyWithLockTolerance(src, dest, options = {}) {
    try {
        await fs.copy(src, dest, options);
        return true;
    } catch (error) {
        if (error && error.code === 'EPERM') {
            console.warn(`   ⚠️ 跳过被占用的复制目标: ${dest}`);
            console.warn(`      原因: ${error.message}`);
            return false;
        }
        throw error;
    }
}

// 辅助函数：统计文件数量
async function countFiles(dir) {
    let count = 0;

    async function walk(directory) {
        const files = await fs.readdir(directory);
        for (const file of files) {
            const filePath = path.join(directory, file);
            const stat = await fs.stat(filePath);
            if (stat.isDirectory()) {
                await walk(filePath);
            } else {
                count++;
            }
        }
    }

    if (await fs.pathExists(dir)) {
        await walk(dir);
    }

    return count;
}

// 辅助函数：计算目录大小
async function getDirSize(dir) {
    let size = 0;

    async function walk(directory) {
        const files = await fs.readdir(directory);
        for (const file of files) {
            const filePath = path.join(directory, file);
            const stat = await fs.stat(filePath);
            if (stat.isDirectory()) {
                await walk(filePath);
            } else {
                size += stat.size;
            }
        }
    }

    if (await fs.pathExists(dir)) {
        await walk(dir);
    }

    return size;
}

preparePackage().catch(console.error);
