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

import java.time.LocalDateTime;
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 com.baomidou.mybatisplus.extension.toolkit.SqlHelper;

import link.at17.mid.tushare.annotation.UpdateMethod;
import link.at17.mid.tushare.dao.ThsDailyDao;
import link.at17.mid.tushare.dao.ThsListDao;
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 link.at17.mid.tushare.enums.ThsStockMarket;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class ThsDailyService {
    
    private static final LocalDateTime THS_DAILY_BEGIN_LOCALDATE = LocalDateTime.of(2007, 8, 1, 0, 0, 0);
    
    @Autowired
    ThsDailyDao thsDailyDao;
    
    @Autowired
    ThsListDao thsListDao;
    
    @Autowired
    TushareCrawler tushareCrawler;
    
    @Autowired
    RedissonClient redis;

    /**
     * <a href="https://tushare.pro/document/2?doc_id=260"><b>同花顺板块指数日线行情</b></a><br>
     * 接口：ths_daily<br>
     * 描述：获取同花顺板块指数行情。注：数据版权归属同花顺，如做商业用途，请主动联系同花顺，如需帮助请联系微信：waditu_a<br>
     * 限量：单次最大3000行数据（需6000积分），可根据指数代码、日期参数循环提取。<br>
     * @param queryWay
     * @return
     */
    @UpdateMethod(name="同花顺板块指数日线行情", order=8)
    public boolean updateData(
            @AllowedEnum({"ByDateUpdate", "ByStockCrossCheck"})
            QueryWay queryWay) {
        TushareRequestBody baseRequest = new TushareRequestBody("ths_daily").addFields("ts_code,trade_date,close,open,high,low,pre_close,avg_price,change,pct_change,vol,turnover_rate,total_mv,float_mv");
        Function<List<JSONObject>, Boolean> function = (t) -> {
            thsDailyDao.insertOrUpdateList(t);
            return true;
        };

        List<Future<TushareCrawlerResult>> executeResult;
        if (queryWay.compareTo(QueryWay.ByStock) >= 0) {
            executeResult = tushareCrawler.rollingQueryByStock(baseRequest, thsListDao.listByExchange(ThsStockMarket.A), thsDailyDao, function, 3000L, queryWay, null);
        }
        else {
            executeResult = tushareCrawler.rollingQueryByDate(baseRequest, thsDailyDao, function, queryWay, THS_DAILY_BEGIN_LOCALDATE);
        }
        log.info("同花顺板块指数行情更新完成");
        for (Future<TushareCrawlerResult> f : executeResult) {
            try {
                TushareCrawlerResult result = f.get();
                JSONObject request = result.getRequest();
                if (result.isFatal()) {
                    log.error("同花顺板块指数行情数据未获取，发生致命错误，将不会重试：{}", request.toJSONString());
                }
                else if (!result.isSuccess()) {
                    log.warn("同花顺板块指数行情数据未获取：{}", request.toJSONString());
                }
            } catch (InterruptedException | ExecutionException e) {
                log.error("同花顺板块指数行情数据执行结果时发生错误", e);
            }
        }
        if (baseRequest.hasFingerprint()) {
            redis.getBucket(baseRequest.getFingerprint()).delete();
        }
        return true;
    }
    
    /**
     * 插入从 Tushare 获取的数据
     * @param list
     * @return 插入是否成功
     */
    public boolean insertOrUpdateList(List<JSONObject> list) {
        return SqlHelper.retBool(thsDailyDao.insertOrUpdateList(list));
    }

}
