package com.m2pool.lease.task;

import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.m2pool.lease.constant.BlockInterval;
import com.m2pool.lease.entity.LeaseGpuConfig;
import com.m2pool.lease.entity.LeaseMiningSoftwareConfig;
import com.m2pool.lease.mapper.LeaseGpuConfigMapper;
import com.m2pool.lease.mapper.LeaseMiningSoftwareConfigMapper;
import com.m2pool.lease.task.info.*;
import io.lettuce.core.ScriptOutputType;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description 获取gpu 信息三方api：whattomine.com 定时任务
 * @Date 2025/12/16 15:38
 * @Author yyb
 */
@Configuration
@EnableScheduling
public class GpuRequestApiTask {

    @Resource
    private LeaseGpuConfigMapper leaseGpuConfigMapper;

    @Resource
    private LeaseMiningSoftwareConfigMapper leaseMiningSoftwareConfigMapper;

    @Scheduled(cron = "0 0 0/6 * * ? ")
    //@Scheduled(cron = "0 0/5 * * * ? ")
    public void gpuInfoTask(){
        List<GpuInfo> gpuInfos = fetchGpuInfo();
        List<LeaseGpuConfig> leaseGpuConfigs = convertGpuInfoToLeaseConfig(gpuInfos);
        List<LeaseMiningSoftwareConfig> leaseMiningSoftwareConfigs = leaseMiningSoftwareConfigMapper.
                selectList(new LambdaQueryWrapper<>());
        //选出挖矿软件只支持的算法和币种
        List<LeaseGpuConfig> leaseGpuConfigs1 = new ArrayList<>();
        for (LeaseGpuConfig leaseGpuConfig : leaseGpuConfigs) {
            for (LeaseMiningSoftwareConfig leaseMiningSoftwareConfig : leaseMiningSoftwareConfigs) {
                if (leaseMiningSoftwareConfig.getAlgorithm().contains(leaseGpuConfig.getAlgorithm())){
                    leaseGpuConfig.setCoin(leaseMiningSoftwareConfig.getCoin());
                    leaseGpuConfigs1.add(leaseGpuConfig);
                    break;
                }
            }
        }
        List<AlgorithmInfo> coinNetPowers = fetchMiningPower();
        if (!coinNetPowers.isEmpty()){
            Map<String, AlgorithmInfo> coinPowerMap = coinNetPowers.stream()
                    .collect(Collectors.toMap(AlgorithmInfo-> AlgorithmInfo.getCoin()+"-"+AlgorithmInfo.getName(), Function.identity()));
            for (LeaseGpuConfig leaseGpuConfig : leaseGpuConfigs1) {
                AlgorithmInfo coinPower = coinPowerMap.get(leaseGpuConfig.getCoin()+"-"+leaseGpuConfig.getAlgorithm());
                BigDecimal monthIncome = calculateMonthIncome(leaseGpuConfig, coinPower);
                leaseGpuConfig.setMonthIncome(monthIncome);
            }

        }
        leaseGpuConfigMapper.insertOrUpdateBatchByEntity(leaseGpuConfigs1);
    }

    /**
     * 计算月收入
     * @param leaseGpuConfig
     * @param coinPower
     * @return
     */
    private static BigDecimal calculateMonthIncome(LeaseGpuConfig leaseGpuConfig,  AlgorithmInfo coinPower) {
        BigDecimal monthIncome = BigDecimal.ZERO;
        if (coinPower != null){
            monthIncome = leaseGpuConfig.getHashrate()
                    .divide(coinPower.getHashrate().divide(BigDecimal.valueOf(1000 * 1000), 8, RoundingMode.HALF_UP), 8, RoundingMode.HALF_UP)
                    .multiply(BigDecimal.valueOf(24 * 60 * 60)
                            .divide(coinPower.getBlockInterval(), 8, RoundingMode.HALF_UP))
                    .multiply(coinPower.getBlockReward()).multiply(BigDecimal.valueOf(30))
                    .multiply(coinPower.getPrice())
            ;
        }
        return monthIncome;
    }


