package com.m2pool.pool.utils;


import cn.hutool.core.io.IORuntimeException;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.m2pool.common.core.text.Convert;
import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.pool.config.ApacheHttpClientPoolUtil;
import com.m2pool.pool.entity.BlockInfo;
import com.m2pool.pool.enums.NodeConfig;
import com.m2pool.pool.mapper.PoolMapper;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description 节点调用
 * @Date 2024/6/24 10:21
 * @Author 杜懿
 */
public class NodeRpc{

    public static String getResult(String coin,String method,String[] params) {

        NodeConfig config = (NodeConfig) EnumUtils.get(NodeConfig.class, coin);
        String uri ="http://"+config.getIp()+":"+config.getHost();

        String auth =config.getUser()+":"+config.getPwd();

        // 构建请求体
        JSONObject requestBody = new JSONObject();
        requestBody.put("jsonrpc", "1.0");
        requestBody.put("id", "testnet");
        requestBody.put("method", method);
        if ("nexa".equals(config.getCoin())) {
            requestBody.put("params", params);
        }
        // 创建 HttpPost 请求
        HttpPost httpPost = new HttpPost(uri);
        // 设置请求头
        httpPost.setHeader("Authorization", "Basic " + Base64.getEncoder().encodeToString(auth.getBytes()));
        httpPost.setHeader("Content-Type", "application/json");
        // 设置请求体
        StringEntity entity = null;
        try {
            entity = new StringEntity(requestBody.toString());
        } catch (UnsupportedEncodingException e) {
            return "error:connection failed by UnsupportedEncodingException"+e;
        }
        httpPost.setEntity(entity);
        //从连接池获取连接不要放到下面try with resource中，否则连接池会关闭
        CloseableHttpClient httpClient = ApacheHttpClientPoolUtil.getHttpClient();
        //发起请求
        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
            // 获取响应实体
            HttpEntity responseEntity = response.getEntity();
            if (responseEntity != null) {
                String body = EntityUtils.toString(responseEntity);
                JSONObject jsonObject = JSON.parseObject(body);

                String result = jsonObject.getString("result");
                String error = jsonObject.getString("error");
                if (StringUtils.isNull(result) && StringUtils.isNotBlank(error)){
                    System.out.println("error:"+JSON.parseObject(error).getString("message"));
                    return "error:"+JSON.parseObject(error).getString("message");
                }
                if(StringUtils.isNull(result) && StringUtils.isBlank(error)){
                    System.out.println("result和error为空");
                    return "error:connection failed";
                }
                return result;
            }
            return "error:result is null";
        }catch (Exception e){
            System.out.println("报错了"+e);
            return "error:connection failed by IOException"+e;
        }




