package com.seer.teach.teacher.common.utils;

import jakarta.annotation.PreDestroy;
import java.util.Map;
import java.util.concurrent.*;

/**
 * 倒计时执行工具类
 * 提供基于用户ID的延迟任务调度和取消功能，确保同一用户只能有一个正在运行的倒计时任务
 */
public class CountdownExecutorUtil {

    /**
     * 单线程调度执行器，用于执行延迟任务
     * 线程设置为守护线程，命名为"static-delay-executor"
     */
    private static final ScheduledExecutorService SCHEDULER =
            Executors.newScheduledThreadPool(8, r -> {
                Thread t = new Thread(r, "static-delay-executor");
                t.setDaemon(true);
                return t;
            });

    /**
     * 存储用户ID与对应调度任务的映射关系
     * 使用ConcurrentHashMap保证线程安全
     */
    private static final Map<Integer, ScheduledFuture<?>> FUTURE_MAP = new ConcurrentHashMap<>();



    /**
     * 启动一个倒计时任务
     * 如果该用户已存在正在运行的任务，则先取消旧任务再启动新任务
     *
     * @param userId 用户唯一标识
     * @param delaySeconds 延迟执行的秒数
     * @param task 需要执行的任务
     */
    public static void start(Integer userId, Integer delaySeconds, Runnable task) {
        // 先取消该用户已存在的任务
        cancel(userId);

        // 调度新的延迟任务
        ScheduledFuture<?> future = SCHEDULER.schedule(() -> {
            try {
                task.run();
            } finally {
                // 任务执行完成后从映射中移除
                FUTURE_MAP.remove(userId);
            }
        }, delaySeconds, TimeUnit.SECONDS);

        // 将新任务存入映射
        FUTURE_MAP.put(userId, future);
    }

    /**
     * 取消指定用户的倒计时任务
     *
     * @param userId 用户唯一标识
     * @return true-成功取消任务，false-未找到对应任务或任务已执行完成
     */
    public static boolean cancel(Integer userId) {
        ScheduledFuture<?> future = FUTURE_MAP.remove(userId);
        if (future != null) {
            return future.cancel(false);
        }
        return false;
    }


    /**
     * 应用销毁时关闭调度器并清理所有任务
     * 该方法在Spring容器销毁Bean时自动调用
     */
    @PreDestroy
    public void shutdown() {
        SCHEDULER.shutdownNow();
        FUTURE_MAP.clear();
    }
}

