const { exec, spawn } = require('child_process');
const { promisify } = require('util');
const path = require('path');
const fs = require('fs');

const execAsync = promisify(exec);

/**
 * 检测当前操作系统
 */
function getOSPlatform() {
    const platform = process.platform;
    if (platform === 'win32') return 'windows';
    if (platform === 'darwin') return 'macos';
    if (platform === 'linux') return 'linux';
    return 'unknown';
}

/**
 * 检查文件或目录是否存在
 */
function checkPathExists(targetPath) {
    try {
        fs.accessSync(targetPath);
        return true;
    } catch (error) {
        return false;
    }
}

/**
 * 获取目录路径（如果是文件则返回所在目录）
 */
function getDirectoryPath(targetPath) {
    try {
        const stats = fs.statSync(targetPath);
        if (stats.isFile()) {
            return path.dirname(targetPath);
        }
        if (stats.isDirectory()) {
            return targetPath;
        }
    } catch (error) {
        throw new Error(`路径不存在或无法访问: ${targetPath}`);
    }
    return targetPath;
}

/**
 * 在 Windows 系统打开目录
 */
async function openDirectoryWindows(directoryPath) {
    // 确保路径使用反斜杠
    const normalizedPath = directoryPath.replace(/\//g, '\\');
    
    console.log(`📁 在文件资源管理器中打开: ${normalizedPath}`);
    
    // 方法1: 使用 explorer 命令
    try {
        const command = `explorer "${normalizedPath}"`;
        await execAsync(command);
        console.log('✅ 已启动文件资源管理器');
        return true;
    } catch (error) {
        console.warn('方法1失败:', error.message);
    }
    
    // 方法2: 使用 start 命令
    try {
        const command = `start "" "${normalizedPath}"`;
        await execAsync(command);
        console.log('✅ 已使用 start 命令打开');
        return true;
    } catch (error) {
        console.warn('方法2失败:', error.message);
    }
    
    throw new Error('无法在Windows系统中打开目录');
}

/**
 * 在 macOS 系统打开目录
 */
async function openDirectoryMacOS(directoryPath) {
    console.log(`📁 在访达中打开: ${directoryPath}`);
    
    // 方法1: 使用 open 命令
    try {
        const command = `open "${directoryPath}"`;
        await execAsync(command);
        console.log('✅ 已启动访达');
        return true;
    } catch (error) {
        console.warn('方法1失败:', error.message);
    }
    
    // 方法2: 使用 open -R 命令（打开包含指定文件的文件夹）
    try {
        const command = `open -R "${directoryPath}"`;
        await execAsync(command);
        console.log('✅ 已使用 open -R 命令打开');
        return true;
    } catch (error) {
        console.warn('方法2失败:', error.message);
    }
    
    throw new Error('无法在macOS系统中打开目录');
}

/**
 * 在 Linux 系统打开目录
 */
async function openDirectoryLinux(directoryPath) {
    console.log(`📁 在文件管理器中打开: ${directoryPath}`);
    
    // 尝试不同的文件管理器
    const fileManagers = [
        'xdg-open',        // 标准Linux桌面打开方式
        'nautilus',        // GNOME
        'dolphin',         // KDE
        'thunar',          // XFCE
        'pcmanfm',         // LXDE
        'nemo',            // Cinnamon
        'caja'            // MATE
    ];
    
    for (const manager of fileManagers) {
        try {
            // 检查文件管理器是否可用
            await execAsync(`which ${manager}`);
            
            const command = `${manager} "${directoryPath}"`;
            const child = spawn(manager, [directoryPath], {
                stdio: 'ignore',
                detached: true
            });
            
            child.unref();
            console.log(`✅ 已使用 ${manager} 打开目录`);
            return true;
        } catch (error) {
            // 继续尝试下一个文件管理器
            continue;
        }
    }
    
    // 最后尝试 xdg-open（最通用的方式）
    try {
        const command = `xdg-open "${directoryPath}"`;
        const child = spawn('xdg-open', [directoryPath], {
            stdio: 'ignore',
            detached: true
        });
        
        child.unref();
        console.log('✅ 已使用 xdg-open 打开目录');
        return true;
    } catch (error) {
        throw new Error('无法在Linux系统中打开目录，请确保已安装文件管理器');
    }
}

/**
 * 在终端中打开目录（跨平台）
 */
async function openDirectoryInTerminal(directoryPath) {
    const os = getOSPlatform();
    const dirPath = getDirectoryPath(directoryPath);
    
    console.log(`💻 操作系统: ${os}`);
    console.log(`📂 目标目录: ${dirPath}`);
    
    if (!checkPathExists(dirPath)) {
        throw new Error(`路径不存在: ${dirPath}`);
    }
    
    switch (os) {
        case 'windows':
            return await openDirectoryWindows(dirPath);
        case 'macos':
            return await openDirectoryMacOS(dirPath);
        case 'linux':
            return await openDirectoryLinux(dirPath);
        default:
            throw new Error(`不支持的操作系统: ${process.platform}`);
    }
}

/**
 * 在系统默认终端中打开并切换到目录
 */
async function openTerminalInDirectory(directoryPath) {
    const os = getOSPlatform();
    const dirPath = getDirectoryPath(directoryPath);
    
    console.log(`🖥️  在终端中打开目录: ${dirPath}`);
    
    if (!checkPathExists(dirPath)) {
        throw new Error(`路径不存在: ${dirPath}`);
    }
    
    const commands = {
        windows: `start cmd /K "cd /d "${dirPath}" && echo 当前目录: %cd%"`,
        macos: `osascript -e 'tell application "Terminal" to do script "cd \\\"${dirPath}\\\" && pwd"'`,
        linux: `gnome-terminal --working-directory="${dirPath}" || konsole --workdir "${dirPath}" || xterm -e "cd \\"${dirPath}\\" && bash"`
    };
    
    try {
        let command;
        switch (os) {
            case 'windows':
                command = commands.windows;
                break;
            case 'macos':
                command = commands.macos;
                break;
            case 'linux':
                command = commands.linux;
                break;
            default:
                throw new Error('不支持的操作系统');
        }
        
        // 使用 spawn 避免命令注入漏洞
        const shell = os === 'windows' ? 'cmd.exe' : '/bin/bash';
        const args = os === 'windows' ? ['/c', command] : ['-c', command];
        
        const child = spawn(shell, args, {
            stdio: 'ignore',
            detached: true
        });
        
        child.unref();
        console.log('✅ 已启动终端并切换到目录');
        return true;
    } catch (error) {
        console.warn('无法在终端中打开目录:', error.message);
        return false;
    }
}

/**
 * 主函数 - 打开文件所在目录
 */
async function openFileDirectory(filePath, options = {}) {
    const {
        openInTerminal = false,    // 是否在终端中打开
        createIfNotExists = false, // 目录不存在时是否创建
        wait = false              // 是否等待进程结束
    } = options;
    
    try {
        // 检查路径是否存在
        if (!checkPathExists(filePath)) {
            if (createIfNotExists) {
                const dirPath = path.dirname(filePath);
                fs.mkdirSync(dirPath, { recursive: true });
                console.log(`📁 创建目录: ${dirPath}`);
            } else {
                throw new Error(`路径不存在: ${filePath}`);
            }
        }
        
        const directoryPath = getDirectoryPath(filePath);
        
        if (openInTerminal) {
            await openTerminalInDirectory(directoryPath);
        } else {
            await openDirectoryInTerminal(directoryPath);
        }
        
        return true;
    } catch (error) {
        console.error('❌ 打开目录失败:', error.message);
        return false;
    }
}

/**
 * 使用示例
 */
async function main() {
    // 示例1: 打开当前脚本所在目录
    const currentFile = __filename;
    console.log('当前文件:', currentFile);
    
    // 方法1: 在文件管理器中打开
    console.log('\n--- 在文件管理器中打开 ---');
    await openFileDirectory(currentFile);
    
    // 等待2秒
    await new Promise(resolve => setTimeout(resolve, 2000));
    
    // 方法2: 在终端中打开（可选）
    console.log('\n--- 在终端中打开 ---');
    await openFileDirectory(currentFile, { openInTerminal: true });
}

// 命令行使用方式
if (require.main === module) {
    const args = process.argv.slice(2);
    
    if (args.length === 0) {
        // 没有参数，打开当前目录
        openFileDirectory(process.cwd())
            .then(success => {
                if (!success) process.exit(1);
            })
            .catch(error => {
                console.error('错误:', error.message);
                process.exit(1);
            });
    } else {
        const filePath = path.resolve(args[0]);
        const options = {
            openInTerminal: args.includes('--terminal') || args.includes('-t'),
            createIfNotExists: args.includes('--create') || args.includes('-c')
        };
        
        openFileDirectory(filePath, options)
            .then(success => {
                if (!success) process.exit(1);
            })
            .catch(error => {
                console.error('错误:', error.message);
                process.exit(1);
            });
    }
}

// 导出函数
module.exports = {
    openFileDirectory,
    openDirectoryInTerminal,
    openTerminalInDirectory,
    getOSPlatform
};