package com.lanyuanxiaoyao.leopard.strategy;

import cn.hutool.core.lang.Tuple;
import com.lanyuanxiaoyao.leopard.core.entity.Daily;
import com.lanyuanxiaoyao.leopard.core.entity.Daily_;
import com.lanyuanxiaoyao.leopard.core.entity.QDaily;
import com.lanyuanxiaoyao.leopard.core.entity.Stock;
import com.lanyuanxiaoyao.leopard.core.repository.DailyRepository;
import com.lanyuanxiaoyao.leopard.core.repository.StockRepository;
import jakarta.annotation.Resource;
import jakarta.transaction.Transactional;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@Slf4j
@SpringBootApplication(scanBasePackages = "com.lanyuanxiaoyao.leopard")
@EnableJpaAuditing
public class StrategyApplication {
  @Resource
  private StockRepository stockRepository;
  @Resource
  private DailyRepository dailyRepository;

  public static void main(String[] args) {
    SpringApplication.run(StrategyApplication.class, args);
  }

  @Transactional(rollbackOn = Throwable.class)
  @EventListener(ApplicationReadyEvent.class)
  public void test() {
    var dailies = dailyRepository.findAll(
      QDaily.daily.tradeDate.year().eq(2025),
      Sort.by(Daily_.TRADE_DATE)
    );
    // log.info("OpenDate: {}, CloseDate: {}", dailies.getFirst().getTradeDate(), dailies.getLast().getTradeDate());
    // var closes = dailies.stream().map(Daily::getHfqClose).toList();
    // var statistics = new DescriptiveStatistics();
    // closes.forEach(statistics::addValue);
    // log.info("Ascending: {}", (closes.getLast() - closes.getFirst()) * 100.0 / closes.getFirst());
    // log.info("STD: {}", statistics.getStandardDeviation());
    dailies.stream()
      .collect(Collectors.groupingBy(Daily::getStock))
      .entrySet()
      .stream()
      .map(entry -> {
        var stock = entry.getKey();
        var statistics = new DescriptiveStatistics();
        entry.getValue()
          .stream()
          .map(Daily::getHfqClose)
          .forEach(statistics::addValue);
        var std = statistics.getStandardDeviation();
        return new Tuple(stock, std);
      })
      .sorted((t1, t2) -> Double.compare(t2.get(1), t1.get(1)))
      .forEachOrdered(tuple -> log.info("Stock: {}, STD: {}", ((Stock) tuple.get(0)).getCode(), tuple.get(1)));
  }
}
