package com.ecep.contract.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicInteger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.ecep.contract.SpringApp;
import com.ecep.contract.TaskStatus;
import com.ecep.contract.ui.Tasker;

import lombok.Getter;

/**
 * 任务监控中心 - 统一管理所有异步任务
 */
@Component
public class TaskMonitorCenter {
    private static final Logger logger = LoggerFactory.getLogger(TaskMonitorCenter.class);

    // 正在运行的任务列表
    @Getter
    private final List<MonitoredTask<?>> activeTasks = new ArrayList<>();
    // 任务ID映射
    private final Map<String, MonitoredTask<?>> taskMap = new ConcurrentHashMap<>();
    // 任务计数器
    private final AtomicInteger taskCounter = new AtomicInteger(0);
    /**
     * 注册并启动任务
     */
    public <T> MonitoredTask<T> registerTask(Tasker<T> task) {
        return registerTask(task, null);
    }

    /**
     * 注册并启动任务，支持设置超时时间
     */
    public <T> MonitoredTask<T> registerTask(Tasker<T> task, Long timeoutSeconds) {
        String taskId = generateTaskId();
        MonitoredTask<T> monitoredTask = new MonitoredTask<>(task, taskId);

        // 设置超时处理
        if (timeoutSeconds != null && timeoutSeconds > 0) {
            monitoredTask.setTimeout(timeoutSeconds);
        }

        // 添加任务状态变更监听器
        monitoredTask.setOnSucceeded(() -> {
            if (logger.isInfoEnabled()) {
                logger.info("任务[{}]执行成功: {}", taskId, monitoredTask.getTitle());
            }
            recordHistory(monitoredTask, TaskStatus.SUCCEEDED);
            removeActiveTask(monitoredTask);
        });

        monitoredTask.setOnFailed(() -> {
            if (logger.isErrorEnabled()) {
                logger.error("任务[{}]执行失败: {}", taskId, monitoredTask.getTitle(),
                        monitoredTask.getException());
            }
            recordHistory(monitoredTask, TaskStatus.FAILED);
            removeActiveTask(monitoredTask);
        });

        monitoredTask.setOnCancelled(() -> {
            if (logger.isInfoEnabled()) {
                logger.info("任务[{}]被取消: {}", taskId, monitoredTask.getTitle());
            }
            recordHistory(monitoredTask, TaskStatus.CANCELLED);
            removeActiveTask(monitoredTask);
        });

        // 保存任务引用并启动
        taskMap.put(taskId, monitoredTask);
        activeTasks.add(monitoredTask);

        if (logger.isInfoEnabled()) {
            logger.info("任务[{}]已注册并启动: {}", taskId, monitoredTask.getTitle());
        }
        return monitoredTask;
    }

    /**
     * 取消任务
     */
    public boolean cancelTask(String taskId) {
        MonitoredTask<?> task = taskMap.get(taskId);
        if (task != null && task.isRunning()) {
            task.cancel();
            return true;
        }
        return false;
    }

    /**
     * 取消所有任务
     */
    public void cancelAllTasks() {
        for (MonitoredTask<?> task : new ArrayList<>(activeTasks)) {
            task.cancel();
        }
    }

    /**
     * 从活动列表中移除任务
     */
    private void removeActiveTask(MonitoredTask<?> task) {
        activeTasks.remove(task);
        taskMap.remove(task.getTaskId());
    }

    /**
     * 记录任务历史
     */
    private void recordHistory(MonitoredTask<?> task, TaskStatus status) {
        TaskHistory history = new TaskHistory(
                task,
                status,
                System.currentTimeMillis(), null);

        // saved in db
    }

    /**
     * 生成任务ID
     */
    private String generateTaskId() {
        return "task-" + UUID.randomUUID().toString().substring(0, 8) + "-" + taskCounter.incrementAndGet();
    }

    public <T> void registerAndStartTask(Tasker<T> task) {
        MonitoredTask<T> registerTask = registerTask(task);
        getExecutorService().submit(registerTask);
    }

    ScheduledExecutorService getExecutorService() {
        return SpringApp.getBean(ScheduledExecutorService.class);
    }
}