package com.seer.teach.teacher.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.*;

/**
 * 用户学习定时器任务管理器
 * <p>
 * 功能：
 * - 支持为每个用户注册定时器任务（仅保存，不执行）
 * - 可按需启动、取消、判断是否存在任务
 * - 定时器结束后执行指定的回调逻辑
 */
@Slf4j
@Service
public class ReadCountdownManagerService {

    /**
     * 定时任务线程池
     */
    private final ScheduledExecutorService scheduler =
            Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors() * 2);

    /**
     * 存放用户的待执行任务
     * key：userId
     * value：待执行的任务（包装了 delaySeconds 和 action）
     */
    private final Map<Integer, CountdownTask> countdownTaskMap = new ConcurrentHashMap<>();

    /**
     * 存放正在执行的调度任务（用户 → ScheduledFuture）
     */
    private final Map<Integer, ScheduledFuture<?>> runningTasks = new ConcurrentHashMap<>();

    /**
     * 注册一个用户的定时器任务（仅保存，不立即执行）
     *
     * @param userId       用户ID
     * @param delaySeconds 延迟时间（秒）
     * @param action       定时器结束执行的逻辑
     */
    public void registerCountdown(Integer userId, int delaySeconds, Runnable action) {
        cancelCountdown(userId);
        countdownTaskMap.put(userId, new CountdownTask(delaySeconds, action));
        log.info("阅读定时器 已为用户 {} 注册 {} 秒（未启动）", userId, delaySeconds);
    }

    /**
     * 启动指定用户的定时器任务（如果存在）
     *
     * @param userId 用户ID
     */
    public void startCountdown(Integer userId) {
        // 如果该用户没有注册任务，则忽略
        CountdownTask taskInfo = countdownTaskMap.get(userId);
        if (taskInfo == null) {
            log.warn("阅读定时器  用户 {} 没有已注册的定时器任务", userId);
            return;
        }

        // 如果任务已经在执行，先取消旧的
        cancelCountdown(userId);

        log.info("阅读定时器  用户 {} 开始执行 {} 秒定时器", userId, taskInfo.delaySeconds);

        // 启动定时器
        ScheduledFuture<?> scheduledFuture = scheduler.schedule(() -> {
            try {
                log.info("阅读定时器  用户 {} 定时器结束，开始执行任务", userId);
                taskInfo.action.run();
            } catch (Exception e) {
                log.error("阅读定时器  用户 {} 定时器任务执行异常", userId, e);
            } finally {
                runningTasks.remove(userId);
                countdownTaskMap.remove(userId);
            }
        }, taskInfo.delaySeconds, TimeUnit.SECONDS);

        runningTasks.put(userId, scheduledFuture);
    }

    /**
     * 判断指定用户是否已有注册的定时器任务
     *
     * @param userId 用户ID
     * @return true=有任务；false=无任务
     */
    public boolean hasCountdown(Integer userId) {
        return countdownTaskMap.containsKey(userId);
    }

    /**
     * 取消指定用户的定时器任务（无论是否执行中）
     *
     * @param userId 用户ID
     */
    public void cancelCountdown(Integer userId) {
        // 取消执行中的任务
        ScheduledFuture<?> running = runningTasks.remove(userId);
        if (running != null && !running.isDone()) {
            running.cancel(false);
            log.info("阅读定时器  用户 {} 执行中的定时器任务已取消", userId);
        }

        // 移除注册任务
        if (countdownTaskMap.remove(userId) != null) {
            log.info("阅读定时器  用户 {} 已移除注册的定时器任务", userId);
        }
    }

    /**
     * 关闭所有定时器任务并释放资源
     */
    public void shutdown() {
        scheduler.shutdownNow();
        countdownTaskMap.clear();
        runningTasks.clear();
        log.info("阅读定时器  已清理所有定时器任务");
    }

    /**
     * 定时器任务信息封装类
     */
    private static class CountdownTask {
        final int delaySeconds;
        final Runnable action;

        CountdownTask(int delaySeconds, Runnable action) {
            this.delaySeconds = delaySeconds;
            this.action = action;
        }
    }
}
