package com.lanyuanxiaoyao.leopard.core.task;

import com.lanyuanxiaoyao.leopard.core.entity.StockCollection;
import com.lanyuanxiaoyao.leopard.core.entity.StockScore;
import com.lanyuanxiaoyao.leopard.core.repository.StockCollectionRepository;
import com.lanyuanxiaoyao.leopard.core.service.selector.PyramidStockSelector;
import java.time.LocalDate;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * 金字塔选股
 *
 * @author lanyuanxiaoyao
 * @version 20250925
 */
@Slf4j
@Component
public class PyramidSelect extends TaskRunner {
  private final StockCollectionRepository stockCollectionRepository;

  private final PyramidStockSelector pyramidStockSelector;

  protected PyramidSelect(ApplicationContext context, StockCollectionRepository stockCollectionRepository, PyramidStockSelector pyramidStockSelector) {
    super(context);
    this.stockCollectionRepository = stockCollectionRepository;
    this.pyramidStockSelector = pyramidStockSelector;
  }

  @Transactional(rollbackFor = Throwable.class)
  @Override
  public String process(Map<String, Object> params, StepUpdater updater) {
    var candidates = pyramidStockSelector.select(new PyramidStockSelector.Request(LocalDate.now().getYear(), 50));

    var collection = new StockCollection();
    collection.setName("金字塔选股");
    collection.setDescription("金字塔选股");
    collection.setScores(
      candidates.stream()
        .map(candidate -> {
          var score = new StockScore();
          score.setStock(candidate.stock());
          score.setScore(candidate.score());
          score.setExtra(candidate.extra());
          score.setCollection(collection);
          return score;
        })
        .collect(Collectors.toSet())
    );
    stockCollectionRepository.save(collection);

    return """
      | Code | Name | Score |
      | ---- | ---- | ----- |
      %s
      """.formatted(candidates.stream()
      .map(candidate -> "| %s | %s | %.2f |".formatted(candidate.stock().getCode(), candidate.stock().getName(), candidate.score()))
      .collect(Collectors.joining("\n")));
  }
}
