package com.cpp.web.service.datafactory;

import cn.hutool.core.thread.ThreadFactoryBuilder;

import java.util.concurrent.*;
import java.util.Date;

public class ScheduledHelper {

    // 用于存储当前安排的任务，以便可以取消它  
    private ScheduledFuture<?> currentTask;
    // 用于调度任务的ScheduledExecutorService  
    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, new ThreadFactoryBuilder().setNamePrefix("RatioTimer-").build());


    /**
     * 在指定时间执行任务。  
     *
     * @param targetDate 任务应该执行的时间  
     * @param task       要执行的任务  
     * @throws IllegalArgumentException 如果targetDate在过去  
     */
    public synchronized void scheduleTaskAtFixedDate(Date targetDate, Runnable task) {
        // 检查目标日期是否在过去  
        long delay = targetDate.getTime() - System.currentTimeMillis();
        if (delay < 0) {
            throw new IllegalArgumentException("目标日期已过");
        }

        // 如果当前有任务正在等待执行，则取消它  
        if (currentTask != null && !currentTask.isDone()) {
            currentTask.cancel(false); // 不中断正在运行的任务（因为我们知道它还没开始）  
        }

        // 安排新任务  
        currentTask = scheduler.schedule(() -> {
            try {
                task.run();
            } finally {
                // 清除currentTask引用，以便可以安排新的任务（在finally块中确保即使任务抛出异常也能清除）  
                synchronized (this) {
                    currentTask = null;
                }
            }
        }, delay, TimeUnit.MILLISECONDS);
    }

    /**
     * 关闭scheduler（应该在不再需要时调用）  
     */
    public synchronized void shutdownScheduler() {
        // 尝试取消当前任务（尽管在关闭scheduler时这可能不是必需的）  
        if (currentTask != null && !currentTask.isDone()) {
            currentTask.cancel(true); // 这里可以中断正在运行的任务，但通常关闭scheduler时不会有任务在运行  
        }
        // 然后关闭scheduler  
        scheduler.shutdown();
        try {
            // 等待scheduler中的所有任务完成或等待超时（这里可以根据需要设置超时时间）  
            if (!scheduler.awaitTermination(60, TimeUnit.SECONDS)) {
                // 如果在超时时间内没有完成关闭，则强制关闭  
                scheduler.shutdownNow();
            }
        } catch (InterruptedException e) {
            // 如果当前线程在等待过程中被中断，则也强制关闭scheduler  
            scheduler.shutdownNow();
            Thread.currentThread().interrupt(); // 保留中断状态  
        }
    }
}