package com.ruoshui.core.util;

import com.ruoshui.core.log.JobLogger;
import com.ruoshui.core.thread.JobThread;
import com.sun.jna.Platform;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;

/**
 * ProcessUtil
 *
 * @author jingwk
 * @version 1.0
 * @since 2019/11/09
 */

public class ProcessUtil {

    private static Logger logger = LoggerFactory.getLogger(JobThread.class);

    public static String getProcessId(Process process) {
        long pid = -1;
        Field field;

        if (Platform.isWindows()) {
            try {
                field = process.getClass().getDeclaredField("handle");
                field.setAccessible(true);
                pid = Kernel32.INSTANCE.GetProcessId((Long) field.get(process));
            } catch (Exception ex) {
                logger.error("get process id for windows error {0}", ex);
            }
        } else if (Platform.isLinux() || Platform.isAIX()) {
            // 方式一：系统属性
            logger.info("JDK Version: {}", System.getProperty("java.version"));

            // 方式二：Runtime.version() (Java 9+)
            logger.info("JDK Version2: {}", Runtime.version());  
                    
            try {
                // Class<?> clazz = Class.forName("java.lang.UNIXProcess");
                // field = clazz.getDeclaredField("pid");
                // field.setAccessible(true);
                // pid = (Integer) field.get(process);
                // 服务器上的jdk版本大于8 ，不兼容当前的模式
                String processName = process.getClass().getName();
                logger.info("processName: {}", processName);

                if (processName.equals("java.lang.UNIXProcess")) {
                    try {
                        // 仅Java 8兼容：保留原逻辑（可选）
                        Field pidField = process.getClass().getDeclaredField("pid");
                        pidField.setAccessible(true);
                        pid = pidField.getLong(process);
                    } catch (Exception e) {
                        logger.error("jdk8-erro-get process id for unix error {0}", e);
                        throw new RuntimeException("获取进程ID失败", e);
                    }
                } else if (process instanceof ProcessHandle) {
                     logger.error("java9+process instanceof ProcessHandle ");
                    // Java 9+ 推荐方式：ProcessHandle API
                    pid = ((ProcessHandle) process).pid();
                } else {
                    // 目前服务器上的docker JDK 11 方案：使用实际进程类反射获取 pid
                    Class<?> clazz = process.getClass();
                    Field declaredField = clazz.getDeclaredField("pid");
                    declaredField.setAccessible(true);
                    pid = declaredField.getLong(process);
                }
            }  catch (Throwable e) {
                logger.error("get process id for unix error ", e);
                throw new UnsupportedOperationException("不支持当前JDK的进程ID获取");
            }
        }
        return String.valueOf(pid);
    }

    /**
     * 关闭Linux进程
     *
     * @param pid 进程的PID
     */
    public static boolean killProcessByPid(String pid) {
        if (StringUtils.isEmpty(pid) || "-1".equals(pid)) {
            throw new RuntimeException("Pid ==" + pid);
        }
        Process process = null;
        BufferedReader reader = null;
        String command = "";
        boolean result;
        if (Platform.isWindows()) {
            command = "cmd.exe /c taskkill /PID " + pid + " /F /T ";
        } else if (Platform.isLinux() || Platform.isAIX()) {
            command = "kill " + pid;
        }
        try {
            // 杀掉进程
            process = Runtime.getRuntime().exec(command);
            reader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8));
            String line;
            while ((line = reader.readLine()) != null) {
                JobLogger.log(line);
            }
            result = true;
        } catch (Exception e) {
            logger.error("kill pid error {0}", e);
            result = false;
        } finally {
            if (process != null) {
                process.destroy();
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    logger.error("reader close error {0}", e);
                }
            }
        }
        return result;
    }

}
