package com.qqchen.deploy.backend.workflow.delegate;

import com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants;
import com.qqchen.deploy.backend.workflow.dto.definition.node.localVariables.ScriptNodeLocalVariables;
import com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables.ScriptNodePanelVariables;
import com.qqchen.deploy.backend.workflow.enums.NodeLogTypeEnums;
import com.qqchen.deploy.backend.workflow.dto.event.ShellLogEvent;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.delegate.BpmnError;
import org.flowable.engine.delegate.DelegateExecution;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Shell脚本任务的委派者实现
 */
@Slf4j
@Component
public class ShellNodeDelegate extends BaseNodeDelegate<ScriptNodePanelVariables, ScriptNodeLocalVariables> {

    @Resource
    private ApplicationEventPublisher eventPublisher;

    // 用于存储实时输出的Map
    private static final Map<String, StringBuilder> outputMap = new ConcurrentHashMap<>();

    private static final Map<String, StringBuilder> errorMap = new ConcurrentHashMap<>();

    @Override
    protected Class<ScriptNodePanelVariables> getPanelVariablesClass() {
        return ScriptNodePanelVariables.class;
    }

    @Override
    protected Class<ScriptNodeLocalVariables> getLocalVariablesClass() {
        return ScriptNodeLocalVariables.class;
    }

    @Override
    protected void executeInternal(DelegateExecution execution,
                                   ScriptNodePanelVariables panelVariables,
                                   ScriptNodeLocalVariables localVariables) {
        if (panelVariables == null || panelVariables.getScript() == null) {
            throw new BpmnError(WorkFlowConstants.WORKFLOW_EXEC_ERROR, "Script is required but not provided");
        }

//        try {
//            log.info("准备执行脚本: {}", panelVariables.getScript());
//            // 使用processInstanceId而不是executionId
//            String processInstanceId = execution.getProcessInstanceId();
//            outputMap.put(processInstanceId, new StringBuilder());
//            errorMap.put(processInstanceId, new StringBuilder());
//
//            // 创建进程构建器
//            ProcessBuilder processBuilder = new ProcessBuilder();
//
//            // 根据操作系统选择合适的shell
//            String os = System.getProperty("os.name").toLowerCase();
//            if (os.contains("win")) {
//                // Windows系统使用cmd
//                processBuilder.command("cmd", "/c", panelVariables.getScript());
//            } else {
//                // Unix-like系统使用bash
//                processBuilder.command("bash", "-c", panelVariables.getScript());
//            }
//
//            // 设置工作目录
//            if (StringUtils.hasText(localVariables.getWorkDir())) {
//                // Windows系统路径处理
//                String workDirValue = localVariables.getWorkDir();
//                if (os.contains("win")) {
//                    // 确保使用Windows风格的路径分隔符
//                    workDirValue = workDirValue.replace("/", "\\");
//                    // 如果路径以\开头，去掉第一个\
//                    if (workDirValue.startsWith("\\")) {
//                        workDirValue = workDirValue.substring(1);
//                    }
//                }
//                File workDirFile = new File(workDirValue);
//                if (!workDirFile.exists()) {
//                    workDirFile.mkdirs();
//                }
//                processBuilder.directory(workDirFile);
//            }
//
//            // 设置环境变量
//            if (localVariables.getEnv() != null) {
//                processBuilder.environment().putAll(localVariables.getEnv());
//            }
//
//            // 执行命令
//            log.info("执行shell脚本: {}", panelVariables.getScript());
//            Process process = processBuilder.start();
//
//            // 创建线程池处理输出
//            ExecutorService executorService = Executors.newFixedThreadPool(2);
//
//            // 处理标准输出
//            Future<?> outputFuture = executorService.submit(() ->
//                processInputStream(process.getInputStream(), processInstanceId, NodeLogTypeEnums.STDOUT));
//
//            // 处理错误输出
//            Future<?> errorFuture = executorService.submit(() ->
//                processInputStream(process.getErrorStream(), processInstanceId, NodeLogTypeEnums.STDERR));
//
//            // 等待进程完成
//            int exitCode = process.waitFor();
//
//            // 等待输出处理完成
//            outputFuture.get(5, TimeUnit.SECONDS);
//            errorFuture.get(5, TimeUnit.SECONDS);
//
//            // 关闭线程池
//            executorService.shutdown();
//
//            // 设置最终结果
//            StringBuilder finalOutput = outputMap.get(processInstanceId);
//            StringBuilder finalError = errorMap.get(processInstanceId);
//
//            execution.setVariable("shellOutput", finalOutput.toString());
//            execution.setVariable("shellError", finalError.toString());
//            execution.setVariable("shellExitCode", exitCode);
//
//            // 清理缓存
//            outputMap.remove(processInstanceId);
//            errorMap.remove(processInstanceId);
//
//            if (exitCode != 0) {
//                log.error("Shell脚本执行失败，退出码: {}", exitCode);
//                execution.setVariable("errorDetail", "Shell脚本执行失败，退出码: " + exitCode);
//                throw new BpmnError(WorkFlowConstants.WORKFLOW_EXEC_ERROR, "Shell脚本执行失败，退出码: " + exitCode);
//            }
//            log.info("Shell脚本执行成功");
//            log.debug("脚本输出: {}", finalOutput);
//
//        } catch (Exception e) {
//            log.error("Shell脚本执行失败", e);
//            throw new BpmnError(WorkFlowConstants.WORKFLOW_EXEC_ERROR, e.getMessage());
//        }
    }

    private void processInputStream(InputStream inputStream, String processInstanceId, NodeLogTypeEnums logType) {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
            String line;
            while ((line = reader.readLine()) != null) {
                // 发布日志事件
                eventPublisher.publishEvent(new ShellLogEvent(processInstanceId, line, logType));

                // 同时保存到StringBuilder中
                if (logType == NodeLogTypeEnums.STDOUT) {
                    StringBuilder output = outputMap.get(processInstanceId);
                    synchronized (output) {
                        output.append(line).append("\n");
                    }
//                    log.info("Shell output: {}", line);
                } else {
                    StringBuilder error = errorMap.get(processInstanceId);
                    synchronized (error) {
                        error.append(line).append("\n");
                    }
//                    log.error("Shell error: {}", line);
                }
            }
        } catch (IOException e) {
            log.error("Error reading process output", e);
        }
    }
}