    /**
     * 三方api 获取gpu信息
     * @return
     */
    public List<GpuInfo> fetchGpuInfo() {
        String url = "https://whattomine.com/api/v1/gpus?api_token=8ea12738081eaa70a37d62364ddfffecc0c96a6047f02b4cc728af7588fcdbd8";
        String response = HttpRequest.get(url).execute().body();

        // 将JSONUtil.parseArray改为JSON.parseArray
        JSONArray gpusArray = JSON.parseArray(response);
        List<GpuInfo> gpuInfoList = new ArrayList<>();

        for (Object obj : gpusArray) {
            // JSONObject转换方式
            JSONObject gpuJson = (JSONObject) obj;
            GpuInfo gpuInfo = new GpuInfo();

            // 设置基本GPU信息
            gpuInfo.setId(gpuJson.getLong("id"));
            gpuInfo.setName(gpuJson.getString("name"));
            gpuInfo.setRelease_date(gpuJson.getString("release_date"));

            // 处理算法信息
            JSONArray algorithmsArray = gpuJson.getJSONArray("algorithms");
            List<AlgorithmInfo> algorithmInfos = new ArrayList<>();

            for (Object algoObj : algorithmsArray) {
                // JSONObject转换方式
                JSONObject algoJson = (JSONObject) algoObj;
                AlgorithmInfo algorithmInfo = new AlgorithmInfo();

                algorithmInfo.setName(algoJson.getString("name"));
                algorithmInfo.setHashrate(algoJson.getBigDecimal("hashrate"));
                algorithmInfo.setPower(algoJson.getBigDecimal("power"));

                algorithmInfos.add(algorithmInfo);
            }

            gpuInfo.setAlgorithms(algorithmInfos);
            gpuInfoList.add(gpuInfo);
        }

        return gpuInfoList;
    }


    public List<LeaseGpuConfig> convertGpuInfoToLeaseConfig(List<GpuInfo> gpuInfos) {
        List<LeaseGpuConfig> leaseGpuConfigs = new ArrayList<>();

        for (GpuInfo gpuInfo : gpuInfos) {
            if (gpuInfo.getAlgorithms() != null) {
                for (AlgorithmInfo algorithm : gpuInfo.getAlgorithms()) {
                    LeaseGpuConfig config = buildGpuConfig(gpuInfo, algorithm);
                    leaseGpuConfigs.add(config);
                }
            }
        }

        return leaseGpuConfigs;
    }

    private static LeaseGpuConfig buildGpuConfig(GpuInfo gpuInfo, AlgorithmInfo algorithm) {
        LeaseGpuConfig config = new LeaseGpuConfig();
        config.setName(gpuInfo.getName());
        config.setAlgorithm(algorithm.getName());
        config.setHashrate(algorithm.getHashrate().divide(BigDecimal.valueOf(1000 * 1000),2, RoundingMode.HALF_UP));
        config.setPowerDissipation(algorithm.getPower());
        return config;
    }


    /**
     * 三方api 获取gpu 对应算法的收益信息
     * @return
     */
    public static List<AlgorithmInfo> fetchMiningPower() {
        String url = "https://whattomine.com/api/v1/coins?api_token=8ea12738081eaa70a37d62364ddfffecc0c96a6047f02b4cc728af7588fcdbd8";
        String response = HttpRequest.get(url).execute().body();
        JSONArray gpusArray = JSON.parseArray(response);
        List<AlgorithmInfo> hashRateInfos = new ArrayList<>();
        for (int i = 0; i < gpusArray.size(); i++) {
            JSONObject item = gpusArray.getJSONObject(i);
            AlgorithmInfo info = new AlgorithmInfo();
            info.setCoin(item.getString("tag"));
            info.setName(item.getString("algorithm"));
            info.setHashrate(new BigDecimal(item.getLong("nethash")));
            info.setBlockReward(BigDecimal.valueOf(item.getDouble("block_reward")));
            info.setBlockInterval(BigDecimal.valueOf(item.getDouble("block_time")));
            // 解析exchanges数组并获取第一个对象的price值
            JSONArray exchanges = item.getJSONArray("exchanges");
            if (!exchanges.isEmpty()) {
                JSONObject firstExchange = exchanges.getJSONObject(0);
                //30日平均币价
                info.setPrice(BigDecimal.valueOf(firstExchange.getDouble("price30")).multiply(BigDecimal.valueOf(100000)));
            }
            hashRateInfos.add(info);
        }
        return hashRateInfos;
    }
}
