package com.m2pool.pool.task;

import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.m2pool.common.core.utils.DateUtils;
import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.redis.service.RedisService;
import com.m2pool.pool.entity.BlockInfo;
import com.m2pool.pool.mapper.PoolMapper;
import com.m2pool.pool.vo.DateValueVo;
import lombok.Data;
import org.apache.http.HttpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static com.m2pool.pool.utils.dome4j.getSha3xBlockInfoForXml;

/**
 * @Description nexa 币价定时任务 每小时定时从CoinMarketCap拿
 * @Date 2024/6/14 14:03
 * @Author dy
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "task.price")
@EnableScheduling
public class NeaxPriceTask {

    private boolean enable;

    @Autowired
    private PoolMapper poolMapper;

    private  String COINMARKETCAP_KEY="ba4fc555-e8b3-4bb2-aa91-bfa81044e8bf";
    //private  String COINMARKETCAP_KEY="7b7a5fc2-795d-4900-a4db-152681382d52";


    private  String ALL_COINS="nexa,monacoin,groestlcoin,digibyte,radiant,alephium,monero,ethereum";

    @Autowired
    private RedisService redisService;

    //@Scheduled(cron = "0 0/1 * * * ?")
     @Scheduled(cron = "0 0,3,30,33 * * * ?")
    public void PriceToRedisAndDb()
        {
            if(!enable){
                System.out.println("PriceTask 定时任务已关闭，请在nacos修改配置");
                return;
            }
            Map<String, BigDecimal> map = getResultFromNetByAllCoins();
            int  count = 1;
            while (StringUtils.isNull(map)
                    || StringUtils.isNull(map.get("nexa"))
                    || StringUtils.isNull(map.get("grs"))
                    || StringUtils.isNull(map.get("dgb"))
                    || StringUtils.isNull(map.get("rxd"))
                    || StringUtils.isNull(map.get("alph"))
                    || StringUtils.isNull(map.get("monero"))
                    || StringUtils.isNull(map.get("sha3x"))
                    || StringUtils.isNull(map.get("eth"))
            ){
                if(count >= 10){
                    break;
                }
                map =  getResultFromNetByAllCoins();
                count++;
            }

            Date now = new Date();
            int minute = (now.getMinutes() / 30) * 30;
            now.setMinutes( minute);
            now.setSeconds(0);
            String date = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);
            if(StringUtils.isNotNull(map)){

                //处理nexa
                BigDecimal nexa = map.get("nexa");
                if(StringUtils.isNull(nexa)){
                    //重拿nexa
                    nexa = getResultFromNet("nexa");
                    int  nexaCount = 1;
                    while (StringUtils.isNull(nexa)){
                        if(nexaCount >= 5){
                            break;
                        }
                        nexa = getResultFromNet("nexa");
                        nexaCount++;
                    }
                }else {
                    redisService.setCacheObject("nexa_price",nexa);
                    //存入数据库
                    DateValueVo nexaVo = new DateValueVo();
                    nexaVo.setDate(now);
                    nexaVo.setValue(nexa);
                    poolMapper.insertPrice("nexa_price",date , nexaVo);
                }

                //处理mona
                BigDecimal mona = map.get("mona");
                if(StringUtils.isNull(mona)){
                    //重拿mona
                    mona = getResultFromNet("monacoin");
                    int  monaCount = 1;
                    while (StringUtils.isNull(mona)){
                        if(monaCount >= 5){
                            break;
                        }
                        mona = getResultFromNet("monacoin");
                        monaCount++;
                    }
                }else {
                    redisService.setCacheObject("mona_price",mona);
                    //存入数据库
                    DateValueVo monaVo = new DateValueVo();
                    monaVo.setDate(now);
                    monaVo.setValue(mona);
                    poolMapper.insertPrice("mona_price",date , monaVo);
                }

                //处理grs
                BigDecimal grs = map.get("grs");
                if(StringUtils.isNull(grs)){
                    //重拿grs
                    grs = getResultFromNet("groestlcoin");
                    int  grsCount = 1;
                    while (StringUtils.isNull(grs)){
                        if(grsCount >= 5){
                            break;
                        }
                        grs = getResultFromNet("groestlcoin");
                        grsCount++;
                    }
                }else {
                    redisService.setCacheObject("grs_price",grs);
                    //存入数据库
                    DateValueVo grsVo = new DateValueVo();
                    grsVo.setDate(now);
                    grsVo.setValue(grs);
                    poolMapper.insertPrice("grs_price",date , grsVo);
                }

                //处理dgb
                BigDecimal dgb = map.get("dgb");
                if(StringUtils.isNull(dgb)){
                    //重拿dgb
                    dgb = getResultFromNet("digibyte");
                    int  dgbCount = 1;
                    while (StringUtils.isNull(dgb)){
                        if(dgbCount >= 5){
                            break;
                        }
                        dgb = getResultFromNet("digibyte");
                        dgbCount++;
                    }
                }else {
                    redisService.setCacheObject("dgbo_price",dgb);
                    redisService.setCacheObject("dgbq_price",dgb);
                    redisService.setCacheObject("dgbs_price",dgb);
                    //存入数据库
                    DateValueVo dgbVo = new DateValueVo();
                    dgbVo.setDate(now);
                    dgbVo.setValue(dgb);
                    poolMapper.insertPrice("dgbo_price",date , dgbVo);
                    poolMapper.insertPrice("dgbq_price",date , dgbVo);
                    poolMapper.insertPrice("dgbs_price",date , dgbVo);
                }

                //处理rxd
                BigDecimal rxd = map.get("rxd");
                if(StringUtils.isNull(rxd)){
                    //重拿rxd
                    rxd = getResultFromNet("radiant");
                    int  rxdCount = 1;
                    while (StringUtils.isNull(rxd)){
                        if(rxdCount >= 5){
                            break;
                        }
                        rxd = getResultFromNet("radiant");
                        rxdCount++;
                    }
                }else {
                    redisService.setCacheObject("rxd_price",rxd);
                    //存入数据库
                    DateValueVo rxdVo = new DateValueVo();
                    rxdVo.setDate(now);
                    rxdVo.setValue(rxd);
                    poolMapper.insertPrice("rxd_price",date , rxdVo);
                }

                //处理alph
                BigDecimal alph = map.get("alph");
                if(StringUtils.isNull(alph)){
                    //重拿alph
                    alph = getResultFromNet("alephium");
                    int  alphCount = 1;
                    while (StringUtils.isNull(alph)){
                        if(alphCount >= 5){
                            break;
                        }
                        alph = getResultFromNet("alephium");
                        alphCount++;
                    }
                }else {
                    redisService.setCacheObject("alph_price",alph);
                    //存入数据库
                    DateValueVo alphVo = new DateValueVo();
                    alphVo.setDate(now);
                    alphVo.setValue(alph);
                    poolMapper.insertPrice("alph_price",date , alphVo);
                }


                //处理monero
                BigDecimal monero = map.get("monero");
                if(StringUtils.isNull(monero)){
                    //重拿monero
                    monero = getResultFromNet("monero");
                    int  moneroCount = 1;
                    while (StringUtils.isNull(monero)){
                        if(moneroCount >= 5){
                            break;
                        }
                        monero = getResultFromNet("monero");
                        moneroCount++;
                    }
                }else {
                    redisService.setCacheObject("monero_price",monero);
                    //存入数据库
                    DateValueVo moneroVo = new DateValueVo();
                    moneroVo.setDate(now);
                    moneroVo.setValue(monero);
                    poolMapper.insertPrice("monero_price",date , moneroVo);
                }


                //处理xtm
                BigDecimal sha3x = map.get("sha3x");
                if(StringUtils.isNotNull(sha3x)){
                    redisService.setCacheObject("sha3x_price",sha3x);
                    //存入数据库
                    DateValueVo xtmVo = new DateValueVo();
                    xtmVo.setDate(now);
                    xtmVo.setValue(sha3x);
                    poolMapper.insertPrice("sha3x_price",date , xtmVo);
                }



                //处理eth
                BigDecimal eth = map.get("eth");
                if(StringUtils.isNull(eth)){
                    //重拿eth
                    eth = getResultFromNet("ethereum");
                    int  ethCount = 1;
                    while (StringUtils.isNull(eth)){
                        if(ethCount >= 5){
                            break;
                        }
                        eth = getResultFromNet("ethereum");
                        ethCount++;
                    }
                }else {
                    redisService.setCacheObject("eth_price",eth);
                    //存入数据库
                    DateValueVo ethVo = new DateValueVo();
                    ethVo.setDate(now);
                    ethVo.setValue(eth);
                    poolMapper.insertPrice("eth_price",date , ethVo);
                }
            }
    }

    //@Scheduled(cron = "1 0,30 * * * ?")
    //public void GRSPriceToRedis(){
    //    BigDecimal price = getResultFromNet("groestlcoin");
    //    int  count = 1;
    //    while (StringUtils.isNull(price)){
    //        if(count >= 10){
    //            break;
    //        }
    //        price = getResultFromNet("groestlcoin");
    //        count++;
    //    }
    //    if(StringUtils.isNotNull(price)){
    //        redisService.setCacheObject("grs_price",price);
    //        //存入数据库
    //        DateValueVo com.m2pool.chat.vo = new DateValueVo();
    //        Date now = new Date();
    //        int minute = (now.getMinutes() / 30) * 30;
    //        now.setMinutes( minute);
    //        now.setSeconds(0);
    //        com.m2pool.chat.vo.setDate(now);
    //        com.m2pool.chat.vo.setValue(price);
    //        String date = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);
    //        poolMapper.insertPrice("grs_price",date , com.m2pool.chat.vo);
    //    }
    //}
    //
    //
    //@Scheduled(cron = "2 0,30 * * * ?")
    //public void MONAPriceToRedis(){
    //    BigDecimal price = getResultFromNet("monacoin");
    //    int  count = 1;
    //    while (StringUtils.isNull(price)){
    //        if(count >= 10){
    //            break;
    //        }
    //        price = getResultFromNet("monacoin");
    //        count++;
    //    }
    //    if(StringUtils.isNotNull(price)){
    //        redisService.setCacheObject("mona_price",price);
    //        //存入数据库
    //        DateValueVo com.m2pool.chat.vo = new DateValueVo();
    //        Date now = new Date();
    //        int minute = (now.getMinutes() / 30) * 30;
    //        now.setMinutes( minute);
    //        now.setSeconds(0);
    //        com.m2pool.chat.vo.setDate(now);
    //        com.m2pool.chat.vo.setValue(price);
    //        String date = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);
    //        poolMapper.insertPrice("mona_price",date , com.m2pool.chat.vo);
    //    }
    //}
    //
    //@Scheduled(cron = "3 0,30 * * * ?")
    //public void DGBPriceToRedis(){
    //    BigDecimal price = getResultFromNet("digibyte");
    //    int  count = 1;
    //    while (StringUtils.isNull(price)){
    //        if(count >= 10){
    //            break;
    //        }
    //        price = getResultFromNet("digibyte");
    //        count++;
    //    }
    //    if(StringUtils.isNotNull(price)){
    //        redisService.setCacheObject("dgbq_price",price);
    //        redisService.setCacheObject("dgbo_price",price);
    //        redisService.setCacheObject("dgbs_price",price);
    //
    //        //存入数据库
    //        DateValueVo com.m2pool.chat.vo = new DateValueVo();
    //        Date now = new Date();
    //        int minute = (now.getMinutes() / 30) * 30;
    //        now.setMinutes( minute);
    //        now.setSeconds(0);
    //        com.m2pool.chat.vo.setDate(now);
    //        com.m2pool.chat.vo.setValue(price);
    //        String date = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);
    //        poolMapper.insertPrice("dgbq_price",date , com.m2pool.chat.vo);
    //        poolMapper.insertPrice("dgbo_price",date , com.m2pool.chat.vo);
    //        poolMapper.insertPrice("dgbs_price",date , com.m2pool.chat.vo);
    //    }
    //}
    //
    //
    //@Scheduled(cron = "4 0,30 * * * ?")
    //public void RXDPriceToRedis(){
    //    BigDecimal price = getResultFromNet("radiant");
    //    int  count = 1;
    //    while (StringUtils.isNull(price)){
    //        if(count >= 10){
    //            break;
    //        }
    //        price = getResultFromNet("radiant");
    //        count++;
    //    }
    //    if(StringUtils.isNotNull(price)){
    //        redisService.setCacheObject("rxd_price",price);
    //
    //        //存入数据库
    //        DateValueVo com.m2pool.chat.vo = new DateValueVo();
    //        Date now = new Date();
    //        int minute = (now.getMinutes() / 30) * 30;
    //        now.setMinutes( minute);
    //        now.setSeconds(0);
    //        com.m2pool.chat.vo.setDate(now);
    //        com.m2pool.chat.vo.setValue(price);
    //        String date = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);
    //        poolMapper.insertPrice("rxd_price",date ,com.m2pool.chat.vo);
    //    }
    //}


    public BigDecimal getResultFromNet(String coin){
        String uri = "https://pro-api.coinmarketcap.com/v2/cryptocurrency/quotes/latest?slug="+coin;

        try {
            String body = HttpRequest
                    .get(uri)
                    .header(HttpHeaders.ACCEPT,"application/json")
                    .header("X-CMC_PRO_API_KEY",COINMARKETCAP_KEY)
                    .timeout(3000)
                    .execute()
                    .body();

            JSONObject jsonObject = JSON.parseObject(body);
            if (StringUtils.isNull(jsonObject)){
                throw new RuntimeException();
            }
            JSONObject data = jsonObject.getJSONObject("data");
            if (StringUtils.isNull(data)){
                throw new RuntimeException();
            }

            JSONObject object = null;
            if("nexa".equals(coin.toLowerCase())){
                object = data.getJSONObject("23380");
            }else if("monacoin".equals(coin.toLowerCase())){
                object = data.getJSONObject("213");
            }
            else if("groestlcoin".equals(coin.toLowerCase())){
                object = data.getJSONObject("258");
            }else if("digibyte".equals(coin.toLowerCase())){
                object = data.getJSONObject("109");
            }
            else if("radiant".equals(coin.toLowerCase())){
                object = data.getJSONObject("22866");
            }
            else if("alephium".equals(coin.toLowerCase())){
                object = data.getJSONObject("14878");
            }else if ("monero".equalsIgnoreCase(coin)){
                object = data.getJSONObject("328");
            }else if("eth".equalsIgnoreCase(coin)){
                object = data.getJSONObject("1027");
            }

            if (StringUtils.isNull(object)){
                throw new RuntimeException();
            }
            JSONObject quote = object.getJSONObject("quote");
            if (StringUtils.isNull(quote)){
                throw new RuntimeException();
            }
            JSONObject usd = quote.getJSONObject("USD");
            if (StringUtils.isNull(usd)){
                throw new RuntimeException();
            }
            BigDecimal price = usd.getBigDecimal("price").setScale(8,BigDecimal.ROUND_HALF_UP);
            if (StringUtils.isNull(price)){
                throw new RuntimeException();
            }
            System.out.println(price);
            return price;
        } catch (Exception e) {
            System.out.println("Error: cannont access content - " + e.toString());
            return null;
        }
    }


    public Map<String,BigDecimal> getResultFromNetByAllCoins(){
        String uri = "https://pro-api.coinmarketcap.com/v2/cryptocurrency/quotes/latest?slug="+ALL_COINS;

        Map<String,BigDecimal> map = new HashMap<>();
        map.put("nexa",null);
        map.put("mona",null);
        map.put("grs",null);
        map.put("dgb",null);
        map.put("rxd",null);
        map.put("alph",null);
        map.put("monero",null);
        map.put("eth",null);



        try {
            String body = HttpRequest
                    .get(uri)
                    .header(HttpHeaders.ACCEPT,"application/json")
                    .header("X-CMC_PRO_API_KEY",COINMARKETCAP_KEY)
                    .timeout(3000)
                    .execute()
                    .body();

            JSONObject jsonObject = JSON.parseObject(body);
            if (StringUtils.isNull(jsonObject)){
                return map;
            }
            JSONObject data = jsonObject.getJSONObject("data");
            if (StringUtils.isNull(data)){
                return map;
            }

            //数字是通过coinmarketcap 查询的对应币种id 可以切换曲线图时间粒度浏览器后台查看coinmarketcap调用的id值
            JSONObject nexaObject = data.getJSONObject("23380");
            JSONObject monaObject = data.getJSONObject("213");
            JSONObject grsObject = data.getJSONObject("258");
            JSONObject dgbObject = data.getJSONObject("109");
            JSONObject rxdObject = data.getJSONObject("22866");
            JSONObject alphObject = data.getJSONObject("14878");
            JSONObject moneroObject = data.getJSONObject("328");
            JSONObject ethObject = data.getJSONObject("1027");

            BigDecimal nexaPrice = getPriceByCoinIdJSONObject(nexaObject);
            BigDecimal monaPrice = getPriceByCoinIdJSONObject(monaObject);
            BigDecimal grsPrice = getPriceByCoinIdJSONObject(grsObject);
            BigDecimal dgbPrice = getPriceByCoinIdJSONObject(dgbObject);
            BigDecimal rxdPrice = getPriceByCoinIdJSONObject(rxdObject);
            BigDecimal alphPrice = getPriceByCoinIdJSONObject(alphObject);
            BigDecimal moneroPrice = getPriceByCoinIdJSONObject(moneroObject);
            BigDecimal ethPrice = getPriceByCoinIdJSONObject(ethObject);

            map.put("nexa",nexaPrice);
            map.put("mona",monaPrice);
            map.put("grs",grsPrice);
            map.put("dgb",dgbPrice);
            map.put("rxd",rxdPrice);
            map.put("alph",alphPrice);
            map.put("monero",moneroPrice);
            map.put("eth",ethPrice);

            //xtm 不通过coinmarketcap 获取币价
            BlockInfo sha3xBlockInfoForXml = getSha3xBlockInfoForXml();
            if (StringUtils.isNotNull(sha3xBlockInfoForXml)){
                map.put("sha3x",sha3xBlockInfoForXml.getPrice().divide(BigDecimal.valueOf(7.1),8,BigDecimal.ROUND_HALF_UP));
            }
            return map;

        } catch (Exception e) {
            System.out.println("Error: cannont access content - " + e.toString());
            return map;
        }
    }

    public BigDecimal getPriceByCoinIdJSONObject(JSONObject coinIdjs){
        if (StringUtils.isNull(coinIdjs)){
           return null;
        }
        JSONObject quote = coinIdjs.getJSONObject("quote");
        if (StringUtils.isNull(quote)){
            return null;
        }
        JSONObject usd = quote.getJSONObject("USD");
        if (StringUtils.isNull(usd)){
            return null;
        }
        BigDecimal price = usd.getBigDecimal("price").setScale(8,BigDecimal.ROUND_HALF_UP);
        if (StringUtils.isNull(price)){
            return null;
        }
        return price;
    }


}
