import {app, BrowserWindow, ipcMain, dialog} from 'electron';
import {exec, spawn} from 'child_process';
import path from 'path';
import {fileURLToPath} from 'url';
import fs from 'fs';
import axios from 'axios';
import ProcessManager from './processManager.js'

const processManager = new ProcessManager(); // 创建进程管理器实例
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const PJI_SCRIPT_PATH_PREFIX = "/home/cicv/work/pji_desktop/"
// console.log("PJI_SCRIPT_PATH_PREFIX", PJI_SCRIPT_PATH_PREFIX)

function createWindow() {
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            preload: path.join(__dirname, 'preload.js'), // 确保路径正确
            contextIsolation: true,
            enableRemoteModule: false,
            nodeIntegration: false,
        }
    });

    win.webContents.openDevTools(); // 打开开发者工具进行调试
    win.loadURL('http://localhost:5173'); // 开发环境
    // win.loadURL('http://36.110.106.156:81'); // 生产环境
    console.log('Window created and URL loaded');
}

app.whenReady().then(createWindow);

app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
        app.quit();
    }
});


app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
        createWindow();
    }
});

// // 禁用GPU加速
// app.disableHardwareAcceleration()


// ------------- 进程通信 -------------
ipcMain.handle('dialog:open', async (event, options = {}) => {
    const result = await dialog.showOpenDialog(BrowserWindow.getFocusedWindow() || BrowserWindow.getAllWindows()[0], options);
    return result.canceled ? null : result.filePaths;
});


// 下载文件
ipcMain.handle('download-file', async (event, { url, fileName, savePath, overwriteFlag, dialogFlag, requestType, data }) => {
    try {
        let filePath
        let getPath
        // console.log("url", url)
        // console.log("response", response)
        if (dialogFlag) { // 弹出保存文件对话框
            console.log("savePath", savePath)
            // 获取保存路径
            getPath = await dialog.showSaveDialog({
                defaultPath: path.join(app.getPath('downloads'), fileName)
            })
            filePath = getPath.filePath
            if (getPath.canceled || filePath === "") {
                return { success: false, message: 'File path does not exist' }
            }
        } else {
            filePath = path.join(savePath, fileName);
        }

        console.log("filePath", filePath)

        // 查找文件是否存在
        const fileExists = fs.existsSync(filePath)
        if (fileExists && !overwriteFlag) { // 已存在且不覆盖
            return {success: true, filePath}
        } else { // 不存在
            console.log("url", url)
            let response
            if (requestType === "get") {
                console.log("get...")
                response = await axios.get(url, {responseType: 'stream'});
            } else {
                response = await axios.post(url, data, {responseType: 'stream'});
            }
            console.log("response", response)

            // 写入文件
            const writer = fs.createWriteStream(filePath);

            return new Promise((resolve, reject) => {
                response.data.pipe(writer);

                let error = null;
                writer.on('error', err => {
                    error = err;
                    writer.close();
                    reject(err);
                });

                writer.on('close', () => {
                    if (!error) {
                        resolve({success: true, filePath}); // 返回成功信息
                    } else {
                        reject({success: false, error: error.message}); // 返回错误信息
                    }
                });
            });
        }
    } catch (error) {
        console.error('下载文件出错:', error);
        throw error;
    }
});


// 删除文件
ipcMain.on('delete-file', (event, {fileName, savePath}) => {
    const filePath = path.join(savePath, fileName);
    // 检查文件是否存在
    if (fs.existsSync(filePath)) {
        // 文件存在，尝试删除
        fs.unlink(filePath, (err) => {
            if (err) {
                event.reply('delete-file-response', { success: false, message: err.message });
            } else {
                event.reply('delete-file-response', { success: true, message: 'File deleted successfully' });
            }
        });
    } else {
        // 文件不存在
        event.reply('delete-file-response', { success: false, message: 'File does not exist' });
    }
});

