package jnpf.attendance.bean;

import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

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

/**
 * 线程池配置类
 * 根据任务类型（CPU密集、IO密集、混合）创建合适的线程池。
 */
@Configuration
public class FtbThreadPoolExecutor {
    // 队列边界
    private static final int QUEUE_CAPACITY = 200;
    // 线程存活时间 s(秒)
    private static final long KEEP_ALIVE_TIME = 15L;

    private static final String THREAD_NAME_PREFIX = "FTB服务-考勤模块";
    @Bean(name = "attendanceRuleThreadPool", destroyMethod = "shutdown")
    public ThreadPoolExecutor attendanceRuleThreadPool() {
        return createNamedThreadPool("attendance-rule", TaskType.CPU_INTENSIVE);
    }
    @Bean(name = "cpuIntensiveThreadPool", destroyMethod = "shutdown")
    public ThreadPoolExecutor cpuIntensiveThreadPool() {
        return createThreadPool(TaskType.CPU_INTENSIVE);
    }

    @Bean(name = "ioIntensiveThreadPool", destroyMethod = "shutdown")
    public ThreadPoolExecutor ioIntensiveThreadPool() {
        return createThreadPool(TaskType.IO_INTENSIVE);
    }

    @Bean(name = "mixedThreadPool", destroyMethod = "shutdown")
    public ThreadPoolExecutor mixedThreadPool() {
        return createThreadPool(TaskType.MIXED);
    }

    @Bean(name = "cultivateThreadPool", destroyMethod = "shutdown")
    public ThreadPoolExecutor cultivateThreadPool() {
        return createNamedThreadPool("cultivate-thread-v2", TaskType.IO_INTENSIVE);
    }

    private ThreadPoolExecutor createNamedThreadPool(String name, TaskType type) {
        int actualProcessors = Math.min(Runtime.getRuntime().availableProcessors(), 42);
        int runTime, cpuTime;
        switch (type) {
            case CPU_INTENSIVE:
                runTime = 10;
                cpuTime = 1;
                break;
            case IO_INTENSIVE:
                runTime = 5;
                cpuTime = 1;
                break;
            case MIXED:
            default:
                runTime = 50;
                cpuTime = 1;
                break;
        }
        int maxPoolSize = calculateMaxPoolSize(actualProcessors, runTime, cpuTime, type);
        BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(QUEUE_CAPACITY);

        return new ThreadPoolExecutor(
                actualProcessors,
                maxPoolSize,
                KEEP_ALIVE_TIME, TimeUnit.SECONDS,
                queue,
                new ThreadFactory() {
                    private final ThreadFactory defaultFactory = Executors.defaultThreadFactory();
                    private final AtomicInteger count = new AtomicInteger(1);

                    @Override
                    public Thread newThread(@NotNull Runnable r) {
                        Thread thread = defaultFactory.newThread(r);
                        thread.setName("FTB服务-考勤模块-" + name + "-thread-" + count.getAndIncrement());
                        return thread;
                    }
                },
                new ThreadPoolExecutor.CallerRunsPolicy()
        );
    }
    private ThreadPoolExecutor createThreadPool(TaskType type) {
        // 限制为实际核心数
        int actualProcessors = Math.min(Runtime.getRuntime().availableProcessors(), 42);
        int runTime, cpuTime;
        switch (type) {
            case CPU_INTENSIVE:
                runTime = 10;
                cpuTime = 1;
                break;
            case IO_INTENSIVE:
                runTime = 5;
                cpuTime = 1;
                break;
            case MIXED:
            default:
                runTime = 50;
                cpuTime = 1;
                break;
        }
        int maxPoolSize = calculateMaxPoolSize(actualProcessors, runTime, cpuTime, type);
        BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(QUEUE_CAPACITY);

        return new ThreadPoolExecutor(
                actualProcessors,
                maxPoolSize,
                KEEP_ALIVE_TIME, TimeUnit.SECONDS,
                queue,
                new ThreadFactory() {
                    private final ThreadFactory defaultFactory = Executors.defaultThreadFactory();
                    private final AtomicInteger count = new AtomicInteger(1);

                    @Override
                    public Thread newThread(@NotNull Runnable r) {
                        Thread thread = defaultFactory.newThread(r);
                        thread.setName(THREAD_NAME_PREFIX + "-" + type.name().toLowerCase() + "-thread-" + count.getAndIncrement());
                        return thread;
                    }
                },
                new ThreadPoolExecutor.CallerRunsPolicy()
        );
    }

    /**
     * 根据公式：最佳线程数 = N * (1 + (WT / ST))
     * 其中 WT = runTime - cpuTime，即线程等待时间
     *
     * @param availableProcessors CPU核心数
     * @param runTime             线程总运行时间（单位可自定，如毫秒）
     * @param cpuTime             线程CPU计算时间
     * @return 最佳线程池大小
     */
    private int calculateMaxPoolSize(int availableProcessors, int runTime, int cpuTime, TaskType type) {
        if (cpuTime <= 0) {
            throw new IllegalArgumentException("参数不合法：cpuTime 应大于 0");
        }
        if (type == TaskType.IO_INTENSIVE) {
            // I/O 密集型：4 倍核心数，上限 200
            return Math.min(availableProcessors * 4, 200);
        } else if (type == TaskType.CPU_INTENSIVE) {
            // CPU 密集型：等于核心数
            return availableProcessors;
        } else {
            // 混合型
            long ratio = 1L + (long) runTime / cpuTime;
            long calculated = (long) availableProcessors * ratio;
            return (int) Math.min(calculated, 200);
        }
    }

    public enum TaskType {
        CPU_INTENSIVE,
        IO_INTENSIVE,
        MIXED
    }
}
