package cn.axzo.workflow.server.common.util;

import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.Objects;

/**
 * 一个一次性 JVM 外部进程执行，并返回结果的 Shell 工具
 *
 * @author wangli
 * @since 2024-10-22 15:05
 */
@Slf4j
public class ShellUtil {

    private ShellUtil() {
    }

    public static String grepDateLog(String profile, String keyword, String dateStr) {
        return grepLog(profile, keyword, DateUtil.parseDate(dateStr), null);
    }

    public static String grepDateLog(String profile, String keyword, Date date) {
        return grepLog(profile, keyword, date, null);
    }

    public static String grepTodayLog(String profile, String keyword) {
        return grepLog(profile, keyword, new Date(), null);
    }

    /**
     * 入参示例 zgrep '9812ea104cf643c4908e772a46abac17' workflowEngine.log | grep 'checkDeath()'
     * @param profile 环境
     * @param keyword 具体的命令
     * @return
     */
    public static String grepRealTimeLog(String profile, String keyword) {
        return grepLog(profile, keyword, null, null);
    }

    /**
     *
     * @param profile
     * @param keyword
     * @param date
     * @param grepKeyword
     * @return
     */
    public static String grepLog(String profile, String keyword, Date date, String grepKeyword) {
        return executeCmd("cd " + getLogPath(profile) + " && zgrep '" + keyword + "' workflowEngine.log" +
                (Objects.nonNull(date) ? "." + DateUtil.formatDate(date) + ".*" : "") +
                (StringUtils.hasText(grepKeyword) ? " | grep '" + grepKeyword + "'": "")
        );
    }

    /**
     * 入参示例 cd /mnt/app-logdata/java-dev/workflowEngine && zgrep '9812ea104cf643c4908e772a46abac17' workflowEngine.log | grep 'checkDeath()'
     * @param fullCommand
     * @return
     */
    private static String executeCmd(String fullCommand) {
        if (!StringUtils.hasText(fullCommand)) {
            return "命令不能为空";
        }
        try {
            ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", fullCommand);
            Process process = pb.start();
            InputStream inputStream = process.getInputStream();
            InputStream errorStream = process.getErrorStream();

            StringBuilder outputBuilder = new StringBuilder();
            // 读取命令输出的线程
            Thread outputReader = new Thread(() -> {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        outputBuilder.append(line).append("\n");
                    }
                } catch (IOException e) {
                    log.warn("outputReader 发生异常: {}", e.getMessage(), e);
                }
            });
            outputReader.start();

            // 读取命令错误输出的线程
            Thread errorReader = new Thread(() -> {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        outputBuilder.append("Error: ").append(line).append("\n");
                    }
                } catch (IOException e) {
                    log.warn("errorReader 发生异常: {}", e.getMessage(), e);
                }
            });
            errorReader.start();

            // 等待命令执行完成
            outputReader.join();
            errorReader.join();

            return outputBuilder.toString();
        } catch (IOException | InterruptedException e) {
            log.error("Execute command 发生异常: {}", e.getMessage(), e);
            return "Error executing command.";
        }
    }

    public static String getLogPath(String profile) {
        String logSegment = profile;
        if (Objects.equals("dev", profile)) {
            logSegment = "java-dev";
        }
        return "/mnt/app-logdata/" + logSegment + "/workflowEngine/";
    }
}
