package com.lanyuanxiaoyao.leopard.server.service.task;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.lanyuanxiaoyao.leopard.core.entity.Task;
import com.lanyuanxiaoyao.leopard.core.entity.TaskTemplate;
import com.lanyuanxiaoyao.leopard.server.service.TaskService;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowFact;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import java.time.LocalDateTime;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@LiteflowComponent
public class TaskMonitorNodes {
  private final TaskService taskService;

  public TaskMonitorNodes(TaskService taskService) {
    this.taskService = taskService;
  }

  @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "task_start", nodeName = "任务开始", nodeType = NodeTypeEnum.COMMON)
  public void taskStart(NodeComponent node) {
    try {
      var context = node.getContextBean(TaskMonitorContext.class);
      var task = new Task();
      task.setName(context.getTemplate().getName());
      task.setDescription(context.getTemplate().getDescription());
      task.setStatus(Task.Status.RUNNING);
      task.setLaunchedTime(LocalDateTime.now());
      var taskId = taskService.save(task);
      context.setTaskId(taskId);
    } catch (Exception exception) {
      log.warn("Not in task", exception);
    }
  }

  @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "task_end", nodeName = "任务结束", nodeType = NodeTypeEnum.COMMON)
  public void taskEnd(NodeComponent node, @LiteflowFact("taskId") Long taskId) {
    if (ObjectUtil.isNotNull(taskId)) {
      var task = taskService.detail(taskId);
      task.setStatus(Task.Status.SUCCESS);
      task.setStep(100);
      task.setFinishedTime(LocalDateTime.now());
      var result = node.<String>getContextValue("taskResult");
      if (StrUtil.isNotBlank(result)) {
        task.setResult(result);
      }
      taskService.save(task);
    }
  }

  @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "task_error", nodeName = "任务错误", nodeType = NodeTypeEnum.COMMON)
  public void taskError(NodeComponent node, @LiteflowFact("taskId") Long taskId) {
    if (ObjectUtil.isNotNull(taskId)) {
      var task = taskService.detail(taskId);
      task.setStatus(Task.Status.FAILURE);
      task.setFinishedTime(LocalDateTime.now());
      var exception = node.getSlot().getException();
      if (ObjectUtil.isNotNull(exception)) {
        task.setError(ExceptionUtil.stacktraceToString(exception));
      }
      taskService.save(task);
    }
  }

  @Data
  public static final class TaskMonitorContext {
    private TaskTemplate template;
    private Long taskId;
    private String taskResult;

    public TaskMonitorContext(TaskTemplate template) {
      this.template = template;
    }
  }
}
