package study.datasched;

import com.xxl.job.core.executor.impl.XxlJobSimpleExecutor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * U85 教学实验执行器：真实 xxl-job-core 3.5.0（XxlJobSimpleExecutor，frameless）。
 *
 * 角色只在实验内：向本地 admin 注册、接收 /trigger、按 JobThread 队列执行、
 * 回调 handle 结果。所有观察写入 marker 目录，由 run.py 读取。
 *
 * 系统属性：
 *   lab.admin.addresses  admin 地址（逗号分隔）
 *   lab.appname          执行器 appname，必须与 admin 中执行器组一致
 *   lab.accessToken      与组 access_token 一致
 *   lab.port             内嵌 Netty 端口
 *   lab.logpath          执行器本地日志目录（仓库外）
 *   lab.marker.dir       marker 输出目录
 */
public final class ExecutorMain {

    public static void main(String[] args) throws Exception {
        String adminAddresses = System.getProperty("lab.admin.addresses", "http://127.0.0.1:18085");
        String appname = System.getProperty("lab.appname", "study-u85-executor");
        String accessToken = System.getProperty("lab.accessToken", "study_u85_token");
        int port = Integer.parseInt(System.getProperty("lab.port", "19985"));
        String logPath = System.getProperty("lab.logpath", "/tmp/study-u85-executor-logs");
        Path markerDir = Path.of(System.getProperty("lab.marker.dir", "/tmp/study-u85-markers"));
        Files.createDirectories(markerDir);
        Files.createDirectories(Path.of(logPath));

        LabJobs jobs = new LabJobs(markerDir);

        XxlJobSimpleExecutor executor = new XxlJobSimpleExecutor();
        executor.setAdminAddresses(adminAddresses);
        executor.setAppname(appname);
        executor.setAccessToken(accessToken);
        executor.setAddress("http://127.0.0.1:" + port);
        executor.setPort(port);
        executor.setLogPath(logPath);
        executor.setLogRetentionDays(3);
        executor.setGlueEnabled(false);
        executor.setXxlJobBeanList(List.of(jobs));
        executor.start();

        // 告知编排脚本执行器已起来（注册线程异步，另有 marker 由 run.py 轮询注册表确认）
        Path ready = markerDir.resolve("executor-ready-" + port + ".txt");
        Files.writeString(ready, "port=" + port + "\nappname=" + appname + "\n");
        System.out.println("U85OBSERVE executor-ready port=" + port + " appname=" + appname);

        CountDownLatch latch = new CountDownLatch(1);
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("U85OBSERVE executor-destroy begin port=" + port);
            executor.destroy();
            System.out.println("U85OBSERVE executor-destroy done port=" + port);
            latch.countDown();
        }, "lab-shutdown-" + port));
        // 主线程保活；信号退出走 shutdown hook
        while (!latch.await(1, TimeUnit.HOURS)) {
            // keep alive
        }
    }
}
