import { createWriteStream, createReadStream } from 'fs';
import { promises as fs } from 'fs';
import * as path from 'path';
import * as tar from 'tar';
import * as zlib from 'zlib';
import { taskManager } from './taskManager.js';
import { createTarSecurityFilter } from '../../utils/tarSecurityFilter.js';
import { zipToolsManager } from '../../utils/zipToolsManager.js';
export class CompressionWorker {
    async compressFiles(taskId, sourcePaths, archivePath, format, compressionLevel) {
        try {
            taskManager.updateTask(taskId, {
                status: 'running',
                message: '开始压缩文件...',
                progress: 0
            });
            if (format === 'zip') {
                await this.compressZip(taskId, sourcePaths, archivePath, compressionLevel);
            }
            else if (format === 'tar') {
                await this.compressTar(taskId, sourcePaths, archivePath);
            }
            else if (format === 'tar.gz') {
                await this.compressTarGz(taskId, sourcePaths, archivePath, compressionLevel);
            }
            else if (format === 'tar.xz') {
                await this.compressTarXz(taskId, sourcePaths, archivePath, compressionLevel);
            }
            else if (format === '7z') {
                await this.compress7z(taskId, sourcePaths, archivePath);
            }
            else {
                throw new Error(`不支持的压缩格式: ${format}`);
            }
            taskManager.updateTask(taskId, {
                status: 'completed',
                message: '压缩完成',
                progress: 100
            });
        }
        catch (error) {
            taskManager.updateTask(taskId, {
                status: 'failed',
                message: `压缩失败: ${error.message}`,
                progress: 0
            });
            throw error;
        }
    }
    async compressZip(taskId, sourcePaths, archivePath, compressionLevel) {
        taskManager.updateTask(taskId, {
            message: '正在使用 Zip-Tools 压缩...',
            progress: 5
        });
        const cwd = path.dirname(sourcePaths[0]);
        const files = sourcePaths.map(p => path.relative(cwd, p));
        await zipToolsManager.compressZip(archivePath, files, cwd);
    }
    async compressTar(taskId, sourcePaths, archivePath) {
        taskManager.updateTask(taskId, {
            message: '正在创建TAR归档...',
            progress: 10
        });
        const relativePaths = sourcePaths.map(p => path.basename(p));
        await tar.create({
            f: archivePath,
            cwd: path.dirname(sourcePaths[0])
        }, relativePaths);
    }
    async compressTarGz(taskId, sourcePaths, archivePath, compressionLevel) {
        taskManager.updateTask(taskId, {
            message: '正在创建TAR.GZ压缩包...',
            progress: 10
        });
        const relativePaths = sourcePaths.map(p => path.basename(p));
        await tar.create({
            f: archivePath,
            z: true,
            cwd: path.dirname(sourcePaths[0])
        }, relativePaths);
    }
    async compressTarXz(taskId, sourcePaths, archivePath, compressionLevel) {
        taskManager.updateTask(taskId, {
            message: '正在创建TAR.XZ压缩包...',
            progress: 10
        });
        const tempTarPath = archivePath.replace('.tar.xz', '.tar');
        try {
            const relativePaths = sourcePaths.map(p => path.basename(p));
            await tar.create({
                f: tempTarPath,
                cwd: path.dirname(sourcePaths[0])
            }, relativePaths);
            taskManager.updateTask(taskId, {
                message: '正在进行XZ压缩...',
                progress: 60
            });
            await new Promise((resolve, reject) => {
                const readStream = createReadStream(tempTarPath);
                const writeStream = createWriteStream(archivePath);
                const compressStream = zlib.createGzip({ level: compressionLevel });
                readStream
                    .pipe(compressStream)
                    .pipe(writeStream)
                    .on('finish', () => {
                    fs.unlink(tempTarPath).catch(console.error);
                    resolve();
                })
                    .on('error', reject);
            });
        }
        catch (error) {
            try {
                await fs.unlink(tempTarPath);
            }
            catch { }
            throw error;
        }
    }
    async extractArchive(taskId, archivePath, targetPath) {
        try {
            taskManager.updateTask(taskId, {
                status: 'running',
                message: '开始解压文件...',
                progress: 0
            });
            const ext = path.extname(archivePath).toLowerCase();
            const fileName = path.basename(archivePath).toLowerCase();
            await fs.mkdir(targetPath, { recursive: true });
            if (ext === '.zip') {
                await this.extractZip(taskId, archivePath, targetPath);
            }
            else if (ext === '.7z') {
                await this.extract7z(taskId, archivePath, targetPath);
            }
            else if (ext === '.tar') {
                await this.extractTar(taskId, archivePath, targetPath);
            }
            else if (fileName.endsWith('.tar.gz') || fileName.endsWith('.tgz')) {
                await this.extractTarGz(taskId, archivePath, targetPath);
            }
            else if (fileName.endsWith('.tar.xz') || fileName.endsWith('.txz')) {
                await this.extractTarXz(taskId, archivePath, targetPath);
            }
            else {
                throw new Error(`不支持的压缩格式: ${ext}。支持的格式: .zip, .7z, .tar, .tar.gz, .tar.xz`);
            }
            taskManager.updateTask(taskId, {
                status: 'completed',
                message: '解压完成',
                progress: 100
            });
        }
        catch (error) {
            taskManager.updateTask(taskId, {
                status: 'failed',
                message: `解压失败: ${error.message}`,
                progress: 0
            });
            throw error;
        }
    }
    async extractZip(taskId, archivePath, targetPath) {
        taskManager.updateTask(taskId, {
            message: '正在使用 Zip-Tools 解压...',
            progress: 10
        });
        await zipToolsManager.extractZip(archivePath, targetPath);
    }
    async compress7z(taskId, sourcePaths, archivePath) {
        taskManager.updateTask(taskId, {
            message: '正在使用 7z 压缩...',
            progress: 5
        });
        const cwd = path.dirname(sourcePaths[0]);
        const files = sourcePaths.map(p => path.relative(cwd, p));
        await zipToolsManager.compress7z(archivePath, files, cwd);
    }
    async extract7z(taskId, archivePath, targetPath) {
        taskManager.updateTask(taskId, {
            message: '正在使用 7z 解压...',
            progress: 10
        });
        await zipToolsManager.extract7z(archivePath, targetPath);
    }
    async extractTar(taskId, archivePath, targetPath) {
        taskManager.updateTask(taskId, {
            message: '正在解压TAR归档...',
            progress: 10
        });
        await tar.extract({
            file: archivePath,
            cwd: targetPath,
            filter: createTarSecurityFilter({ cwd: targetPath }),
            onentry: (entry) => {
                taskManager.updateTask(taskId, {
                    message: `正在解压: ${entry.path}`,
                    progress: Math.min(90, Math.random() * 80 + 10)
                });
            }
        });
    }
    async extractTarGz(taskId, archivePath, targetPath) {
        taskManager.updateTask(taskId, {
            message: '正在解压TAR.GZ压缩包...',
            progress: 10
        });
        await tar.extract({
            file: archivePath,
            cwd: targetPath,
            gzip: true,
            filter: createTarSecurityFilter({ cwd: targetPath }),
            onentry: (entry) => {
                taskManager.updateTask(taskId, {
                    message: `正在解压: ${entry.path}`,
                    progress: Math.min(90, Math.random() * 80 + 10)
                });
            }
        });
    }
    async extractTarXz(taskId, archivePath, targetPath) {
        taskManager.updateTask(taskId, {
            message: '正在解压TAR.XZ压缩包...',
            progress: 10
        });
        const tempTarPath = archivePath.replace(/\.(tar\.xz|txz)$/, '.tar');
        try {
            taskManager.updateTask(taskId, {
                message: '正在解压XZ压缩...',
                progress: 20
            });
            await new Promise((resolve, reject) => {
                const readStream = createReadStream(archivePath);
                const writeStream = createWriteStream(tempTarPath);
                const decompressStream = zlib.createGunzip();
                readStream
                    .pipe(decompressStream)
                    .pipe(writeStream)
                    .on('finish', resolve)
                    .on('error', reject);
            });
            taskManager.updateTask(taskId, {
                message: '正在解压TAR归档...',
                progress: 50
            });
            await tar.extract({
                file: tempTarPath,
                cwd: targetPath,
                filter: createTarSecurityFilter({ cwd: targetPath }),
                onentry: (entry) => {
                    taskManager.updateTask(taskId, {
                        message: `正在解压: ${entry.path}`,
                        progress: Math.min(90, Math.random() * 40 + 50)
                    });
                }
            });
            await fs.unlink(tempTarPath);
        }
        catch (error) {
            try {
                await fs.unlink(tempTarPath);
            }
            catch { }
            throw error;
        }
    }
}
export const compressionWorker = new CompressionWorker();
