import axios from 'axios';
import * as fs from 'fs';
import { createWriteStream } from 'fs';
import * as path from 'path';
import { zipToolsManager } from '../../../utils/zipToolsManager.js';
export class TModDownloader {
    constructor(options = {}) {
        this.githubApiUrl = 'https://api.github.com/repos/tModLoader/tModLoader/releases/latest';
        this.fileName = 'tmodloader.zip';
        this.cancelled = false;
        const baseDownloadDir = options.downloadDir || process.cwd();
        const baseExtractDir = options.extractDir || path.join(baseDownloadDir, 'tmodloader');
        this.options = {
            downloadDir: baseDownloadDir,
            extractDir: baseExtractDir,
            deleteAfterExtract: options.deleteAfterExtract ?? true,
            clearExtractDir: options.clearExtractDir ?? false,
            createVersionDir: options.createVersionDir ?? false
        };
    }
    async getLatestReleaseInfo() {
        try {
            const response = await axios.get(this.githubApiUrl);
            const assets = response.data.assets;
            const version = response.data.tag_name || 'unknown';
            const patterns = [
                /tmodloader.*server.*\.zip$/i,
                /tmodloader.*\.zip$/i,
                /.*server.*\.zip$/i,
                /^(?!.*example).*\.zip$/i
            ];
            for (const pattern of patterns) {
                const asset = assets.find((asset) => pattern.test(asset.name));
                if (asset) {
                    return { downloadUrl: asset.browser_download_url, version };
                }
            }
            const zipAsset = assets.find((asset) => asset.name.endsWith('.zip') &&
                !asset.name.toLowerCase().includes('example'));
            if (zipAsset) {
                return { downloadUrl: zipAsset.browser_download_url, version };
            }
            throw new Error('未找到可下载的zip文件');
        }
        catch (error) {
            throw new Error(`获取最新版本失败: ${error}`);
        }
    }
    async getLatestDownloadUrl() {
        const { downloadUrl } = await this.getLatestReleaseInfo();
        return downloadUrl;
    }
    clearDirectory(dirPath) {
        if (fs.existsSync(dirPath)) {
            const files = fs.readdirSync(dirPath);
            for (const file of files) {
                const filePath = path.join(dirPath, file);
                const stat = fs.statSync(filePath);
                if (stat.isDirectory()) {
                    this.clearDirectory(filePath);
                    fs.rmdirSync(filePath);
                }
                else {
                    fs.unlinkSync(filePath);
                }
            }
            console.log(`已清空目录: ${dirPath}`);
        }
    }
    getFinalExtractDir(version) {
        let extractDir = this.options.extractDir;
        if (this.options.createVersionDir && version) {
            const cleanVersion = version.replace(/^v/, '');
            extractDir = path.join(extractDir, cleanVersion);
        }
        return extractDir;
    }
    async getLatestDownloadUrlLegacy() {
        try {
            const response = await axios.get(this.githubApiUrl);
            const assets = response.data.assets;
            const patterns = [
                /tmodloader.*server.*\.zip$/i,
                /tmodloader.*\.zip$/i,
                /.*server.*\.zip$/i,
                /^(?!.*example).*\.zip$/i
            ];
            for (const pattern of patterns) {
                const asset = assets.find((asset) => pattern.test(asset.name));
                if (asset) {
                    return asset.browser_download_url;
                }
            }
            const zipAsset = assets.find((asset) => asset.name.endsWith('.zip') &&
                !asset.name.toLowerCase().includes('example'));
            if (zipAsset) {
                return zipAsset.browser_download_url;
            }
            throw new Error('未找到可下载的zip文件');
        }
        catch (error) {
            throw new Error(`获取最新版本失败: ${error}`);
        }
    }
    cancel() {
        this.cancelled = true;
        if (this.currentDownloadController) {
            this.currentDownloadController.abort();
        }
        this.cleanupDirectory().catch(() => {
        });
        console.log('tModLoader下载已取消');
    }
    isCancelled() {
        return this.cancelled;
    }
    async downloadFile(url, filePath) {
        try {
            this.currentDownloadController = new AbortController();
            const response = await axios({
                method: 'GET',
                url: url,
                responseType: 'stream',
                signal: this.currentDownloadController.signal
            });
            if (this.cancelled) {
                throw new Error('操作已取消');
            }
            await new Promise((resolve, reject) => {
                const writeStream = createWriteStream(filePath);
                response.data.pipe(writeStream);
                writeStream.on('finish', () => resolve());
                writeStream.on('error', (error) => reject(error));
                response.data.on('error', (error) => reject(error));
            });
            if (this.cancelled) {
                throw new Error('操作已取消');
            }
        }
        catch (error) {
            if (this.cancelled || error?.code === 'ABORT_ERR') {
                throw new Error('操作已取消');
            }
            throw new Error(`下载文件失败: ${error}`);
        }
    }
    async extractZip(zipPath, extractPath) {
        if (this.cancelled) {
            throw new Error('操作已取消');
        }
        await zipToolsManager.extractZip(zipPath, extractPath);
    }
    checkAndDeleteExistingZip(filePath) {
        if (fs.existsSync(filePath)) {
            fs.unlinkSync(filePath);
            console.log(`已删除现有文件: ${filePath}`);
        }
    }
    async downloadAndExtract() {
        this.cancelled = false;
        const zipPath = path.join(this.options.downloadDir, this.fileName);
        try {
            if (this.cancelled) {
                throw new Error('操作已取消');
            }
            console.log('开始获取最新版本信息...');
            const { downloadUrl, version } = await this.getLatestReleaseInfo();
            console.log(`找到版本: ${version}`);
            console.log(`找到下载地址: ${downloadUrl}`);
            if (this.cancelled) {
                throw new Error('操作已取消');
            }
            const finalExtractDir = this.getFinalExtractDir(version);
            console.log(`解压目录: ${finalExtractDir}`);
            this.checkAndDeleteExistingZip(zipPath);
            if (!fs.existsSync(this.options.downloadDir)) {
                fs.mkdirSync(this.options.downloadDir, { recursive: true });
            }
            if (this.options.clearExtractDir) {
                this.clearDirectory(finalExtractDir);
            }
            if (!fs.existsSync(finalExtractDir)) {
                fs.mkdirSync(finalExtractDir, { recursive: true });
            }
            if (this.cancelled) {
                throw new Error('操作已取消');
            }
            console.log(`开始下载到: ${zipPath}`);
            await this.downloadFile(downloadUrl, zipPath);
            console.log('下载完成');
            if (this.cancelled) {
                throw new Error('操作已取消');
            }
            console.log(`开始解压到: ${finalExtractDir}`);
            await this.extractZip(zipPath, finalExtractDir);
            console.log('解压完成');
            if (this.cancelled) {
                throw new Error('操作已取消');
            }
            if (this.options.deleteAfterExtract) {
                fs.unlinkSync(zipPath);
                console.log('压缩包已删除');
            }
            await this.cleanupDirectory();
            console.log(`tModLoader服务端 ${version} 下载和解压完成！`);
            console.log(`服务端位置: ${finalExtractDir}`);
        }
        catch (error) {
            if (fs.existsSync(zipPath)) {
                fs.unlinkSync(zipPath);
            }
            throw error;
        }
    }
    getOptions() {
        return { ...this.options };
    }
    updateOptions(options) {
        const newDownloadDir = options.downloadDir || this.options.downloadDir;
        const newExtractDir = options.extractDir ||
            (options.downloadDir ? path.join(newDownloadDir, 'tmodloader') : this.options.extractDir);
        this.options = {
            ...this.options,
            ...options,
            downloadDir: newDownloadDir,
            extractDir: newExtractDir
        };
    }
    async getVersionInfo() {
        return await this.getLatestReleaseInfo();
    }
    setExtractDir(extractDir) {
        this.options.extractDir = path.resolve(extractDir);
    }
    async getCurrentExtractDir() {
        if (this.options.createVersionDir) {
            const { version } = await this.getLatestReleaseInfo();
            return this.getFinalExtractDir(version);
        }
        return this.options.extractDir;
    }
    async cleanupDirectory() {
        try {
            const zipPath = path.join(this.options.downloadDir, this.fileName);
            if (fs.existsSync(zipPath)) {
                fs.unlinkSync(zipPath);
                console.log(`已清理临时文件: ${zipPath}`);
            }
            if (this.options.downloadDir.includes('temp') || this.options.downloadDir.includes('tmp')) {
                try {
                    const files = fs.readdirSync(this.options.downloadDir);
                    if (files.length === 0) {
                        fs.rmdirSync(this.options.downloadDir);
                        console.log(`已清理临时目录: ${this.options.downloadDir}`);
                    }
                }
                catch (error) {
                }
            }
        }
        catch (error) {
            console.warn('清理临时文件时出错:', error);
        }
    }
}
export async function downloadTModLoader(options = {}) {
    const downloader = new TModDownloader(options);
    await downloader.downloadAndExtract();
}
export async function getLatestTModLoaderInfo() {
    const downloader = new TModDownloader();
    return await downloader.getVersionInfo();
}
