package com.lanyuanxiaoyao.leopard.core.service;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.lanyuanxiaoyao.leopard.core.entity.Task;
import com.lanyuanxiaoyao.leopard.core.repository.TaskRepository;
import com.lanyuanxiaoyao.leopard.core.task.PyramidSelect;
import com.lanyuanxiaoyao.leopard.core.task.TaskRunner;
import com.lanyuanxiaoyao.leopard.core.task.UpdateDailyTask;
import com.lanyuanxiaoyao.leopard.core.task.UpdateFinanceIndicatorTask;
import com.lanyuanxiaoyao.leopard.core.task.UpdateStockTask;
import com.lanyuanxiaoyao.leopard.core.task.UpdateYearlyTask;
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

/**
 * @author lanyuanxiaoyao
 * @version 20250829
 */
@Slf4j
@Service
public class TaskService extends SimpleServiceSupport<Task> {
  private final ExecutorService executor = Executors.newFixedThreadPool(50);
  private final ApplicationContext context;

  @Getter
  private final Set<TaskTemplate> templates = Stream.of(
    new TaskTemplate("更新股票信息", "更新股票信息", UpdateStockTask.class),
    new TaskTemplate("更新年线指标", "更新年线指标", UpdateYearlyTask.class),
    new TaskTemplate("更新日线数据", "更新日线数据", UpdateDailyTask.class),
    new TaskTemplate("更新财务指标", "更新财务指标", UpdateFinanceIndicatorTask.class),
    new TaskTemplate("金字塔选股", "金字塔选股", PyramidSelect.class)
  ).collect(Collectors.toSet());
  private final Map<String, TaskTemplate> templateMap = templates.stream()
    .collect(Collectors.toMap(TaskTemplate::id, template -> template));

  public TaskService(TaskRepository repository, ApplicationContext context) {
    super(repository);
    this.context = context;
  }

  public TaskTemplate getTemplate(String templateId) {
    return templateMap.get(templateId);
  }

  public void execute(String templateId, Map<String, Object> params) {
    execute(templateId, params, true);
  }

  public void execute(String templateId, Map<String, Object> params, boolean async) {
    var template = templateMap.get(templateId);
    if (ObjectUtil.isNull(template)) {
      throw new RuntimeException("任务模板不存在");
    }
    var instance = context.getBean(template.runnerClass());
    if (async) {
      executor.submit(() -> instance.run(template, params));
    } else {
      instance.run(template, params);
    }
  }

  public record TaskTemplate(
    String id,
    String name,
    String description,
    Class<? extends TaskRunner> runnerClass
  ) {
    public TaskTemplate(String name, String description, Class<? extends TaskRunner> runnerClass) {
      this(IdUtil.fastUUID(), name, description, runnerClass);
    }
  }
}
