package com.m2pool.lease.task;

import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.m2pool.lease.dto.ProductMachineDto;
import com.m2pool.lease.entity.LeaseProductMachine;
import com.m2pool.lease.mapper.LeaseProductMachineMapper;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @Description TODO
 * @Date 2025/11/7 14:16
 * @Author yyb
 */
@Configuration
@EnableScheduling
public class RealPowerInsetTask {

    @Resource
    private LeaseProductMachineMapper leaseProductMachineMapper;

    private static final int BATCH_SIZE = 1000;
    private static final int THREAD_POOL_SIZE = Runtime.getRuntime().availableProcessors();
    private final ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
    public void batchInsert(String coin,List<ProductMachineDto> recentlyFiveMinutesData) {
        // 用于记录执行过程中的异常
        AtomicReference<Exception> exceptionRef = new AtomicReference<>();
        List<CompletableFuture<Void>> futures = new ArrayList<>();

        for (int i = 0; i < recentlyFiveMinutesData.size(); i += BATCH_SIZE) {
            int toIndex = Math.min(i + BATCH_SIZE, recentlyFiveMinutesData.size());
            List<ProductMachineDto> subList = recentlyFiveMinutesData.subList(i, toIndex);

            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                try {
                    leaseProductMachineMapper.batchInsertPowers(coin, subList);
                } catch (Exception e) {
                    exceptionRef.set(e);
                    throw new RuntimeException(e);
                }
            }, executorService);

            futures.add(future);
        }
        // 等待所有任务完成
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
        try {
            allFutures.get();
        } catch (InterruptedException | ExecutionException e) {
            // 如果有异常，将异常信息设置到 exceptionRef 中
            exceptionRef.set(e);
        }

        // 如果有异常，抛出异常触发事务回滚
        if (exceptionRef.get() != null) {
            System.out.println("批量插入数据实时算力数据出错"+exceptionRef.get());
            throw new RuntimeException("批量插入数据实时算力数据出错", exceptionRef.get());
        }
    }

    public List<ProductMachineDto> getRealPower(String coin){
        List<LeaseProductMachine> leaseProductMachines = leaseProductMachineMapper.selectList(new LambdaQueryWrapper<LeaseProductMachine>()
                .eq(LeaseProductMachine::getDel, false));
        List<ProductMachineDto> recentlyFiveMinutesData = leaseProductMachineMapper.getRecentlyFiveMinutesData(leaseProductMachines, coin);
        for (ProductMachineDto recentlyFiveMinutesDatum : recentlyFiveMinutesData) {
            recentlyFiveMinutesDatum.setComputingPower(recentlyFiveMinutesDatum.getComputingPower()
                    .divide(BigDecimal.valueOf(24 * 60 * 60),2, RoundingMode.HALF_UP));
        }
        return recentlyFiveMinutesData;
    }


    @Scheduled(cron = "0 0/5 * * * ? ")
    @DSTransactional
    public void nexaRealPowerInset(){
        List<ProductMachineDto> nexaPower = getRealPower("nexa");
        batchInsert("nexa",nexaPower);

    }

    @Scheduled(cron = "0 0/5 * * * ? ")
    @DSTransactional
    public void monaRealPowerInset(){
        List<ProductMachineDto> monaPower = getRealPower("mona");
        batchInsert("mona",monaPower);
    }

    @Scheduled(cron = "0 0/5 * * * ? ")
    @DSTransactional
    public void rxdRealPowerInset(){
        List<ProductMachineDto> rxdPower = getRealPower("mona");
        batchInsert("rxd",rxdPower);
    }

    @Scheduled(cron = "0 0/5 * * * ? ")
    @DSTransactional
    public void grsRealPowerInset(){
        List<ProductMachineDto> rxdPower = getRealPower("grs");
        batchInsert("grs",rxdPower);
    }

}
