package com.test.test.task;

import com.test.test.domain.TestTask;
import com.test.test.domain.qo.GroupIdQO;
import com.test.test.service.ITestTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

/**
 * 定时任务管理器
 * 负责调度和执行定时任务
 */
@Slf4j
@Component
public class TestTaskManager {

    @Resource
    private ITestTaskService testTaskService;

    @Resource
    private TaskScheduler taskScheduler;

    @Value("${test.jmeterHomePath:/opt/apache-jmeter}")
    private String jmeterHomePath;

    // 用于存储正在运行的任务
    private final Map<Long, ScheduledFuture<?>> scheduledTasks = new ConcurrentHashMap<>();

    @PostConstruct
    public void init() {
        loadTasks(); // 初始化时加载所有启用的定时任务
    }

    /**
     * 初始加载所有启用的定时任务
     */
    private void loadTasks() {
        try {
            GroupIdQO qo = new GroupIdQO();
            List<TestTask> tasks = testTaskService.selectTestTaskList(qo);
            if (tasks != null) {
                tasks.stream()
                    .filter(task -> task != null 
                        && task.getStatus() != null 
                        && task.getStatus() == 0 
                        && "0".equals(task.getDelFlag()))
                    .forEach(this::scheduleTask);
            }
        } catch (Exception e) {
            log.error("加载定时任务失败", e);
        }
    }

    /**
     * 更新任务
     */
    public void updateTask(TestTask task) {
        log.info("更新任务 {}", task.getId());
        Long taskId = task.getId();
        
        // 先取消现有任务
        if (scheduledTasks.containsKey(taskId)) {
            scheduledTasks.get(taskId).cancel(true);
            scheduledTasks.remove(taskId);
        }

        // 如果任务状态是启用且没有被删除，则重新调度
        if (task.getStatus() == 0 && "0".equals(task.getDelFlag())) {
            log.info("启动任务:{}", task.getId());
            scheduleTask(task);
        }
    }

    /**
     * 添加新任务到定时调度
     */
    public void addNewTask(TestTask task) {
        // 只有当任务状态是启用且没有被删除时才创建定时任务
        if (task.getStatus() == 0 && "0".equals(task.getDelFlag())) {
            log.info("加入定时任务:{}", task.getId());
            scheduleTask(task);
        }
    }

    /**
     * 移除定时任务
     */
    public void removeTask(Long taskId) {
        if (scheduledTasks.containsKey(taskId)) {
            scheduledTasks.get(taskId).cancel(true);
            scheduledTasks.remove(taskId);
            log.info("已移除定时任务: {}", taskId);
        }
    }

    /**
     * 批量移除定时任务
     */
    public void removeTasks(Long[] taskIds) {
        for (Long taskId : taskIds) {
            removeTask(taskId);
        }
    }

    /**
     * 调度单个任务
     */
    private void scheduleTask(TestTask task) {
        try {
            if (task.getCrontab() == null || task.getCrontab().trim().isEmpty()) {
                log.error("任务 [{}] 的cron表达式为空", task.getName());
                return;
            }

            CronTrigger trigger = new CronTrigger(task.getCrontab());
            ScheduledFuture<?> future = taskScheduler.schedule(
                () -> executeTask(task), trigger
            );
            scheduledTasks.put(task.getId(), future);
            log.info("成功调度任务: {}", task.getName());
        } catch (IllegalArgumentException e) {
            log.error("无效的cron表达式: " + task.getCrontab(), e);
        } catch (Exception e) {
            log.error("调度任务时发生错误: " + task.getName(), e);
        }
    }

    /**
     * 执行单个任务
     */
    private void executeTask(TestTask task) {
        try {
            log.info("开始执行任务: {}", task.getName());
            testTaskService.executeTestTaskById(task.getId(), 1, null, jmeterHomePath, "system");
        } catch (Exception e) {
            log.error("执行任务 [{}] 时发生错误", task.getName(), e);
        }
    }
} 