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

import link.at17.mid.tushare.annotation.UpdateMethod;
import link.at17.mid.tushare.dao.ThsListDao;
import link.at17.mid.tushare.dao.ThsMemberDao;
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.models.ThsStockInfo;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class ThsMemberService {

    @Autowired
    ThsMemberDao thsMemberDao;
    
    @Autowired
    ThsListDao thsListDao;
    
    @Autowired
    TushareCrawler tushareCrawler;
    
    @Autowired
    RedissonClient redis;


    /**
     * <a href="https://tushare.pro/document/2?doc_id=261"><b>同花顺概念板块成分</b></a><br>
     * 接口：ths_member<br>
     * 描述：获取同花顺概念板块成分列表注：数据版权归属同花顺，如做商业用途，请主动联系同花顺。<br>
     * 限量：用户积累5000积分可调取，每分钟可调取200次，可按概念板块代码循环提取所有成分
     */
    @UpdateMethod(name="同花顺概念板块成分", order=7)
    public boolean updateData() {
        TushareRequestBody baseRequest = new TushareRequestBody("ths_member").addFields("ts_code,con_code,con_name,weight,in_date,out_date,is_new");
        Function<List<JSONObject>, Boolean> function = (t) -> {
            thsMemberDao.insertOrUpdateList(t);
            return true;
        };
        List<ThsStockInfo> stockInfoList = thsListDao.listByExchange(null);
        while (true) {
            List<Future<TushareCrawlerResult>> executeResult = tushareCrawler.rollingQueryByStock(baseRequest, stockInfoList, null, function, 5000L, QueryWay.ByStock, null);
            
            stockInfoList.clear();
            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());
                        stockInfoList.add(request.getJSONObject("params").to(ThsStockInfo.class));
                    }
                } catch (InterruptedException | ExecutionException e) {
                    log.error("同花顺概念板块成分数据执行结果时发生错误", e);
                }
            }
            if (stockInfoList.size() == 0) {
                log.info("同花顺概念板块成分更新完成");
                break;
            }
            log.info("重新获取未获取成功的同花顺概念板块成分");
        }
        if (baseRequest.hasFingerprint()) {
            redis.getBucket(baseRequest.getFingerprint()).delete();
        }
        return true;
    }
    
    /**
     * 插入从 Tushare 获取的数据
     * @param list
     * @return 插入是否成功
     */
    public boolean insertOrUpdateList(List<JSONObject> list) {
        return SqlHelper.retBool(thsMemberDao.insertOrUpdateList(list));
    }

}
