package com.czg.utils;

import org.jetbrains.annotations.NotNull;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * Java 21 异步多任务执行工具类
 * 功能：异步执行多个任务，等待所有任务完成后统一返回结果（包含成功/失败信息）
 * 特性：基于虚拟线程、支持泛型、完善的异常处理、可自定义线程池
 *
 * @author yjjie
 * @date 2026/1/6 18:21
 */
public class AsyncTaskExecutor {

    // 默认线程池：Java 21 虚拟线程池（轻量级、高并发）
    private static final ExecutorService DEFAULT_EXECUTOR = Executors.newVirtualThreadPerTaskExecutor();

    /**
     * 执行多个异步任务，等待所有任务完成后统一返回结果
     *
     * @param tasks 任务列表（每个任务是一个 Supplier 函数式接口，封装具体业务逻辑）
     * @param <T>   任务返回值类型
     * @return 所有任务的执行结果（包含成功/失败信息）
     */
    public static <T> List<TaskResult<T>> executeAll(List<Supplier<T>> tasks) {
        return executeAll(tasks, DEFAULT_EXECUTOR);
    }

    /**
     * 执行多个异步任务（自定义线程池），等待所有任务完成后统一返回结果
     *
     * @param tasks    任务列表
     * @param executor 自定义线程池（如需要使用传统线程池可传入）
     * @param <T>      任务返回值类型
     * @return 所有任务的执行结果
     */
    public static <T> List<TaskResult<T>> executeAll(List<Supplier<T>> tasks, ExecutorService executor) {
        // 校验入参
        if (tasks == null || tasks.isEmpty()) {
            return List.of();
        }
        if (executor == null) {
            throw new IllegalArgumentException("线程池不能为null");
        }

        // 1. 提交所有异步任务，获取CompletableFuture列表
        List<CompletableFuture<TaskResult<T>>> futureList = tasks.stream()
                .map(task -> CompletableFuture.supplyAsync(
                        () -> executeSingleTask(task),
                        executor
                ))
                .collect(Collectors.toList());

        // 2. 等待所有任务完成（无超时）
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(
                futureList.toArray(new CompletableFuture[0])
        );

        try {
            // 阻塞等待所有任务完成（可根据业务需求添加超时，如 allFutures.get(10, TimeUnit.SECONDS)）
            allFutures.get();
        } catch (Exception e) {
            // 全局等待异常（如超时、中断），标记所有未完成的任务为失败
            handleGlobalException(futureList, e);
        }

        // 3. 收集所有任务结果
        return futureList.stream()
                // 显式指定泛型类型，让编译器明确知道map的返回类型是TaskResult<T>
                .<TaskResult<T>>map(future -> {
                    try {
                        // 这里强制指定泛型，避免类型推断模糊
                        return future.get();
                    } catch (Exception e) {
                        // 理论上不会走到这里，因为singleTask已捕获异常，allOf已等待完成
                        return new TaskResult<>(null, false, "结果收集异常：" + e.getMessage());
                    }
                })
                .collect(Collectors.toList());
    }

    /**
     * 执行单个任务，捕获任务执行过程中的异常
     */
    private static <T> TaskResult<T> executeSingleTask(Supplier<T> task) {
        try {
            T result = task.get();
            return new TaskResult<>(result, true, null);
        } catch (Exception e) {
            // 捕获单个任务的所有异常，封装为失败结果
            return new TaskResult<>(null, false, "任务执行失败：" + e.getMessage());
        }
    }

    /**
     * 处理全局等待过程中的异常（如超时、中断），标记未完成任务为失败
     */
    private static <T> void handleGlobalException(List<CompletableFuture<TaskResult<T>>> futureList, Exception e) {
        String errorMsg = "全局等待异常：" + e.getMessage();
        futureList.forEach(future -> {
            if (!future.isDone()) {
                // 取消未完成的任务，并标记为失败
                future.complete(new TaskResult<>(null, false, errorMsg));
            }
        });
        // 恢复线程中断状态（如果是中断异常）
        if (e instanceof InterruptedException) {
            Thread.currentThread().interrupt();
        }
    }

    /**
     * 任务结果封装类
     * 包含：返回值、是否成功、失败信息
     *
     * @param <T>      结果类型
     * @param result   Getter 方法 任务返回值（成功时非null）
     * @param success  是否执行成功
     * @param errorMsg 失败信息（失败时非null）
     */
    public record TaskResult<T>(T result, boolean success, String errorMsg) {

        // 重写toString，方便打印结果
        @NotNull
        @Override
        public String toString() {
            if (success) {
                return "TaskResult{success=true, result=" + result + "}";
            } else {
                return "TaskResult{success=false, errorMsg='" + errorMsg + "'}";
            }
        }
    }

    /**
     * 关闭默认线程池（可选，如应用退出时调用）
     */
    public static void shutdownDefaultExecutor() {
        DEFAULT_EXECUTOR.shutdown();
        try {
            if (!DEFAULT_EXECUTOR.awaitTermination(5, TimeUnit.SECONDS)) {
                DEFAULT_EXECUTOR.shutdownNow();
            }
        } catch (InterruptedException e) {
            DEFAULT_EXECUTOR.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}
