package org.xyzh.crontab.task;

import org.xyzh.crontab.pojo.TaskParams;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @description 命令行任务抽象类
 * @filename CommandTask.java
 * @author yslg
 * @copyright xyzh
 * @since 2025-11-10
 */
public abstract class CommandTask extends BaseTask {

    /**
     * 执行命令行任务
     */
    @Override
    protected void doExecute(TaskParams taskParams) throws Exception {
        // 获取工作目录
        String workingDir = getWorkingDirectory(taskParams);
        Path workDir = Paths.get(workingDir);

        if (!Files.exists(workDir)) {
            throw new RuntimeException("工作目录不存在: " + workingDir);
        }

        // 构建命令
        List<String> command = buildCommand(taskParams);
        logger.info("执行命令: {}", String.join(" ", command));

        // 创建进程构建器
        ProcessBuilder processBuilder = new ProcessBuilder(command);
        processBuilder.directory(workDir.toFile());
        processBuilder.redirectErrorStream(true);

        // 设置环境变量强制Python使用UTF-8编码(解决Windows GBK编码问题)
        Map<String, String> env = processBuilder.environment();
        env.put("PYTHONIOENCODING", "utf-8");  // Python I/O编码
        env.put("PYTHONUTF8", "1");             // Python 3.7+ UTF-8模式

        // 启动进程
        Process process = processBuilder.start();

        // 读取输出
        StringBuilder output = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(process.getInputStream(), "UTF-8"))) {
            String line;
            while ((line = reader.readLine()) != null) {
                output.append(line).append("\n");
                logger.debug("命令输出: {}", line);
            }
        }

        // 等待进程结束
        int timeout = getTimeout(taskParams);
        boolean finished = process.waitFor(timeout, TimeUnit.SECONDS);

        if (!finished) {
            process.destroy();
            throw new RuntimeException("命令执行超时（超过" + timeout + "秒）");
        }

        int exitCode = process.exitValue();

        if (exitCode == 0) {
            logger.info("命令执行成功");
            // 处理执行结果
            handleResult(taskParams, output.toString());
        } else {
            logger.error("命令执行失败，退出码: {}", exitCode);
            logger.error("输出内容:\n{}", output.toString());
            throw new RuntimeException("命令执行失败，退出码: " + exitCode);
        }
    }

    /**
     * 获取工作目录（由子类实现）
     */
    protected abstract String getWorkingDirectory(TaskParams taskParams);

    /**
     * 构建命令（由子类实现）
     */
    protected abstract List<String> buildCommand(TaskParams taskParams) throws Exception;

    /**
     * 获取超时时间（秒）
     */
    protected int getTimeout(TaskParams taskParams) {
        return 300; // 默认5分钟
    }

    /**
     * 处理执行结果（由子类实现）
     */
    protected abstract void handleResult(TaskParams taskParams, String output) throws Exception;
}