// 上传文件
ipcMain.on('upload-file', async (event, {filePath, uploadUrl}) => {
    if (!fs.existsSync(filePath)) {
        console.log("File does not exist");
        event.reply('upload-file-response', {success: false, message: 'File does not exist'});
        return;
    }
    try {
        const result = await uploadFile(filePath, uploadUrl);
        console.log("result", result);
        if (result.status) {
            event.reply('upload-file-response', { success: true, message: 'File uploaded successfully', details: result.details });
        } else {
            event.reply('upload-file-response', { success: false, message: 'Error uploading file', details: '' });
        }
    } catch (err) {
        event.reply('upload-file-response', { success: false, message: err.message, details: '' });
    }
});

async function uploadFile(filePath, uploadUrl) {

    const data = fs.readFileSync(filePath)
    // 创建formData对象
    const formData = new FormData();
    formData.append('file', new Blob([data]), path.basename(filePath));

    try {
        // 使用axios上传文件
        const response = await axios.post(uploadUrl, formData, {
            headers: {
                'Content-Type': 'multipart/form-data'
            }
        })
        // console.log('response', response.data)

        return response.data
    } catch (err) {
        console.log("Error uploading file:", err);
        return { status: false, code: '', message: '上传件失败', details: '' };
    }
}

async function uploadFileWithRetry(filePath, uploadUrl, maxRetries = 3) {
    let attempt = 1;

    while (attempt <= maxRetries) {
        console.log("Uploading file - attempt:", attempt);
        try {
            const response = await uploadFile(filePath, uploadUrl);
            console.log("response", response);
            if (response.status) { // 上传成功
                return response;
            } else { // 上传失败
                console.log("Fail to upload file - attempt:", attempt);
                attempt++
            }
        } catch (error) {
            console.log("Error uploading file - attempt:", attempt);
            console.log("Error:", error);
            attempt++
        }
    }
    return { status: false, code: '', message: '上传文件失败', details: '' };
}

// 导入算法镜像
ipcMain.on('docker-import', (event, filePath, tag) => {
    const command = 'bash ' + PJI_SCRIPT_PATH_PREFIX + 'docker_import/run_docker_import.sh ' + filePath + ' pji_nav ' + tag
    console.log('Docker import command：', command);
    exec(command, (error, stdout, stderr) => {
        if (error) {
            console.error(`exec error: ${error}`);
            event.reply('docker-import-response', { success: false, message: error.message });
        } else {
            console.log(`stdout: ${stdout}`);
            console.error(`stderr: ${stderr}`);
            event.reply('docker-import-response', { success: true, message: 'Docker image imported successfully' });
        }
    });
});

// 更新地图
ipcMain.on('update-map', (event, {container_name, file_path}) => {
    const command = 'bash ' + PJI_SCRIPT_PATH_PREFIX + '/map_update/run_map_update.sh ' + container_name + ' ' + file_path;
    console.log('command：', command);

    processManager.startProcess('update-map', command, (error, stdout, stderr) => {
        if (error) {
            console.error(`exec error: ${error}`);
            // event.reply('update-map-response', { success: false, message: error.message });
        } else {
            console.log(`stdout: ${stdout}`);
            console.error(`stderr: ${stderr}`);
            if (stdout.toString().includes('Result JSON file created')) { // 判断结束标志
                event.reply('update-map-response', { success: true, message: 'Update map successfully' });
            } else {
                event.reply('update-map-response', { success: false, message: 'Error updating map' });
            }
        }
    });
});

// 生成world
ipcMain.on('generate-world', (event, {rosbag_path}) => {
    const command = 'bash ' + PJI_SCRIPT_PATH_PREFIX + 'simulation/generate_world.sh ' + rosbag_path
    console.log('World generation command：', command);
    exec(command, (error, stdout, stderr) => {
        if (error) {
            console.error(`exec error: ${error}`);
            event.reply('generate-world-response', { success: false, message: error.message });
        } else {
            console.log(`stdout: ${stdout}`);
            console.error(`stderr: ${stderr}`);
            event.reply('generate-world-response', { success: true, message: 'World generated successfully' });
        }
    });
});

