package com.yeechart.dotMatrix.thread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Service
public class RetryService {

    Logger logger = LoggerFactory.getLogger(RetryService.class);
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5);
    private final ConcurrentHashMap<Runnable, AtomicInteger> retryCountMap = new ConcurrentHashMap<>();

    // 核心线程数，基于CPU核心数的两倍，适合大多数并发场景
    private static final int MAX_RETIES = 5;
    // 基础重试间隔，单位秒
    private static final int BASE_DELAY = 1;
    // 重试间隔乘数
    private static final double BACKOFF_MULTIPLIER = 1.5;
    public interface TaskSubmitCallback {
        void onTaskSubmitted();
    }

    /**
     * 动态调整重试间隔的计算方法
     * @param retryCount 重试次数
     * @return 计算后的重试延迟时间
     */
    private long calculateDelay(int retryCount) {
        return (long)(BASE_DELAY * Math.pow(BACKOFF_MULTIPLIER, retryCount - 1));
    }
    /**
     * 重试 进入线程池
     * @param task 线程
     * @param initialDelay  开始延时的时间
     * @param unit  延迟的时间单位
     * @param callback  回调
     * @return
     */
    public ScheduledFuture<?> scheduleRetry(Runnable task, long initialDelay, TimeUnit unit, TaskSubmitCallback callback) {
        AtomicInteger count = retryCountMap.computeIfAbsent(task, k -> new AtomicInteger(0));
        if (count.getAndIncrement() >= MAX_RETIES) {
            logger.error("  count.getAndIncrement() >= MAX_RETIES  是 重试调用线程池 超出次数: " + task);
            retryCountMap.remove(task);
            return null;
        }
        long delay = calculateDelay(count.get());
        ScheduledFuture<?> future = scheduler.schedule(() -> {
            try {
                logger.error("拒绝策略 排队成功：{}", task.toString());
                task.run();
                // 任务成功执行，通过回调清除重试记录
                if (callback != null) {
                    callback.onTaskSubmitted();
                }
            } catch (Exception e) {
                if (count.get() < MAX_RETIES) {
                    logger.warn("任务执行失败，安排重试第{}次: {}", count.get(), task);
                    scheduleRetry(task, delay, unit, callback);
                } else {
                    logger.error("  count.get() < MAX_RETIES  否  任务最终重试失败: " + task);
                }
            }
        }, initialDelay, unit);
        return future;
    }

    public void cancelRetry(Runnable task) {
        AtomicInteger count = retryCountMap.remove(task);
        if (count != null) {
            // 取消所有与该任务相关的未来重试
            logger.error("取消 重试调用线程池  " + task);
        }
    }
}