        //JSONObject requestBody = new JSONObject();
        //requestBody.put("jsonrpc", "1.0");
        //requestBody.put("id", "testnet");
        //requestBody.put("method", method);
        //if("nexa".equals(config.getCoin())){
        //    requestBody.put("params",params);
        //}
        //try (HttpResponse response = HttpUtil.createPost(uri)
        //        .header("Authorization", "Basic " + Base64.getEncoder().encodeToString(auth.getBytes()))
        //        .header("Content-Type", "application/json")
        //        .body(requestBody.toString())
        //        .timeout(3000)
        //        .execute()) {
        //    String body = response.body();
        //    System.out.println(body);
        //    JSONObject jsonObject = JSON.parseObject(body);
        //
        //    String result = jsonObject.getString("result");
        //    String error = jsonObject.getString("error");
        //
        //    if (StringUtils.isNull(result) && StringUtils.isNotBlank(error)){
        //        System.out.println("error:"+JSON.parseObject(error).getString("message"));
        //        return "error:"+JSON.parseObject(error).getString("message");
        //    }
        //    if(StringUtils.isNull(result) && StringUtils.isBlank(error)){
        //        System.out.println("result和error为空");
        //        return "error:connection failed";
        //    }
        //    return result;
        //}catch (IORuntimeException e){
        //    return "error:connection failed by IORuntimeException" +e;
        //}catch (Exception e){
        //    return "error:connection failed by Exception"+e;
        //}

    }

    public static String getResultTest(String coin, String method, Object[] params) {

        NodeConfig config = (NodeConfig) EnumUtils.get(NodeConfig.class, coin);

        String uri ="http://"+config.getIp()+":"+config.getHost();

        String auth =config.getUser()+":"+config.getPwd();


        JSONObject requestBody = new JSONObject();
        requestBody.put("jsonrpc", "1.0");
        requestBody.put("id", "testnet");
        requestBody.put("method", method);//getblockcount
        requestBody.put("params",params);
        // 创建 HttpPost 请求
        HttpPost httpPost = new HttpPost(uri);
        // 设置请求头
        httpPost.setHeader("Authorization", "Basic " + Base64.getEncoder().encodeToString(auth.getBytes()));
        httpPost.setHeader("Content-Type", "application/json");
        // 设置请求体
        StringEntity entity = null;
        try {
            entity = new StringEntity(requestBody.toString());
        } catch (UnsupportedEncodingException e) {
            return "error:connection failed by UnsupportedEncodingException"+e;
        }
        httpPost.setEntity(entity);
        //从连接池获取连接不要放到下面try with resource中，否则连接池会关闭
        CloseableHttpClient httpClient = ApacheHttpClientPoolUtil.getHttpClient();
        //发起请求
        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {

            // 获取响应实体
            HttpEntity responseEntity = response.getEntity();
            if (responseEntity != null) {
                String body = EntityUtils.toString(responseEntity);
                JSONObject jsonObject = JSON.parseObject(body);

                String result = jsonObject.getString("result");
                String error = jsonObject.getString("error");
                if (StringUtils.isNull(result) && StringUtils.isNotBlank(error)){
                    System.out.println("error:"+JSON.parseObject(error).getString("message"));
                    return "error:"+JSON.parseObject(error).getString("message");
                }
                if(StringUtils.isNull(result) && StringUtils.isBlank(error)){
                    System.out.println("result和error为空");
                    return "error:connection failed";
                }
                return result;
            }
            return "error:result is null";
        }catch (Exception e){
            System.out.println("报错了"+e);
            return "error:connection failed by IOException"+e;
        }

        //
        //try (HttpResponse response = HttpUtil.createPost(uri)
        //        .header("Authorization", "Basic " + Base64.getEncoder().encodeToString(auth.getBytes()))
        //        .header("Content-Type", "application/json")
        //        .body(requestBody.toString())
        //        .timeout(3000)
        //        .execute()) {
        //    String body = response.body();
        //    System.out.println(body);
        //    JSONObject jsonObject = JSON.parseObject(body);
        //
        //    String result = jsonObject.getString("result");
        //    String error = jsonObject.getString("error");
        //
        //    if (StringUtils.isNull(result) && StringUtils.isNotBlank(error)){
        //        System.out.println("error:"+JSON.parseObject(error).getString("message"));
        //        return "error:"+JSON.parseObject(error).getString("message");
        //    }
        //    if(StringUtils.isNull(result) && StringUtils.isBlank(error)){
        //        System.out.println("result和error为空");
        //        return "error:connection failed";
        //    }
        //    return result;
        //}catch (IORuntimeException e){
        //    return "error:connection failed by IORuntimeException" +e;
        //}catch (Exception e){
        //    return "error:connection failed by Exception"+e;
        //}

    }

    /**
     * 校验monero 钱包是否合法
     * @param address
     * @return
     */
    public static boolean checkMonero(String address){
        int length = address.length();

        if(StringUtils.isNotEmpty(address) && (length == 95 || length == 106) ){
            if (address.startsWith("4") || address.startsWith("8")){
                return true;
            }
            return false;
        }
        return false;
    }

    /**
     * 校验sha3x 钱包是否合法
     * @param address
     * @return
     */
    public static boolean checkSha3x(String address){
        int length = address.length();

        if(StringUtils.isNotEmpty(address) && (length == 95 || length == 106) ){
            if (address.startsWith("4") || address.startsWith("8")){
                return true;
            }
            return false;
        }
        return false;
    }

    public static boolean checkAddress(String coin,String address) {
        //不同币种要单独设置验证方法
        String[] params = {address};

        //下面新增的币种暂时不通过节点校验
        if (coin.equals("monero")){
            return checkMonero(address);
        }
        if (coin.equals("sha3x")){
            return true;
        }

        String result = getResultTest(coin, "validateaddress", params);
        //处理result
        if(StringUtils.isBlank(result)){
            throw new RuntimeException("当前请求接口的用户过多,请稍后再试");
        }
        if("error:connection failed".equals(result)){
            throw new RuntimeException("当前请求接口的用户过多,请稍后再试");
        }
        if(result.contains("error:")){
            return false;
        }else {
            JSONObject jsonObject = JSON.parseObject(result);
            Boolean isvalid = jsonObject.getBoolean("isvalid");
            return isvalid;
        }
    }

    /**
     * 根据高度获取该高度对应的hash块
     * @param coin
     * @param height
     * @return
     */
    public static String getBlockInfoByHeight(String coin, Integer height){
        Integer[] params = {height};
        String result = getResultTest(coin, "getblockhash",params);
        return result;
    }

    /**
     * 根据hash 块的hash值获取该块的详细信息
     * @param coin
     * @param hash
     * @return
     */
    public static String getBlockInfoByHash(String coin,String hash){
        String[] params = {hash};
        String result = getResultTest(coin, "getblock",params);
        if(StringUtils.isBlank(result)){
            System.out.println("查询哈希块详细信息结果为空"+result);
            return result;
        }

        if(result.contains("error:")){
            System.out.println("查询哈希块详细信息包含错误："+result);
            return result;
        }
        JSONObject jsonObject = JSON.parseObject(result);
        String powAlgo = jsonObject.getString("pow_algo");
        return powAlgo;
    }

    public static String getHeight(String coin) {
        String result = getResult(coin, "getblockcount",null);
        //处理result
        if(StringUtils.isBlank(result)){
            System.out.println(coin+"获取高度失败 result为空");
            throw new RuntimeException();
        }
        if("error:connection failed".equals(result)){
            System.out.println(coin+"获取高度失败 连接失败");
            return "error:connection failed";
        }

        if(result.contains("error:")){
            System.out.println(coin+result+"获取高度失败");
            return "error: height get failed";
        }else {
           try {
               return result;
           }catch (Exception e){
               return "error: height get failed";
           }
        }

    }

    public static BlockInfo getBlock(String coin) {
        BlockInfo blockInfo = new BlockInfo();
        if(StringUtils.isBlank(coin)){
            return blockInfo;
        }
        coin = coin.toLowerCase();
        switch (coin){
            case "nexa": blockInfo=getNEXABlock();break;
            case "grs": blockInfo=getGRSBlock();break;
            case "mona": blockInfo=getMONABlock();break;
            case "dgbo": blockInfo=getDGBBlock().get("dgbo");break;
            case "dgbq": blockInfo=getDGBBlock().get("dgbq");break;
            case "dgbs": blockInfo=getDGBBlock().get("dgbs");break;
            case "rxd": blockInfo=getRXDBlock();break;
            case "alph": blockInfo=getALPHBlock();break;
            case "enx": blockInfo=getENXBlock();break;
            default: break;
        }

        return blockInfo;
    }


    public static BlockInfo getNEXABlock() {
        String coin = "nexa";
        String nowHeight = getHeight(coin);

        if(nowHeight.contains("error:")){
            return null;
        }

        String[] params = {};
        Object[] statsParams = {Convert.toLong(nowHeight)};
        //全网算力
        String result = getResult(coin, "getmininginfo", params);
        //本次报块奖励
        String result2 = getResultTest(coin, "getblockstats", statsParams);
        BlockInfo blockInfo = new BlockInfo();

        if(StringUtils.isBlank(result)){
            System.out.println("查询结果为空");
            return blockInfo;
        }

        if(result.contains("error:")){
            System.out.println("包含错误："+result);
            return blockInfo;
        }

        JSONObject jsonObject = JSON.parseObject(result);
        JSONObject statsJs = JSON.parseObject(result2);
        long height = jsonObject.getLongValue("blocks");
        blockInfo.setHeight(height);

        BigDecimal difficulty = jsonObject.getBigDecimal("difficulty");
        BigDecimal subsidy = statsJs.getBigDecimal("subsidy");
        if(StringUtils.isNull(subsidy)) {
            System.out.println("subsidy获取结果为空");
            return blockInfo;
        }
        if(StringUtils.isNotNull(difficulty)){
            blockInfo.setDifficulty(difficulty.setScale(2, RoundingMode.HALF_UP));
            //NodeConstant constant = (NodeConstant) EnumUtils.get(NodeConstant.class, coin);
            //BigDecimal factor =  constant.getFactor();
            //if(StringUtils.isNotNull(factor)){
            //    blockInfo.setPower(difficulty.multiply(factor).setScale(2,BigDecimal.ROUND_HALF_UP));
            //}
        }
        BigDecimal netPower = jsonObject.getBigDecimal("networkhashps");
        if (StringUtils.isNotNull(netPower)){
            blockInfo.setPower(netPower);
        }

        //JSONArray txs = jsonObject.getJSONArray("tx");
        //if(StringUtils.isNull(txs)){
        //    return null;
        //}
        //System.out.println(txs);
        //final double[] reward = {0};
        final double[] fees = {0};
        //txs.iterator().forEachRemaining(e -> {
        //    JSONObject json = (JSONObject) e;
        //    String vin = json.getString("vin");
        //    if(StringUtils.isNotNull(vin)){
        //        if(vin.length() == 2){
        //            reward[0] = json.getDoubleValue("sends");
        //        }else if(vin.length() > 2){
        //            BigDecimal fee = json.getBigDecimal("fee");
        //            BigDecimal newFees = fee.add(BigDecimal.valueOf(fees[0]));
        //            fees[0] = newFees.doubleValue();
        //        }
        //    }
        //});

        blockInfo.setReward(subsidy);
        blockInfo.setFees(BigDecimal.valueOf(fees[0]));
        blockInfo.setProfit(blockInfo.getReward().subtract(blockInfo.getFees()));
        System.out.println("blockInfo信息rpc"+blockInfo);
        return blockInfo;
    }

    public static BlockInfo getGRSBlock() {
        String coin = "grs";
        String nowHeight = getHeight(coin);

        if(nowHeight.contains("error:")){
            return null;
        }

        BlockInfo blockInfo = new BlockInfo();
        //todo 调用getblockstats 拿subsidy/100000000做reward fees设置为0、拿blockhash
        Object[] statsParams = {Convert.toLong(nowHeight)};
        String blockstats = getResultTest(coin, "getblockstats", statsParams);
        if(StringUtils.isBlank(blockstats)){
            System.out.println("blockstats查询结果为空");
            return blockInfo;
        }

        if(blockstats.contains("error:")){
            System.out.println("blockstats包含错误："+blockstats);
            return blockInfo;
        }

        JSONObject statsJs = JSON.parseObject(blockstats);
        String blockhash = statsJs.getString("blockhash");
        if(StringUtils.isBlank(blockstats)){
            System.out.println("blockhash获取结果为空");
            return blockInfo;
        }
        System.out.println(blockhash);


        BigDecimal subsidy = statsJs.getBigDecimal("subsidy");
        if(StringUtils.isNull(subsidy)) {
            System.out.println("subsidy获取结果为空");
            return blockInfo;
        }
        subsidy = subsidy.divide(BigDecimal.valueOf(Math.pow(10,8)),4,BigDecimal.ROUND_HALF_UP);
        System.out.println(subsidy);
        Object[] params = {blockhash};

        String result = getResultTest(coin, "getblockheader", params);


        String[] params1 = {};
        String result1 = getResult(coin, "getmininginfo", params1);


        if(StringUtils.isBlank(result) || StringUtils.isBlank(result1)){
            System.out.println("查询结果为空");
            return blockInfo;
        }

        if(result.contains("error:") || result1.contains("error:")){
            System.out.println("包含错误："+result);
            return blockInfo;
        }

        JSONObject jsonObject = JSON.parseObject(result);
        JSONObject jsonObject1 = JSON.parseObject(result1);
        BigDecimal netPower = jsonObject1.getBigDecimal("networkhashps");
        System.out.println("yyb-全网算力grs"+netPower);
        long height = jsonObject.getLongValue("height");
        blockInfo.setHeight(height);

        BigDecimal difficulty = jsonObject.getBigDecimal("difficulty");
        if(StringUtils.isNotNull(difficulty)){
            blockInfo.setDifficulty(difficulty.setScale(2,BigDecimal.ROUND_HALF_UP));
            //NodeConstant constant = (NodeConstant) EnumUtils.get(NodeConstant.class, coin);
            //BigDecimal factor =  constant.getFactor();
            //if(StringUtils.isNotNull(factor)){
            //    blockInfo.setPower(difficulty.multiply(factor).setScale(2,BigDecimal.ROUND_HALF_UP));
            //}
            blockInfo.setPower(netPower);

        }

        blockInfo.setReward(subsidy);
        blockInfo.setFees(BigDecimal.valueOf(0));
        blockInfo.setProfit(blockInfo.getReward().subtract(blockInfo.getFees()));
        return blockInfo;
    }

    public static BlockInfo getMONABlock() {
        String coin = "mona";
        String nowHeight = getHeight(coin);

        if(nowHeight.contains("error:")){
            return null;
        }

        BlockInfo blockInfo = new BlockInfo();
        //todo 调用getblockstats 拿subsidy/100000000做reward fees设置为0、拿blockhash
        Object[] statsParams = {Convert.toLong(nowHeight)};
        String blockstats = getResultTest(coin, "getblockstats", statsParams);
        if(StringUtils.isBlank(blockstats)){
            System.out.println("blockstats查询结果为空");
            return blockInfo;
        }

        if(blockstats.contains("error:")){
            System.out.println("blockstats包含错误："+blockstats);
            return blockInfo;
        }

        JSONObject statsJs = JSON.parseObject(blockstats);
        String blockhash = statsJs.getString("blockhash");
        if(StringUtils.isBlank(blockstats)){
            System.out.println("blockhash获取结果为空");
            return blockInfo;
        }
        System.out.println(blockhash);


        BigDecimal subsidy = statsJs.getBigDecimal("subsidy");
        if(StringUtils.isNull(subsidy)) {
            System.out.println("subsidy获取结果为空");
            return blockInfo;
        }
        subsidy = subsidy.divide(BigDecimal.valueOf(Math.pow(10,8)),4,BigDecimal.ROUND_HALF_UP);
        System.out.println(subsidy);
        Object[] params = {blockhash};

        String result = getResultTest(coin, "getblockheader", params);
        String[] params1 = {};
        String result1 = getResult(coin, "getmininginfo", params1);



        if(StringUtils.isBlank(result) || StringUtils.isBlank(result1)){
            System.out.println("查询结果为空");
            return blockInfo;
        }

        if(result.contains("error:") || result1.contains("error:")){
            System.out.println("包含错误："+result);
            return blockInfo;
        }

        JSONObject jsonObject = JSON.parseObject(result);
        JSONObject jsonObject1 = JSON.parseObject(result1);
        long height = jsonObject.getLongValue("height");
        blockInfo.setHeight(height);

        BigDecimal difficulty = jsonObject.getBigDecimal("difficulty");
        BigDecimal netPower = jsonObject1.getBigDecimal("networkhashps");
        System.out.println("yyb-全网算力mona"+netPower);
        if(StringUtils.isNotNull(difficulty)){
            blockInfo.setDifficulty(difficulty.setScale(2,BigDecimal.ROUND_HALF_UP));
            //NodeConstant constant = (NodeConstant) EnumUtils.get(NodeConstant.class, coin);
            //BigDecimal factor =  constant.getFactor();
            //if(StringUtils.isNotNull(factor)){
            //    blockInfo.setPower(difficulty.multiply(factor).setScale(2,BigDecimal.ROUND_HALF_UP));
            //}
            blockInfo.setPower(netPower);

        }

        blockInfo.setReward(subsidy);
        blockInfo.setFees(BigDecimal.valueOf(0));
        blockInfo.setProfit(blockInfo.getReward().subtract(blockInfo.getFees()));
        return blockInfo;
    }

    public static BlockInfo getRXDBlock() {
        String coin = "rxd";
        String nowHeight = getHeight(coin);

        if(nowHeight.contains("error:")){
            return null;
        }

        BlockInfo blockInfo = new BlockInfo();
        //todo 调用getblockstats 拿subsidy/100000000做reward fees设置为0、拿blockhash
        Object[] statsParams = {Convert.toLong(nowHeight)};
        String blockstats = getResultTest(coin, "getblockstats", statsParams);
        if(StringUtils.isBlank(blockstats)){
            System.out.println("blockstats查询结果为空");
            return blockInfo;
        }

        if(blockstats.contains("error:")){
            System.out.println("blockstats包含错误："+blockstats);
            return blockInfo;
        }

        JSONObject statsJs = JSON.parseObject(blockstats);
        String blockhash = statsJs.getString("blockhash");
        if(StringUtils.isBlank(blockstats)){
            System.out.println("blockhash获取结果为空");
            return blockInfo;
        }
        System.out.println(blockhash);


        BigDecimal subsidy = statsJs.getBigDecimal("subsidy");
        if(StringUtils.isNull(subsidy)) {
            System.out.println("subsidy获取结果为空");
            return blockInfo;
        }
        subsidy = subsidy.divide(BigDecimal.valueOf(Math.pow(10,8)),4,BigDecimal.ROUND_HALF_UP);
        System.out.println(subsidy);
        Object[] params = {blockhash};

        String result = getResultTest(coin, "getblockheader", params);
        String[] params1 = {};
        String result1 = getResult(coin, "getmininginfo", params1);


        if(StringUtils.isBlank(result) || StringUtils.isBlank(result1)){
            System.out.println("查询结果为空");
            return blockInfo;
        }

        if(result.contains("error:") || result1.contains("error:")){
            System.out.println("包含错误："+result);
            return blockInfo;
        }

        JSONObject jsonObject = JSON.parseObject(result);
        JSONObject jsonObject1 = JSON.parseObject(result1);
        long height = jsonObject.getLongValue("height");
        blockInfo.setHeight(height);

        BigDecimal difficulty = jsonObject.getBigDecimal("difficulty");
        BigDecimal netPower = jsonObject1.getBigDecimal("networkhashps");
        System.out.println("yyb-全网算力rxd"+netPower);
        if(StringUtils.isNotNull(difficulty)){
            blockInfo.setDifficulty(difficulty.setScale(2,BigDecimal.ROUND_HALF_UP));
            //NodeConstant constant = (NodeConstant) EnumUtils.get(NodeConstant.class, coin);
            //BigDecimal factor =  constant.getFactor();
            //if(StringUtils.isNotNull(factor)){
            //    blockInfo.setPower(difficulty.multiply(factor).setScale(2,BigDecimal.ROUND_HALF_UP));
            //}
            blockInfo.setPower(netPower);

        }

        blockInfo.setReward(subsidy);
        blockInfo.setFees(BigDecimal.valueOf(0));
        blockInfo.setProfit(blockInfo.getReward().subtract(blockInfo.getFees()));
        return blockInfo;
    }

    public static BlockInfo getALPHBlock() {
        String coin = "alph";
        //拿当前高度
        NodeConfig config = (NodeConfig) EnumUtils.get(NodeConfig.class, coin);

        String uri ="http://"+config.getIp()+":"+config.getHost();

        try {
            String heightUri = uri + "/blockflow/chain-info?fromGroup=0&toGroup=0";
            String heightBody = HttpRequest
                    .get(heightUri)
                    .header("X-API-KEY", "0x09e220e226f2feb7a971a2b6f958e7d4b1c187c8")
                    .header("Content-Type","application/json")
                    //.body(requestBody.toString())
                    .timeout(3000)
                    .execute()
                    .body();

            JSONObject heightJsonObject = JSON.parseObject(heightBody);
            System.out.println("alph 高度api请求结果：|"+heightBody+"|");

            long height = heightJsonObject.getLong("currentHeight");
            String heightError = heightJsonObject.getString("detail");

            if (StringUtils.isNull(height) && StringUtils.isNotBlank(heightError)){
                System.out.println("高度api调用 error:"+heightError);
                return null;
            }
            if(StringUtils.isNull(height) && StringUtils.isBlank(heightError)){
                System.out.println("height和error为空");
                return null;
            }

            BlockInfo blockInfo = new BlockInfo();
            blockInfo.setHeight(height);

            //根据高度拿到hash
            String hashUri = uri + "/blockflow/hashes?fromGroup=0&toGroup=0&height="+height;
            String hashBody = HttpRequest
                    .get(hashUri)
                    .header("X-API-KEY", "0x09e220e226f2feb7a971a2b6f958e7d4b1c187c8")
                    .header("Content-Type","application/json")
                    //.body(requestBody.toString())
                    .timeout(3000)
                    .execute()
                    .body();

            System.out.println("alph 哈希api请求结果：|"+hashBody+"|");
            JSONObject hashJsonObject = JSON.parseObject(hashBody);
            List<String> hashes = hashJsonObject.getJSONArray("headers").toJavaList(String.class);
            String hashError = hashJsonObject.getString("detail");
            if (StringUtils.isNull(hashes) && StringUtils.isNotBlank(hashError)){
                System.out.println("hashApi调用 error:"+hashError);
                return null;
            }
            if(StringUtils.isNull(hashes) && StringUtils.isBlank(hashError)){
                System.out.println("hashApi调用 未通过hashes获取到数据");
                return null;
            }

            String mainHash = "";
            for (String hash : hashes){
                //对每一个hash 请求is-block-in-main-chain 找出为true的hash 其他忽略
                String checkUri = uri + "/blockflow/is-block-in-main-chain?blockHash="+hash;
                String checkBody = HttpRequest
                        .get(checkUri)
                        .header("X-API-KEY", "0x09e220e226f2feb7a971a2b6f958e7d4b1c187c8")
                        .header("Content-Type","application/json")
                        //.body(requestBody.toString())
                        .timeout(3000)
                        .execute()
                        .body();
                System.out.println("alph 哈希校验api请求结果：|"+checkBody+"|");
                System.out.println("checkBody"+checkBody);
                if("true".equals(checkBody)){
                    mainHash = hash;
                    break;
                }
            }

            if(StringUtils.isBlank(mainHash)){
                return null;
            }
            System.out.println("mainHash:"+mainHash);
            //通过hash获取当前全网算力current-hashrate、获取当前全网难度current-difficulty
            String hashRateUri = uri + "/infos/current-hashrate";
            String hashRateBody = HttpRequest
                    .get(hashRateUri)
                    .header("X-API-KEY", "0x09e220e226f2feb7a971a2b6f958e7d4b1c187c8")
                    .header("Content-Type","application/json")
                    //.body(requestBody.toString())
                    .timeout(3000)
                    .execute()
                    .body();

            JSONObject hashRateJsonObject = JSON.parseObject(hashRateBody);
            System.out.println("alph 当前算力api请求结果：|"+hashRateJsonObject+"|");
            String hashRateStr = hashRateJsonObject.getString("hashrate");
            String hashRateError = hashRateJsonObject.getString("detail");

            if (StringUtils.isNull(hashRateStr) && StringUtils.isNotBlank(hashRateError)){
                System.out.println("当前全网算力APi调用 error:"+hashRateError);
                return null;
            }
            if(StringUtils.isNull(hashRateStr) && StringUtils.isBlank(hashRateError)){
                System.out.println("当前全网算力APi调用 未通过hashes获取到数据");
                return null;
            }
            BigDecimal hashrate= BigDecimal.ONE;
            if(hashRateStr.toUpperCase().contains("kh/s")){
                hashrate = new BigDecimal(hashRateStr.
                        replace("KH/s","").
                        replace(" ","")).
                        multiply(BigDecimal.valueOf(1000));
            }else if(hashRateStr.toLowerCase().contains("mh/s")){
                hashrate = new BigDecimal(hashRateStr.
                        replace("MH/s","").
                        replace(" ","")).
                        multiply(BigDecimal.valueOf(1000*1000));
            }else if(hashRateStr.toLowerCase().contains("gh/s")){
                hashrate = new BigDecimal(hashRateStr.
                        replace("GH/s","").
                        replace(" ","")).
                        multiply(BigDecimal.valueOf(1000*1000)).
                        multiply(BigDecimal.valueOf(1000));
            }else if(hashRateStr.toLowerCase().contains("th/s")){
                hashrate = new BigDecimal(hashRateStr.
                        replace("TH/s","").
                        replace(" ","")).
                        multiply(BigDecimal.valueOf(1000*1000)).
                        multiply(BigDecimal.valueOf(1000*1000));
            }else if(hashRateStr.toLowerCase().contains("ph/s")){
                hashrate = new BigDecimal(hashRateStr.
                        replace("PH/s","").
                        replace(" ","")).
                        multiply(BigDecimal.valueOf(1000*1000)).
                        multiply(BigDecimal.valueOf(1000*1000)).
                        multiply(BigDecimal.valueOf(1000));
            }else if(hashRateStr.toLowerCase().contains("h/s")){
                hashrate = new BigDecimal(hashRateStr.
                        replace("H/s","").
                        replace(" ",""));
            }else {
                //
            }

            blockInfo.setPower(hashrate);

            String diffUri = uri + "/infos/current-difficulty";
            String diffBody = HttpRequest
                    .get(diffUri)
                    .header("X-API-KEY", "0x09e220e226f2feb7a971a2b6f958e7d4b1c187c8")
                    .header("Content-Type","application/json")
                    //.body(requestBody.toString())
                    .timeout(3000)
                    .execute()
                    .body();

            JSONObject diffJsonObject = JSON.parseObject(diffBody);
            System.out.println("alph 当前难度api请求结果：|"+diffJsonObject+"|");
            BigDecimal diff = diffJsonObject.getBigDecimal("difficulty");
            String diffError = diffJsonObject.getString("detail");

            if (StringUtils.isNull(diff) && StringUtils.isNotBlank(diffError)){
                System.out.println("当前全网难度APi调用 error:"+diffError);
                return null;
            }
            if(StringUtils.isNull(diff) && StringUtils.isBlank(diffError)){
                System.out.println("当前全网难度APi调用 未通过hashes获取到数据");
                return null;
            }
            blockInfo.setDifficulty(diff);

            //
            String blockUri = uri + "/blockflow/blocks/"+mainHash;
            String blockBody = HttpRequest
                    .get(blockUri)
                    .header("X-API-KEY", "0x09e220e226f2feb7a971a2b6f958e7d4b1c187c8")
                    .header("Content-Type","application/json")
                    //.body(requestBody.toString())
                    .timeout(3000)
                    .execute()
                    .body();

            JSONObject blockJsonObject = JSON.parseObject(blockBody);
            //transactions[]的最后一个对象 判断inputs为空 再拿fixedOutputs中的attoAlphAmount/(10*8)作为reword
            System.out.println("alph 区块信息api请求结果：|"+hashRateJsonObject+"|");
            JSONArray transactions = blockJsonObject.getJSONArray("transactions");
            System.out.println("transactions|"+transactions+"|");
            JSONObject lastTransactionJsonObject = transactions.getJSONObject(transactions.size() - 1);
            JSONObject unsigned = lastTransactionJsonObject.getJSONObject("unsigned");
            System.out.println("unsigned|"+unsigned+"|");


            JSONArray inputs = unsigned.getJSONArray("inputs");

            if (inputs.size() == 0){
                System.out.println("为空");

                //inputs是空数组才能说明是报块奖励 而不是转账
                JSONArray fixedOutputs = unsigned.getJSONArray("fixedOutputs");
                JSONObject fixedOutput = fixedOutputs.getJSONObject(0);
                BigDecimal attoAlphAmount = fixedOutput.getBigDecimal("attoAlphAmount");
                BigDecimal reword = attoAlphAmount.divide(BigDecimal.valueOf(1000*1000),6,BigDecimal.ROUND_HALF_UP)
                        .divide(BigDecimal.valueOf(1000*1000),8,BigDecimal.ROUND_HALF_UP)
                        .divide(BigDecimal.valueOf(1000*1000),8,BigDecimal.ROUND_HALF_UP);
                blockInfo.setReward(reword);
                blockInfo.setFees(BigDecimal.ZERO);
                blockInfo.setProfit(reword);
            }

            return blockInfo;
        }catch (IORuntimeException e){
            System.out.println("alph  IO异常:"+e.getMessage());
            return null;
        }catch (Exception e){
            System.out.println("alph  抛出异常:"+e);
            return null;
        }

        //BigDecimal difficulty = jsonObject.getBigDecimal("difficulty");
        //if(StringUtils.isNotNull(difficulty)){
        //    blockInfo.setDifficulty(difficulty.setScale(2,BigDecimal.ROUND_HALF_UP));
        //    NodeConstant constant = (NodeConstant) EnumUtils.get(NodeConstant.class, coin);
        //    BigDecimal factor =  constant.getFactor();
        //    if(StringUtils.isNotNull(factor)){
        //        blockInfo.setPower(difficulty.multiply(factor).setScale(2,BigDecimal.ROUND_HALF_UP));
        //    }
        //
        //}
        //
        //blockInfo.setReward(subsidy);
        //blockInfo.setFees(BigDecimal.valueOf(0));
        //blockInfo.setProfit(blockInfo.getReward().subtract(blockInfo.getFees()));
        //return blockInfo;
    }

    public static Map<String,BlockInfo> getDGBBlock() {
        //dgb(qubit)、dgb(skein)、dgb(odo)实质都是dgb 高度始终一致、奖励也是
        String coin = "dgbq";
        HashMap<String,BlockInfo> map = new HashMap<>();
        String nowHeight = getHeight(coin);

        if(nowHeight.contains("error:")){
            System.out.println("nowHeight未正常返回");
            return null;
        }


        //todo 调用getblockstats 拿subsidy/100000000做reward fees设置为0、拿blockhash
        Object[] statsParams = {Convert.toLong(nowHeight)};
        String blockstats = getResultTest(coin, "getblockstats", statsParams);

        if(StringUtils.isBlank(blockstats)){
            System.out.println("blockstats查询结果为空");
            return null;
        }

        if(blockstats.contains("error:")){
            System.out.println("blockstats包含错误："+blockstats);
            return null;
        }

        JSONObject statsJs = JSON.parseObject(blockstats);
        BigDecimal subsidy = statsJs.getBigDecimal("subsidy");
        if(StringUtils.isNull(subsidy)) {
            System.out.println("subsidy获取结果为空");
            return null;
        }
        subsidy = subsidy.divide(BigDecimal.valueOf(Math.pow(10,8)),4,BigDecimal.ROUND_HALF_UP);
        System.out.println(subsidy);
        Object[] params = {};

        //替换掉
        //String result = getResultTest(coin, "getblockchaininfo", params);

        String[] params1 = {};
        String result = getResult(coin, "getmininginfo", params1);


        if(StringUtils.isBlank(result)){
            System.out.println("查询结果为空");
            return null;
        }

        if(result.contains("error:")){
            System.out.println("包含错误："+result);
            return null;
        }

        JSONObject jsonObject = JSON.parseObject(result);
        //难度
        JSONObject difficulties = jsonObject.getJSONObject("difficulties");
        //全网算力
        JSONObject networkhashesps = jsonObject.getJSONObject("networkhashesps");
        if(StringUtils.isNull(difficulties) || StringUtils.isNull(networkhashesps)){
            System.out.println("查询结果为空");
            return null;
        }
        BigDecimal sDiff = difficulties.getBigDecimal("skein");
        BigDecimal sNetwork = networkhashesps.getBigDecimal("skein");
        if(StringUtils.isNotNull(sDiff)){
            BlockInfo sBlockInfo = new BlockInfo();
            sBlockInfo.setHeight(Convert.toLong(nowHeight,20237944L));
            sBlockInfo.setReward(subsidy);
            sBlockInfo.setFees(BigDecimal.ZERO);
            sBlockInfo.setProfit(sBlockInfo.getReward().subtract(sBlockInfo.getFees()));
            sBlockInfo.setDifficulty(sDiff.setScale(2,BigDecimal.ROUND_HALF_UP));
            //NodeConstant constant = (NodeConstant) EnumUtils.get(NodeConstant.class, "dgbs");
            //BigDecimal factor =  constant.getFactor();
            //if(StringUtils.isNotNull(factor)){
            //    sBlockInfo.setPower(sDiff.multiply(factor).setScale(2,BigDecimal.ROUND_HALF_UP));
            //}
            sBlockInfo.setPower(sNetwork);
            map.put("dgbs",sBlockInfo);
        }

        BigDecimal oDiff = difficulties.getBigDecimal("odo");
        BigDecimal oNetwork = networkhashesps.getBigDecimal("odo");
        if(StringUtils.isNotNull(oDiff)){
            BlockInfo oBlockInfo = new BlockInfo();
            oBlockInfo.setHeight(Convert.toLong(nowHeight,20237944L));
            oBlockInfo.setReward(subsidy);
            oBlockInfo.setFees(BigDecimal.ZERO);
            oBlockInfo.setProfit(oBlockInfo.getReward().subtract(oBlockInfo.getFees()));
            oBlockInfo.setDifficulty(oDiff.setScale(2,BigDecimal.ROUND_HALF_UP));
            //NodeConstant constant = (NodeConstant) EnumUtils.get(NodeConstant.class, "dgbo");
            //BigDecimal factor =  constant.getFactor();
            //if(StringUtils.isNotNull(factor)){
            //    oBlockInfo.setPower(oDiff.multiply(factor).setScale(2,BigDecimal.ROUND_HALF_UP));
            //}
            oBlockInfo.setPower(oNetwork);
            map.put("dgbo",oBlockInfo);
        }

        BigDecimal qDiff = difficulties.getBigDecimal("qubit");
        BigDecimal qNetwork = networkhashesps.getBigDecimal("qubit");
        if(StringUtils.isNotNull(qDiff)){
            BlockInfo qBlockInfo = new BlockInfo();
            qBlockInfo.setHeight(Convert.toLong(nowHeight,20237944L));
            qBlockInfo.setReward(subsidy);
            qBlockInfo.setFees(BigDecimal.ZERO);
            qBlockInfo.setProfit(qBlockInfo.getReward().subtract(qBlockInfo.getFees()));
            qBlockInfo.setDifficulty(qDiff.setScale(2,BigDecimal.ROUND_HALF_UP));
            //NodeConstant constant = (NodeConstant) EnumUtils.get(NodeConstant.class, "dgbq");
            //BigDecimal factor =  constant.getFactor();
            //if(StringUtils.isNotNull(factor)){
            //    qBlockInfo.setPower(qDiff.multiply(factor).setScale(2,BigDecimal.ROUND_HALF_UP));
            //}
            qBlockInfo.setPower(qNetwork);
            map.put("dgbq",qBlockInfo);
        }
        System.out.println("存储的数据"+map);
        return map;
    }


    public static BlockInfo getENXBlock() {
        String coin = "enx";
        //报块信息
        String uri = "https://api.entropyx.org/api/info/blockdag";

        //get方法拿reward
        String rewardUri = "https://api.entropyx.org/api/info/blockreward";

        BlockInfo blockInfo = new BlockInfo();

        //get方法拿fee
        String feeUri = "https://api.entropyx.org/api/burn/get-current-burn-fee";
        blockInfo.setReward(BigDecimal.valueOf(333));
        try {
            String body = HttpRequest
                    .get(uri)
                    .header(HttpHeaders.ACCEPT,"application/json")
                    .timeout(3000)
                    .execute()
                    .body();

            JSONObject jsonObject = JSON.parseObject(body);
            if (StringUtils.isNull(jsonObject)){
                return blockInfo;
            }
            BigDecimal reward = jsonObject.getBigDecimal("blockreward");
            blockInfo.setReward(reward);
        } catch (Exception e) {
            System.out.println("Error: cannont access content - " + e.toString());
            return blockInfo;
        }


        //todo 调用getblockstats 拿subsidy/100000000做reward fees设置为0、拿blockhash
        //Object[] statsParams = {Convert.toLong(nowHeight)};
        //String blockstats = getResultTest(coin, "getblockstats", statsParams);
        //if(StringUtils.isBlank(blockstats)){
        //    System.out.println("blockstats查询结果为空");
        //    return blockInfo;
        //}
        //
        //if(blockstats.contains("error:")){
        //    System.out.println("blockstats包含错误："+blockstats);
        //    return blockInfo;
        //}
        //
        //JSONObject statsJs = JSON.parseObject(blockstats);
        //String blockhash = statsJs.getString("blockhash");
        //if(StringUtils.isBlank(blockstats)){
        //    System.out.println("blockhash获取结果为空");
        //    return blockInfo;
        //}
        //System.out.println(blockhash);
        //
        //
        //BigDecimal subsidy = statsJs.getBigDecimal("subsidy");
        //if(StringUtils.isNull(subsidy)) {
        //    System.out.println("subsidy获取结果为空");
        //    return blockInfo;
        //}
        //subsidy = subsidy.divide(BigDecimal.valueOf(Math.pow(10,8)),4,BigDecimal.ROUND_HALF_UP);
        //System.out.println(subsidy);
        //Object[] params = {blockhash};
        //
        //String result = getResultTest(coin, "getblockheader", params);
        //System.out.println("result"+result);
        //
        //
        //
        //if(StringUtils.isBlank(result)){
        //    System.out.println("查询结果为空");
        //    return blockInfo;
        //}
        //
        //if(result.contains("error:")){
        //    System.out.println("包含错误："+result);
        //    return blockInfo;
        //}
        //
        //JSONObject jsonObject = JSON.parseObject(result);
        //long height = jsonObject.getLongValue("height");
        //blockInfo.setHeight(height);
        //
        //BigDecimal difficulty = jsonObject.getBigDecimal("difficulty");
        //if(StringUtils.isNotNull(difficulty)){
        //    blockInfo.setDifficulty(difficulty.setScale(2,BigDecimal.ROUND_HALF_UP));
        //    NodeConstant constant = (NodeConstant) EnumUtils.get(NodeConstant.class, coin);
        //    BigDecimal factor =  constant.getFactor();
        //    if(StringUtils.isNotNull(factor)){
        //        blockInfo.setPower(difficulty.multiply(factor).setScale(2,BigDecimal.ROUND_HALF_UP));
        //    }
        //
        //}
        //
        //blockInfo.setReward(subsidy);
        //blockInfo.setFees(BigDecimal.valueOf(0));
        //blockInfo.setProfit(blockInfo.getReward().subtract(blockInfo.getFees()));
        //return blockInfo;
        return  blockInfo;
    }


}