// 启动仿真环境
ipcMain.on('start-container', (event, {zip_file_path, image_name, container_name}) => {

    // 使用 spawn 启动脚本
    const serviceProcess = spawn('bash', [PJI_SCRIPT_PATH_PREFIX + "simulation/data_preparation.sh", zip_file_path], { detached: true });

    // 设置为后台进程
    serviceProcess.unref();

    // 监听输出
    serviceProcess.stdout.on('data', (data) => {
        console.log(`第一个脚本的输出: ${data}`);
        // 根据第一个脚本的输出判断其是否准备好
        if (data.toString().includes('Data preparation done')) {
            startSecondScript();
        }
    });

    // 监听错误
    serviceProcess.stderr.on('data', (data) => {
        console.error(`执行第一个脚本时出错: ${data}`);
    });

    // 监听关闭
    serviceProcess.on('close', (data) => {
        console.log(`第一个脚本已关闭: ${data}`);
    });

    function startSecondScript() {
        let command = 'bash ' + PJI_SCRIPT_PATH_PREFIX + "/simulation/start_container.sh " + image_name + " " + container_name
        // 启动第二个脚本
        const script2 = exec(command, (error, stdout, stderr) => {
            if (error) {
                console.error(`执行第二个脚本时出错: ${error}`);
                event.sender.send('start-container-response', { success: false, output: error });
                return;
            }
            console.log(`第二个脚本的输出: ${stdout}`);

            event.sender.send('start-container-response', { success: true, output: stdout });
        });

        script2.on('exit', (code) => {
            console.log(`第二个脚本已退出，退出码: ${code}`);
        });
    }
});

// 执行仿真
ipcMain.on('run-simulation', (event, {random_flag, count, obstacle_flag, default_start_flag, default_end_flag, start_point, end_point}) => {

    const command = 'bash ' + PJI_SCRIPT_PATH_PREFIX + 'simulation/run_simulation.sh ' + random_flag + ' ' + count + ' ' + obstacle_flag + ' ' +
        default_start_flag + ' ' + default_end_flag + ' ' + start_point + ' ' + end_point;
    console.log('command：', command);
    processManager.startProcess('run-simulation', command, (error, stdout, stderr) => {
        if (error) {
            console.error(`exec error: ${error}`);
            // event.reply('run-simulation-response', { success: false, message: error.message });
        } else {
            console.log(`stdout: ${stdout}`);
            console.error(`stderr: ${stderr}`);
            if (stdout.toString().includes('Evaluation finished')) { // 判断结束标志
                event.reply('run-simulation-response', { success: true, message: 'Run simulation successfully' });
            } else {
                event.reply('run-simulation-response', { success: false, message: 'Error running simulation' });
            }
        }
    });

    // 设置超时机制（
    const timeoutId = setTimeout(() => {
        if (!event.sender.isDestroyed()) {
            // 如果渲染进程仍然存在
            processManager.killProcess('run-simulation');
            event.reply('run-simulation-response', { success: false, message: 'Script running timeout' });
        }
        clearTimeout(timeoutId)
    }, 10*60*1000); // 10 分钟
});

