import path from 'path';
import fs from 'fs-extra';
import os from 'os';
import axios from 'axios';
import logger from '../../utils/logger.js';
import { spawn } from 'child_process';
export class DirectXManager {
    constructor() {
        this.installDir = path.join(process.cwd(), 'data', 'directx');
    }
    async ensureInstallDir() {
        await fs.ensureDir(this.installDir);
    }
    getVersionDir(version) {
        return path.join(this.installDir, version);
    }
    async checkDirectXInstalled() {
        if (os.platform() !== 'win32') {
            return false;
        }
        logger.info('开始检查DirectX 9.0c运行时组件...');
        await this.checkDirectXWithDxdiag();
        const dllCheck = await this.checkDirectXDLLs();
        if (dllCheck) {
            logger.info('DirectX 9.0c运行时组件检测：已安装');
            return true;
        }
        logger.info('DirectX 9.0c运行时组件检测：未安装');
        logger.info('说明：系统可能有DirectX 12，但缺少DirectX 9.0c特有的运行时文件');
        return false;
    }
    async checkDirectXWithDxdiag() {
        return new Promise((resolve) => {
            try {
                const tempFile = path.join(os.tmpdir(), `dxdiag_${Date.now()}.txt`);
                const child = spawn('dxdiag', ['/t', tempFile], {
                    windowsHide: true,
                    stdio: 'pipe'
                });
                child.on('close', async (code) => {
                    try {
                        if (code === 0 && await fs.pathExists(tempFile)) {
                            const content = await fs.readFile(tempFile, 'utf-8');
                            const directxMatch = content.match(/DirectX Version:\s*DirectX\s*([\d.]+)/i);
                            if (directxMatch) {
                                const version = directxMatch[1];
                                logger.info(`系统DirectX版本: ${version}`);
                                logger.info('注意：即使系统有DirectX 12，仍可能缺少DirectX 9.0c运行时组件');
                            }
                            await fs.remove(tempFile).catch(() => { });
                        }
                        resolve(false);
                    }
                    catch (error) {
                        logger.error('解析dxdiag输出失败:', error);
                        resolve(false);
                    }
                });
                child.on('error', (error) => {
                    logger.warn('运行dxdiag失败:', error.message);
                    resolve(false);
                });
                setTimeout(() => {
                    if (!child.killed) {
                        child.kill('SIGTERM');
                        resolve(false);
                    }
                }, 30000);
            }
            catch (error) {
                logger.error('dxdiag检查失败:', error);
                resolve(false);
            }
        });
    }
    async checkDirectXRegistry() {
        return new Promise((resolve) => {
            const child = spawn('reg', [
                'query',
                'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\DirectX',
                '/v',
                'Version'
            ], { windowsHide: true });
            let output = '';
            child.stdout.on('data', (data) => {
                output += data.toString();
            });
            child.on('close', (code) => {
                if (code === 0) {
                    const versionMatch = output.match(/4\.09\.00\.(\d+)/);
                    if (versionMatch && parseInt(versionMatch[1]) >= 904) {
                        resolve(true);
                        return;
                    }
                }
                resolve(false);
            });
            child.on('error', () => {
                resolve(false);
            });
        });
    }
    async checkDirectXFiles() {
        const systemDir = process.env.SYSTEMROOT ? path.join(process.env.SYSTEMROOT, 'System32') : 'C:\\Windows\\System32';
        const requiredFiles = [
            'ddraw.dll',
            'dsound.dll',
            'dinput.dll',
            'dinput8.dll'
        ];
        try {
            for (const file of requiredFiles) {
                const filePath = path.join(systemDir, file);
                if (!await fs.pathExists(filePath)) {
                    return false;
                }
            }
            return true;
        }
        catch (error) {
            logger.error('检查DirectX文件失败:', error);
            return false;
        }
    }
    async checkDirectXDLLs() {
        const systemDir = process.env.SYSTEMROOT ? path.join(process.env.SYSTEMROOT, 'System32') : 'C:\\Windows\\System32';
        const requiredD3DX9Files = [
            'd3dx9_43.dll',
            'd3dx9_42.dll',
            'd3dx9_41.dll',
            'd3dx9_40.dll',
            'd3dx9_39.dll',
            'd3dx9_38.dll',
            'd3dx9_37.dll',
            'd3dx9_36.dll'
        ];
        const otherRequiredFiles = [
            'xinput1_3.dll',
            'xaudio2_7.dll',
            'd3dcompiler_43.dll'
        ];
        try {
            let foundD3DX9 = false;
            let foundOthers = 0;
            for (const file of requiredD3DX9Files) {
                const filePath = path.join(systemDir, file);
                if (await fs.pathExists(filePath)) {
                    logger.info(`找到DirectX 9.0c文件: ${file}`);
                    foundD3DX9 = true;
                    break;
                }
            }
            for (const file of otherRequiredFiles) {
                const filePath = path.join(systemDir, file);
                if (await fs.pathExists(filePath)) {
                    logger.info(`找到DirectX运行时文件: ${file}`);
                    foundOthers++;
                }
            }
            const isInstalled = foundD3DX9 && foundOthers >= 2;
            if (!foundD3DX9) {
                logger.info('未找到DirectX 9.0c核心文件(d3dx9_*.dll)');
            }
            if (foundOthers < 2) {
                logger.info(`DirectX运行时文件不完整，仅找到 ${foundOthers} 个必需文件`);
            }
            return isInstalled;
        }
        catch (error) {
            logger.error('检查DirectX DLL文件失败:', error);
            return false;
        }
    }
    async downloadFile(url, filePath, onProgress) {
        const response = await axios({
            method: 'GET',
            url,
            responseType: 'stream',
            timeout: 300000,
        });
        const totalLength = parseInt(String(response.headers['content-length'] || '0'), 10);
        let downloadedLength = 0;
        const writer = fs.createWriteStream(filePath);
        response.data.on('data', (chunk) => {
            downloadedLength += chunk.length;
            if (totalLength > 0 && onProgress) {
                const progress = Math.round((downloadedLength / totalLength) * 100);
                onProgress(progress);
            }
        });
        response.data.pipe(writer);
        return new Promise((resolve, reject) => {
            writer.on('finish', resolve);
            writer.on('error', reject);
        });
    }
    async extractDirectXRedist(redistPath, extractDir) {
        return new Promise((resolve, reject) => {
            logger.info(`提取DirectX安装包: ${redistPath} 到 ${extractDir}`);
            const child = spawn(redistPath, ['/Q', '/C', `/T:${extractDir}`], {
                windowsHide: true,
                stdio: 'pipe'
            });
            let output = '';
            let errorOutput = '';
            child.stdout?.on('data', (data) => {
                output += data.toString();
                logger.info(`DirectX提取输出: ${data.toString().trim()}`);
            });
            child.stderr?.on('data', (data) => {
                errorOutput += data.toString();
                logger.warn(`DirectX提取警告: ${data.toString().trim()}`);
            });
            child.on('close', (code) => {
                logger.info(`DirectX提取程序退出，退出码: ${code}`);
                if (code === 0) {
                    logger.info('DirectX安装包提取完成');
                    resolve();
                }
                else {
                    logger.error(`DirectX安装包提取失败，退出码: ${code}`);
                    logger.error(`错误输出: ${errorOutput}`);
                    reject(new Error(`提取失败，退出码: ${code}。${errorOutput || '可能需要管理员权限'}`));
                }
            });
            child.on('error', (error) => {
                logger.error('DirectX提取程序执行出错:', error);
                reject(new Error(`无法启动提取程序: ${error.message}`));
            });
            setTimeout(() => {
                if (!child.killed) {
                    logger.warn('DirectX提取程序执行超时，强制终止');
                    child.kill('SIGTERM');
                    reject(new Error('提取超时，请检查文件或重试'));
                }
            }, 120000);
        });
    }
    async executeDirectXSetup(dxsetupPath) {
        return new Promise((resolve, reject) => {
            logger.info(`执行DirectX安装程序: ${dxsetupPath}`);
            const child = spawn(dxsetupPath, ['/silent'], {
                windowsHide: true,
                stdio: 'pipe'
            });
            let output = '';
            let errorOutput = '';
            child.stdout?.on('data', (data) => {
                output += data.toString();
                logger.info(`DirectX安装输出: ${data.toString().trim()}`);
            });
            child.stderr?.on('data', (data) => {
                errorOutput += data.toString();
                logger.warn(`DirectX安装警告: ${data.toString().trim()}`);
            });
            child.on('close', (code) => {
                logger.info(`DirectX安装程序退出，退出码: ${code}`);
                if (code === 0 || code === 1) {
                    logger.info('DirectX安装程序执行完成');
                    if (code === 1) {
                        logger.warn('DirectX安装完成，但可能需要重启系统以完全生效');
                    }
                    resolve();
                }
                else {
                    logger.error(`DirectX安装程序执行失败，退出码: ${code}`);
                    logger.error(`错误输出: ${errorOutput}`);
                    reject(new Error(`安装失败，退出码: ${code}。${errorOutput || '可能需要管理员权限或系统不兼容'}`));
                }
            });
            child.on('error', (error) => {
                logger.error('DirectX安装程序执行出错:', error);
                reject(new Error(`无法启动安装程序: ${error.message}`));
            });
            setTimeout(() => {
                if (!child.killed) {
                    logger.warn('DirectX安装程序执行超时，强制终止');
                    child.kill('SIGTERM');
                    reject(new Error('安装超时，请检查系统环境或手动安装'));
                }
            }, 300000);
        });
    }
    async executeInstaller(installerPath) {
        return new Promise((resolve, reject) => {
            logger.info(`执行DirectX安装程序: ${installerPath}`);
            const child = spawn(installerPath, ['/Q'], {
                windowsHide: true,
                stdio: 'pipe'
            });
            let output = '';
            let errorOutput = '';
            child.stdout?.on('data', (data) => {
                output += data.toString();
                logger.info(`DirectX安装输出: ${data.toString().trim()}`);
            });
            child.stderr?.on('data', (data) => {
                errorOutput += data.toString();
                logger.warn(`DirectX安装警告: ${data.toString().trim()}`);
            });
            child.on('close', (code) => {
                logger.info(`DirectX安装程序退出，退出码: ${code}`);
                if (code === 0 || code === 1) {
                    logger.info('DirectX安装程序执行完成');
                    if (code === 1) {
                        logger.warn('DirectX安装完成，但可能需要重启系统以完全生效');
                    }
                    resolve();
                }
                else {
                    logger.error(`DirectX安装程序执行失败，退出码: ${code}`);
                    logger.error(`错误输出: ${errorOutput}`);
                    reject(new Error(`安装失败，退出码: ${code}。${errorOutput || '可能需要管理员权限或系统不兼容'}`));
                }
            });
            child.on('error', (error) => {
                logger.error('DirectX安装程序执行出错:', error);
                reject(new Error(`无法启动安装程序: ${error.message}`));
            });
            setTimeout(() => {
                if (!child.killed) {
                    logger.warn('DirectX安装程序执行超时，强制终止');
                    child.kill('SIGTERM');
                    reject(new Error('安装超时，请检查系统环境或手动安装'));
                }
            }, 300000);
        });
    }
    async verifyInstallation() {
        await new Promise(resolve => setTimeout(resolve, 3000));
        const installed = await this.checkDirectXInstalled();
        if (!installed) {
            logger.warn('DirectX安装验证失败，可能需要更多时间或重启系统');
        }
        else {
            logger.info('DirectX安装验证成功');
        }
        return installed;
    }
    async getDirectXEnvironments() {
        await this.ensureInstallDir();
        if (os.platform() !== 'win32') {
            return [];
        }
        logger.info('检查DirectX安装状态...');
        const installed = await this.checkDirectXInstalled();
        const versionDir = this.getVersionDir('directx9');
        logger.info(`DirectX安装状态: ${installed ? '已安装' : '未安装'}`);
        const installerPath = path.join(versionDir, 'dxwebsetup.exe');
        const hasInstaller = await fs.pathExists(installerPath);
        return [{
                version: 'DirectX 9.0c',
                platform: 'win32',
                downloadUrl: 'https://www.microsoft.com/en-us/download/details.aspx?id=35',
                installed,
                installPath: hasInstaller ? versionDir : undefined
            }];
    }
    async installDirectX(downloadUrl, onProgress) {
        if (os.platform() !== 'win32') {
            throw new Error('DirectX只能在Windows系统上安装');
        }
        await this.ensureInstallDir();
        const installed = await this.checkDirectXInstalled();
        if (installed) {
            logger.info('DirectX已经安装，跳过安装过程');
            throw new Error('DirectX 已经安装');
        }
        try {
            const versionDir = this.getVersionDir('directx9');
            await fs.ensureDir(versionDir);
            const fileName = 'directx_Jun2010_redist.exe';
            const downloadPath = path.join(versionDir, fileName);
            logger.info(`开始下载DirectX安装程序`);
            const actualDownloadUrl = 'https://download.microsoft.com/download/8/4/a/84a35bf1-dafe-4ae8-82af-ad2ae20b6b14/directx_Jun2010_redist.exe';
            logger.info(`使用DirectX 9.0c离线安装包: ${actualDownloadUrl}`);
            logger.info(`传入的页面链接: ${downloadUrl}`);
            if (await fs.pathExists(downloadPath)) {
                logger.info('DirectX安装程序已存在，跳过下载');
                onProgress?.('download', 100);
            }
            else {
                await this.downloadFile(actualDownloadUrl, downloadPath, (progress) => {
                    onProgress?.('download', progress);
                });
                logger.info('DirectX安装程序下载完成');
            }
            const stats = await fs.stat(downloadPath);
            if (stats.size < 100000) {
                throw new Error('下载的安装程序文件异常，请重试');
            }
            logger.info('开始提取DirectX安装文件');
            onProgress?.('install', 10);
            const extractDir = path.join(versionDir, 'extracted');
            await this.extractDirectXRedist(downloadPath, extractDir);
            onProgress?.('install', 30);
            logger.info('开始安装DirectX');
            const dxsetupPath = path.join(extractDir, 'DXSETUP.exe');
            await this.executeDirectXSetup(dxsetupPath);
            onProgress?.('install', 80);
            logger.info('验证DirectX安装状态');
            const verifyResult = await this.verifyInstallation();
            onProgress?.('install', 100);
            if (verifyResult) {
                logger.info('DirectX安装并验证成功');
            }
            else {
                logger.warn('DirectX安装完成，但验证未通过。可能需要重启系统或手动检查');
            }
        }
        catch (error) {
            logger.error('DirectX安装失败:', error);
            throw error;
        }
    }
    async uninstallDirectX() {
        if (os.platform() !== 'win32') {
            throw new Error('DirectX只能在Windows系统上操作');
        }
        try {
            const versionDir = this.getVersionDir('directx9');
            let cleaned = false;
            if (await fs.pathExists(versionDir)) {
                await fs.remove(versionDir);
                logger.info('DirectX安装文件已清理');
                cleaned = true;
            }
            const tempDir = os.tmpdir();
            const tempFiles = ['directx_Jun2010_redist.exe', 'dxwebsetup.exe', 'directx_temp'];
            for (const tempFile of tempFiles) {
                const tempPath = path.join(tempDir, tempFile);
                if (await fs.pathExists(tempPath)) {
                    await fs.remove(tempPath);
                    logger.info(`清理临时文件: ${tempFile}`);
                    cleaned = true;
                }
            }
            if (!cleaned) {
                logger.info('没有找到需要清理的DirectX文件');
            }
        }
        catch (error) {
            logger.error('清理DirectX文件失败:', error);
            throw new Error(`清理失败: ${error instanceof Error ? error.message : '未知错误'}`);
        }
    }
    async getDirectXInfo() {
        if (os.platform() !== 'win32') {
            return { installed: false, details: '仅支持Windows系统' };
        }
        const installed = await this.checkDirectXInstalled();
        if (!installed) {
            return {
                installed: false,
                details: 'DirectX 9.0c 未安装或版本过低。建议安装以确保游戏和多媒体应用正常运行。'
            };
        }
        try {
            const versionInfo = await this.getDirectXVersion();
            return {
                version: versionInfo,
                installed: true,
                details: `DirectX ${versionInfo || '9.0c+'} 已安装`
            };
        }
        catch (error) {
            return {
                installed: true,
                details: 'DirectX 已安装，但无法获取详细版本信息'
            };
        }
    }
    async getDirectXVersion() {
        return new Promise((resolve) => {
            const child = spawn('reg', [
                'query',
                'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\DirectX',
                '/v',
                'Version'
            ], { windowsHide: true });
            let output = '';
            child.stdout.on('data', (data) => {
                output += data.toString();
            });
            child.on('close', (code) => {
                if (code === 0) {
                    const versionMatch = output.match(/4\.09\.00\.(\d+)/);
                    if (versionMatch) {
                        const build = versionMatch[1];
                        resolve(`9.0c (${build})`);
                        return;
                    }
                }
                resolve(undefined);
            });
            child.on('error', () => {
                resolve(undefined);
            });
        });
    }
}
