const { ipcMain, app } = require('electron');
const path = require('path');
const fs = require('fs');
const crypto = require('crypto');
const fetch = require('node-fetch');
const tar = require('tar');
const { exec } = require('child_process');

function initPluginHandler(ipcMain) {

    const isPackaged = app.isPackaged
    const resourcesPath = process.resourcesPath
    let pluginsDir = ""

    if (isPackaged) {
        pluginsDir = path.join(resourcesPath, 'plugins');
    } else {
        pluginsDir = path.join(__dirname, '../../../plugins');
    }

    console.log(`Plugins directory set to: ${pluginsDir}`);

    if (!fs.existsSync(pluginsDir)) {
        fs.mkdirSync(pluginsDir, { recursive: true });
        console.log(`Created plugins directory: ${pluginsDir}`);
    }

    ipcMain.handle('get-local-plugins', (event) => {
        console.log('Fetching local plugins list...');
        const localPlugins = fs.readdirSync(pluginsDir).reduce((acc, folder) => {
            const pluginInfoPath = path.join(pluginsDir, folder, 'plugin_info.json');
            if (fs.existsSync(pluginInfoPath)) {
                const pluginInfo = JSON.parse(fs.readFileSync(pluginInfoPath, 'utf8'));
                acc[folder] = pluginInfo;
            }
            return acc;
        }, {});
        console.log('Local plugins:', localPlugins);
        return localPlugins;
    });

    ipcMain.handle('download-plugin', async (event, plugin) => {
        const pluginTarUrl = process.platform === 'win32' ? plugin.plugin_win_url : plugin.plugin_mac_url;
        const pluginTarPath = path.join(pluginsDir, `${plugin.folder_name}.tar.gz`);
        const tempTarPath = `${pluginTarPath}.part`;

        console.log(`Starting download for plugin: ${plugin.plugin_name}`);
        console.log(`Downloading from URL: ${pluginTarUrl}`);
        console.log(`Temporary tar path: ${tempTarPath}`);

        let downloadedSize = 0;

        if (fs.existsSync(tempTarPath)) {
            const stats = fs.statSync(tempTarPath);
            downloadedSize = stats.size;
            console.log(`Resuming download from byte: ${downloadedSize}`);
        }

        const response = await fetch(pluginTarUrl, {
            headers: {
                'Range': `bytes=${downloadedSize}-`
            }
        });

        const totalSize = parseInt(response.headers.get('content-length'), 10) + downloadedSize;
        console.log(`Total file size: ${totalSize} bytes`);

        const fileStream = fs.createWriteStream(tempTarPath, { flags: 'a' });

        response.body.on('data', (chunk) => {
            downloadedSize += chunk.length;
            event.sender.send('download-progress', {
                pluginName: plugin.folder_name,
                progress: (downloadedSize / totalSize) * 100,
            });
        });

        await new Promise((resolve, reject) => {
            response.body.pipe(fileStream);
            response.body.on('error', reject);
            fileStream.on('finish', resolve);
        });

        if (downloadedSize === totalSize) {
            console.log('Download complete. Verifying file integrity...');
            fs.renameSync(tempTarPath, pluginTarPath);
            
            const fileBuffer = fs.readFileSync(pluginTarPath);
            const hashSum = crypto.createHash('md5');
            hashSum.update(fileBuffer);
            const hex = hashSum.digest('hex');

            const expectedMd5 = process.platform === 'win32' ? plugin.plugin_win_md5 : plugin.plugin_mac_md5;

            if (hex !== expectedMd5) {
                console.error('MD5 checksum mismatch. File integrity verification failed.');
                throw new Error('文件完整性校验失败');
            } else {
                console.log('File integrity verified successfully.');
            }

            await extractPlugin(plugin, pluginTarPath);
        } else {
            console.error('Download incomplete. Please try again.');
            throw new Error('下载未完成，请重试');
        }
    });

    async function extractPlugin(plugin, pluginTarPath) {
        const pluginDir = path.join(pluginsDir, plugin.folder_name);
        console.log(`Extracting plugin to: ${pluginDir}`);

        // 确保解压目标目录存在
        if (!fs.existsSync(pluginDir)) {
            fs.mkdirSync(pluginDir, { recursive: true });
            console.log(`Created directory for plugin extraction: ${pluginDir}`);
        }

        await tar.x({
            file: pluginTarPath,
            cwd: pluginDir
        });

        fs.unlinkSync(pluginTarPath);
        console.log(`Deleted temporary tar file: ${pluginTarPath}`);

        const pluginInfoPath = path.join(pluginDir, 'plugin_info.json');
        fs.writeFileSync(pluginInfoPath, JSON.stringify({
            plugin_name: plugin.plugin_name,
            version: plugin.version,
            port: plugin.port,
            entry_file: plugin.entry_file
        }));

        console.log(`Plugin extracted and info saved: ${pluginInfoPath}`);
        return {
            plugin_name: plugin.plugin_name,
            version: plugin.version
        };
    }

    ipcMain.handle('start-plugin', (event, pluginName) => {
        const pluginDir = path.join(pluginsDir, pluginName);
        const pluginInfoPath = path.join(pluginDir, 'plugin_info.json');
        const pluginInfo = JSON.parse(fs.readFileSync(pluginInfoPath, 'utf8'));

        console.log(`Starting plugin: ${pluginInfo.plugin_name} from ${pluginDir}`);

        const condaDir = path.join(pluginDir, 'conda');
        const entryFile = path.join(pluginDir, pluginInfo.entry_file);
        const port = pluginInfo.port

        // 检查 conda 目录和入口文件是否存在
        if (!fs.existsSync(condaDir) || !fs.existsSync(entryFile)) {
            console.error('Plugin installation is incomplete. Please reinstall the plugin.');
            return;
        }

        const pythonFilePath = path.join(condaDir, 'bin', 'python');

        // 处理路径中的空格和特殊字符
        const escapedPythonFilePath = `\\"${pythonFilePath}\\"`;
        const escapedStartFilePath = `\\"${entryFile}\\"`;

        const command = `${escapedPythonFilePath} ${escapedStartFilePath} ${port}`;
        console.log(`Executing command: ${command}`);

        // 在不同平台上使用不同的命令打开终端
        if (process.platform === 'win32') {
            exec(`start cmd.exe /K "${command}"`);
        } else if (process.platform === 'darwin') {
            let cmd = `osascript -e 'tell application "Terminal" to do script "${command}"'`;
            console.log(cmd)
            exec(cmd);
            // exec(`open -a Terminal "${command}"`);
        } else if (process.platform === 'linux') {
            exec(`gnome-terminal -- bash -c "${command}; exec bash"`);
        }
    });

    ipcMain.handle('stop-plugin', (event, pluginName) => {
        const pluginDir = path.join(pluginsDir, pluginName);
        const pluginInfoPath = path.join(pluginDir, 'plugin_info.json');

        console.log(`Stopping plugin: ${pluginName}`);

        if (fs.existsSync(pluginInfoPath)) {
            const pluginInfo = JSON.parse(fs.readFileSync(pluginInfoPath, 'utf8'));
            const port = pluginInfo.port;

            if (process.platform === 'win32') {
                // 在 Windows 上使用 netstat 和 taskkill
                exec(`netstat -ano | findstr :${port}`, (err, stdout, stderr) => {
                    if (err) {
                        console.error(`无法查找使用端口 ${port} 的进程:`, err);
                        return;
                    }

                    const lines = stdout.trim().split('\n');
                    if (lines.length > 0) {
                        const pid = lines[0].trim().split(/\s+/).pop(); // 获取 PID

                        if (pid) {
                            exec(`taskkill /PID ${pid} /F`, (err, stdout, stderr) => {
                                if (err) {
                                    console.error(`无法终止进程 ${pid}:`, err);
                                    return;
                                }
                                console.log(`使用端口 ${port} 的进程 (PID: ${pid}) 已停止`);
                            });
                        } else {
                            console.log(`未找到使用端口 ${port} 的进程`);
                        }
                    } else {
                        console.log(`未找到使用端口 ${port} 的进程`);
                    }
                });
            } else {
                // 非 Windows 系统使用 lsof
                exec(`lsof -i :${port} -t`, (err, stdout, stderr) => {
                    if (err) {
                        console.error(`无法查找使用端口 ${port} 的进程:`, err);
                        return;
                    }

                    const pid = stdout.trim();
                    if (pid) {
                        try {
                            process.kill(pid, 'SIGTERM');
                            console.log(`使用端口 ${port} 的进程 (PID: ${pid}) 已停止`);
                        } catch (error) {
                            console.error(`无法终止进程 ${pid}:`, error);
                        }
                    } else {
                        console.log(`未找到使用端口 ${port} 的进程`);
                    }
                });
            }
        } else {
            console.log(`找不到插件 ${pluginName} 的插件信息文件`);
        }
    });
}

module.exports = { initPluginHandler };