// 读取并上传算法评价结果
ipcMain.handle('process-evaluation-files', async (event, {N, equipmentNo, sceneNo}) => {
    const result = []
    const evalDir = PJI_SCRIPT_PATH_PREFIX + "simulation/data/evaluation";
    const bagDir = PJI_SCRIPT_PATH_PREFIX + "simulation/data/record_bag";
    console.log('N', N)
    // 记录时间戳
    const timeStamp = Date.now()
    console.log("timeStamp", timeStamp);

    // 遍历评价结果文件夹，读取并上传相关数据
    for (let i = 1; i <= N; i++) {
        const subDir = path.join(evalDir, `${i}/result`);
        console.log("subDir", subDir);
        // 文件路径 - report.json
        const jsonFilePath = path.join(subDir, "report.json");
        console.log("jsonFilePath", jsonFilePath);
        // 文件路径 - report.pdf
        const pdfFilePath = path.join(subDir, "report.pdf");
        console.log("pdfFilePath", pdfFilePath);
        // 文件路径 - test-${i}.bag
        const bagFilePath = path.join(bagDir, `test-${i}.bag`);
        console.log("bagFilePath", bagFilePath);

        const uploadPdfUrl = "http://127.0.0.1:8888/simulation/upload/pdf?equipmentNo=" + equipmentNo + "&sceneNo=" + sceneNo +
            "&timeStamp=" + timeStamp + "&round=" + i;

        const uploadBagUrl = "http://127.0.0.1:8888/simulation/upload/bag?equipmentNo=" + equipmentNo + "&sceneNo=" + sceneNo +
            "&timeStamp=" + timeStamp + "&round=" + i;

        try {
            // 读取json文件
            const jsonData = fs.readFileSync(jsonFilePath, "utf-8");
            const parsedData = JSON.parse(jsonData);
            console.log("parsedData", parsedData);
            // 上传pdf文件
            // 查找pdf文件是否存在
            let pdfFileExists = fs.existsSync(pdfFilePath)
            // pdf文件不存在
            if (!pdfFileExists) break
            // pdf文件存在
            const uploadPdfResult = await uploadFileWithRetry(pdfFilePath, uploadPdfUrl);
            console.log("uploadPdfResult", uploadPdfResult);
            if (!uploadPdfResult.status) {
                break
            }

            // 上传bag文件
            // 查找bag文件是否存在
            let bagFileExists = fs.existsSync(bagFilePath)
            // bag文件不存在
            if (!bagFileExists) break
            // bag文件存在
            const uploadBagResult = await uploadFile(bagFilePath, uploadBagUrl);
            console.log("uploadBagResult", uploadBagResult);
            if (!uploadBagResult.status) { break}
            // 整合结果
            result.push({
                "round": i,
                "jsonData": parsedData,
                "uploadPdfKey": uploadPdfResult.details,
                "uploadBagKey": uploadBagResult.details,
                "timeStamp": timeStamp
            })
        } catch (error) {
            console.log("error", error);
            return { success: false, message: "Error uploading evaluation results", data: [] }
        }
    }
    // 判断数据上传是否完整
    if (result.length === N) {
        return { success: true, message: "Evaluation results uploaded successfully", data: result }
    } else {
        return { success: false, message: "Error uploading evaluation results", data: [] }
    }
})

async function uploadMapResult(filePath, uploadUrl) {
    // 查找文件是否存在
    let fileExists = fs.existsSync(filePath)
    let uploadResult = await uploadFileWithRetry(filePath, uploadUrl);
    if (!fileExists) return { success: false, message: "Error uploading map results", data: [] }
    // console.log("uploadResult", uploadResult);
    if (!uploadResult.status) {
        return { success: false, message: "Error uploading map results", data: [] }
    }
    return { success: true, message: "", data: uploadResult }
}

