package link.at17.mid.tushare.data.service;

import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.function.Function;

import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson2.JSONObject;

import link.at17.mid.tushare.annotation.UpdateMethod;
import link.at17.mid.tushare.dao.StockAdjustDao;
import link.at17.mid.tushare.data.crawler.QueryWay;
import link.at17.mid.tushare.data.crawler.tushare.TushareCrawler;
import link.at17.mid.tushare.data.crawler.tushare.TushareCrawlerResult;
import link.at17.mid.tushare.data.crawler.tushare.TushareRequestBody;
import link.at17.mid.tushare.data.validator.AllowedEnum;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class StockAdjustService {

    @Autowired
    StockInfoService stockInfoService;
    
    @Autowired
    StockAdjustDao stockAdjustDao;
    
    @Autowired
    TushareCrawler tushareCrawler;
    
    @Autowired
    RedissonClient redis;
    
    /**
     * 用于插入从 Tushare 获取的内容
     * @param list
     */
    public void insertOrUpdateList(List<JSONObject> list) {
        stockAdjustDao.insertOrUpdateList(list);
    }
    
    
    /**
     * <b><a href="https://waditu.com/document/2?doc_id=28">Tushare 复权因子</a></b><br>
     * <blockquote>
     * 接口：adj_factor<br>
     * 更新时间：早上9点30分<br>
     * 描述：获取股票复权因子，可提取单只股票全部历史复权因子，也可以提取单日全部股票的复权因子。<br>
     * </blockquote>
     * 虽然文档没说，但当这个接口请求单支股的所有数据时，也是 5000 条限制<br>
     * <font color="red">请先更新交易日历和股票列表后再调用该方法，否则可能造成股票复权因子缺失</font>
     */
    @UpdateMethod(name="股票复权因子", order=4)
    public boolean updateData(
            @AllowedEnum({"ByDateUpdate", "ByStockCrossCheck"}) 
            QueryWay queryWay) {

        TushareRequestBody baseRequest = new TushareRequestBody("adj_factor");
        Function<List<JSONObject>, Boolean> function = (t) -> {
            stockAdjustDao.insertOrUpdateList(t);
            return true;
        };
        List<Future<TushareCrawlerResult>> executeResult;
        if (queryWay.compareTo(QueryWay.ByStock) >= 0) {
            executeResult = tushareCrawler.rollingQueryByStock(baseRequest, stockInfoService.list(), stockAdjustDao, function, 5000L, queryWay, null);
        }
        else {
            executeResult = tushareCrawler.rollingQueryByDate(baseRequest, stockAdjustDao, function, queryWay, null);
        }
        log.info("复权数据更新完成");
        for (Future<TushareCrawlerResult> f : executeResult) {
            try {
                TushareCrawlerResult result = f.get();
                JSONObject request = f.get().getRequest();
                if (result.isFatal()) {
                    log.error("复权数据未获取，发生致命错误，将不会重试：{}", request.toJSONString());
                }
                else if (!result.isSuccess()) {
                    log.info("复权数据未获取：{}", request.toJSONString());
                }
            } catch (InterruptedException | ExecutionException e) {
                log.error("检查复权数据执行结果时发生错误", e);
            }
        }
        if (baseRequest.hasFingerprint()) {
            redis.getBucket(baseRequest.getFingerprint()).delete();
        }
        return true;
    }

}