// 读取并上传地图更新结果
ipcMain.handle('process-map-update-files', async (event, {equipmentNo, timeStamp}) => {
    let result = {}
    equipmentNo  = "pji-test"
    timeStamp = Date.now()
    // 记录时间戳
    console.log("timeStamp", timeStamp);
    const dataDir = PJI_SCRIPT_PATH_PREFIX + "map_update/data";
    const mapBufDir = PJI_SCRIPT_PATH_PREFIX + "map_update/data/bag_folder/mapBuf";
    const resultDir = PJI_SCRIPT_PATH_PREFIX + "map_update/data/bag_folder/result";
    const updateMapDir = PJI_SCRIPT_PATH_PREFIX + "map_update/data/bag_folder/update_map";

    // 读取result*.json
    // 文件路径 - result*.json
    const jsonPrefix = "result";
    let files = fs.readdirSync(resultDir);
    let matchedFile = files.find(file => file.startsWith(jsonPrefix))
    let jsonFilePath = ""
    if (matchedFile) {
        // 如果找到匹配的文件
        jsonFilePath = path.join(resultDir, matchedFile);
    }

    console.log("jsonFilePath", jsonFilePath);

    // 文件路径 - 更新前pgm
    const prePgmPath = path.join(mapBufDir, "map.pgm");
    console.log("prePgmPath", prePgmPath);
    // 文件路径 - 更新后pgm
    const pgmSuffix = ".pgm";
    files = fs.readdirSync(updateMapDir);
    matchedFile = files.find(file => file.endsWith(pgmSuffix))
    let updatePgmPath = ""
    if (matchedFile) {
        // 如果找到匹配的文件
        updatePgmPath = path.join(updateMapDir, matchedFile);
    }
    console.log("updatePgmPath", updatePgmPath);
    // 文件路径 - 更新前png
    const prePngPath = path.join(mapBufDir, "map_pre.png");
    console.log("prePngPath", prePngPath);
    // 文件路径 - 更新后png
    const updatePngPath = path.join(mapBufDir, "map_update.png");
    console.log("updatePngPath", updatePngPath);
    // 文件路径 - 更新地图压缩包
    const updateMapPath = path.join(dataDir, "update.zip");
    console.log("updateMapPath", updateMapPath);

    try {
        // 读取json文件
        const jsonData = fs.readFileSync(jsonFilePath, "utf-8");
        const parsedData = JSON.parse(jsonData);
        console.log("parsedData", parsedData);

        const mapId = parsedData["origin_pgm_id"];

        // 上传 更新前pgm
        let uploadUrl = "http://127.0.0.1:8888/map/upload/map?equipmentNo=" + equipmentNo + "&mapId=" + mapId +
            "&timeStamp=" + timeStamp ;

        // 上传文件
        // 上传 更新前pgm
        let res = await uploadMapResult(prePgmPath, uploadUrl);
        if (!res.success) {
            return { success: false, message: "Error uploading map results", data: [] }
        }
        let prePgmUrl = res.data.details
        console.log("prePgmUrl", prePgmUrl);

        // 上传 更新前png
        res = await uploadMapResult(prePngPath, uploadUrl);
        if (!res.success) {
            return { success: false, message: "Error uploading map results", data: [] }
        }
        let prePngUrl = res.data.details
        console.log("prePngUrl", prePngUrl);

        // 上传 更新后pgm
        res = await uploadMapResult(updatePgmPath, uploadUrl);
        if (!res.success) {
            return { success: false, message: "Error uploading map results", data: [] }
        }
        let updatePgmUrl = res.data.details
        console.log("updatePgmUrl", updatePgmUrl);

        // 上传 更新后png
        res = await uploadMapResult(updatePngPath, uploadUrl);
        if (!res.success) {
            return { success: false, message: "Error uploading map results", data: [] }
        }
        let updatePngUrl = res.data.details
        console.log("updatePngUrl", updatePngUrl);

        // 上传 更新地图压缩包
        res = await uploadMapResult(updateMapPath, uploadUrl);
        if (!res.success) {
            return { success: false, message: "Error uploading map results", data: [] }
        }
        let updateMapUrl = res.data.details
        console.log("updateMapUrl", updateMapUrl);

        result = {
            "jsonData": parsedData,
            "prePgmUrl": prePgmUrl,
            "prePngUrl": prePngUrl,
            "updatePgmUrl": updatePgmUrl,
            "updatePngUrl": updatePngUrl,
            "updateMapUrl": updateMapUrl,
        }

        return { success: true, message: "Evaluation results uploaded successfully", data: result }
    } catch (error) {
        console.log("error", error);
    }
})