package com.m2pool.lease.task;

import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.m2pool.common.core.utils.DateUtils;
import com.m2pool.lease.aspect.LedgerLogService;
import com.m2pool.lease.constant.PowerUnit;
import com.m2pool.lease.dto.*;
import com.m2pool.lease.dto.v2.PurchasedMachineListDto;
import com.m2pool.lease.dto.v2.RealHashrateInfoDto;
import com.m2pool.lease.entity.*;
import com.m2pool.lease.mapper.*;
import com.m2pool.lease.mq.message.RabbitmqDeleteWalletMessage;
import com.m2pool.lease.mq.message.RabbitmqPayAutoMessage;
import com.m2pool.lease.service.LeaseOrderItemService;
import com.m2pool.lease.service.LeasePayRecordMessageInfoService;
import com.m2pool.lease.service.LeasePayRecordMessageService;
import com.m2pool.lease.service.LeaseUserOwnedProductService;
import com.m2pool.lease.utils.HashUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
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.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.m2pool.lease.constant.RabbitmqConstant.DELETE_WALLET_QUEUE;
import static com.m2pool.lease.constant.RabbitmqConstant.PAY_AUTO_QUEUE;

/**
 * @Description 订单超时 定时任务
 * @Date 2025/7/15 15:45
 * @Author yyb
 */
@Configuration
@EnableScheduling
public class OrderAndPayTask {


    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private LeaseOrderInfoMapper leaseOrderInfoMapper;
    @Resource
    private LeaseOrderItemMapper leaseOrderItemMapper;
    @Resource
    private LeaseProductMachineMapper leaseProductMachineMapper;
    @Resource
    private LeaseUserWalletDataMapper leaseUserWalletDataMapper;
    @Resource
    private LeasePayRecordMessageService leasePayRecordMessageService;
    @Resource
    private LeasePayRecordMessageMapper leasePayRecordMessageMapper;
    @Resource
    private LeasePayWithdrawMessageMapper leasePayWithdrawMessageMapper;
    @Resource
    private LeasePayRechargeMessageMapper leasePayRechargeMessageMapper;
    @Resource
    private LeaseUserOwnedProductService leaseUserOwnedProductService;
    @Resource
    private LeaseAutoAddressMapper leaseAutoAddressMapper;
    @Resource
    private LeaseShopConfigMapper  leaseShopConfigMapper;
    @Resource
    private LeaseOrderItemService leaseOrderItemService;
    @Resource
    private LeasePayRecordMessageInfoService leasePayRecordMessageInfoService;
    @Resource
    private LeaseMachineTempConfigMapper leaseMachineTempConfigMapper;
    @Resource
    private LeaseOrderMiningMapper leaseOrderMiningMapper;
    @Resource
    private LeaseMachineMapper leaseMachineMapper;
    @Resource
    private LedgerLogService ledgerLogService;

    /**
     * 检查钱包半年内是否有 支付，充值，提现操作
     */
    @Scheduled(cron = "0 5 1 * * ? ")
    //@Scheduled(cron = "0 0/1 * * * ? ")
    @Transactional
    public void checkOperator(){
        //1.查询lease_auto_address 表 状态为1 已使用 的钱包
        List<UserWalletDataDto> validAddress = leaseAutoAddressMapper.getValidAddress();
        if (validAddress.isEmpty()){
            return;
        }
        //2.获取创建时间大于半年，且余额为0的钱包
        List<LeaseUserWalletData> walletForBalanceIsZero = leaseUserWalletDataMapper.getWalletForBalanceIsZero(validAddress);
        if (walletForBalanceIsZero.isEmpty()){
            return;
        }
        //3.根据钱包查询lease_pay_record_message，lease_pay_recharge_message，lease_pay_withdraw_message 三表半年内是否有记录
        Map<String, CheckAddressDto> payRecordMessageMap = leasePayRecordMessageMapper.checkPayOperatorBatch(walletForBalanceIsZero);
        Map<String, CheckAddressDto> withdrawMessageMap = leasePayWithdrawMessageMapper.checkWithdrawOperatorBatch(walletForBalanceIsZero);
        Map<String, CheckAddressDto> rechargeMessageMap = leasePayRechargeMessageMapper.checkRechargeOperatorBatch(walletForBalanceIsZero);

        //3.如果没有记录，则修改钱包的状态为 2已过期
        for (LeaseUserWalletData userWalletDataDto : walletForBalanceIsZero) {
            String address = userWalletDataDto.getFromAddress();
            CheckAddressDto payRecordMessage = payRecordMessageMap.get(address);
            CheckAddressDto withdrawMessage = withdrawMessageMap.get(address);
            CheckAddressDto rechargeMessage = rechargeMessageMap.get(address);

            if (payRecordMessage == null && withdrawMessage == null && rechargeMessage == null){
                //发送钱包过期删除监听mq消息
                long l = System.currentTimeMillis()/1000L;
                RabbitmqDeleteWalletMessage build = RabbitmqDeleteWalletMessage.builder()
                        .msg_type(0)
                        .queue_id(userWalletDataDto.getQueueId())
                        .chain(userWalletDataDto.getFromChain())
                        .symbol(userWalletDataDto.getFromSymbol())
                        .address(userWalletDataDto.getFromAddress())
                        .timestamp(l)
                        .sign(HashUtils.sha256(l)).build();
                rabbitTemplate.convertAndSend(DELETE_WALLET_QUEUE, build);
                System.out.println("发送钱包过期删除监听mq消息成功");
            }
        }

    }

    @Scheduled(cron = "0 0/1 * * * ? ")
    @DSTransactional
    public void paymentTaskV2(){
        Date now = DateUtils.getPreviousHalfHourOrFullHour(new Date());
        //1.查找在进行中的订单
        List<LeaseOrderInfo> needPayOrderList = leaseOrderInfoMapper.getNeedPayOrderList();
        if (needPayOrderList.isEmpty()){
            System.out.println("没有进行中的订单");
            return;
        }
        List<Long> infoIds = new ArrayList<>();
        Map<Long, LeaseOrderInfo> queueIdMap = new HashMap<>();
        for (LeaseOrderInfo leaseOrderInfo : needPayOrderList) {
            queueIdMap.put(leaseOrderInfo.getId(), leaseOrderInfo);
            infoIds.add(leaseOrderInfo.getId());
        }

        //2.根据订单号找到对应的订单详情(状态为1 租约生效中) ,并根据这些订单详情找到每个矿机的信息
        List<LeaseOrderItem> leaseOrderItems = leaseOrderItemMapper.selectList(new LambdaQueryWrapper<LeaseOrderItem>()
                .eq(LeaseOrderItem::getStatus,1)
                .in(LeaseOrderItem::getOrderId, infoIds));

        //本次全部完成的订单id 集合
        List<Long> orderComplete = new ArrayList<>();
        //本次部分已完成订单详情id + 矿机 集合
        List<Long> itemCompleteIds = new ArrayList<>();

        List<LeaseMachine> completeMachines = new ArrayList<>();
        //本此需支付订单详情id 集合
        List<Long> needPayIds = new ArrayList<>();
        //本次需支付订单详情 集合
        List<LeaseOrderItem> needPayInfos = new ArrayList<>();
        getCompleteOrderAndNeedPayOrder(orderComplete,completeMachines,itemCompleteIds,needPayIds,needPayInfos,leaseOrderItems);
        //订单进行过程中,卖方可能修改收款地址。所以每天支付前，需要修改旧收款地址为新地址
        needPayInfos = updateOrderItemSellerWalletAddress(needPayInfos);

        //1.处理需要支付的订单
        //根据 lease_order_item 中订单id 查找到 对应的lease_order_mining 信息
        List<PurchasedMachineListDto> miningInfoByOrderId = leaseOrderMiningMapper.getMiningInfoByOrderId(needPayIds);
        //根据lease_order_mining 中相关信息 钱包 + 币种 + 算法 + 矿工号 + 矿池名 找到对应的实时算力
        if (!miningInfoByOrderId.isEmpty()){
            Map<String, List<PurchasedMachineListDto>> collect = miningInfoByOrderId.stream().collect(Collectors.groupingBy(PurchasedMachineListDto::getPool));

            //挖矿信息 与 订单详情id 映射
            Map<String, PurchasedMachineListDto> miningAnditemIdMap = miningInfoByOrderId.stream()
                    .collect(Collectors.toMap(
                            dto -> dto.getPool() + "_" + dto.getWalletAddress() + "_" +
                                    dto.getWorkerId() + "_" + dto.getCoin() + "_" + dto.getAlgorithm(),
                            Function.identity(),
                            (existing, replacement) -> replacement
                    ));

            List<RealHashrateInfoDto> realPowerList = new ArrayList<>();
            collect.forEach((pool, list) -> {
                realPowerList.addAll(leaseOrderMiningMapper.getRecently24HourHashrate(list, pool, now));
            });
            //挖矿信息 与 实时算力 映射
            Map<String, List<RealHashrateInfoDto>> groupedData = realPowerList.stream()
                    .collect(Collectors.groupingBy(
                            dto -> dto.getPool() + "_" + dto.getWalletAddress() + "_" +
                                    dto.getMiner() + "_" + dto.getCoin() + "_" + dto.getAlgorithm()
                    ));

            //订单id 与 实时算力 映射
            Map<Long, List<RealHashrateInfoDto>> orderIdToHashrateMap = new HashMap<>();
            getOrderItemIdToHashrateMap(orderIdToHashrateMap,miningAnditemIdMap,groupedData);

            //根据实时算力波动情况 求得订单实际支付金额
            Map<Long, LeaseOrderItem> orderIdToPriceMap = needPayInfos.stream().collect(Collectors.toMap(LeaseOrderItem::getId,Function.identity()));
            Map<Long, BigDecimal> orderItemToPriceMap = orderPaymentWaveAlgorithm(orderIdToHashrateMap,orderIdToPriceMap);

            Map<Long, List<LeaseOrderItem>> userMapItem = needPayInfos.stream()
                    .collect(Collectors.groupingBy(LeaseOrderItem::getOrderId));

            List<LeasePayRecordMessageInfo> recordMessageInfoList = new ArrayList<>();
            List<LeaseOrderItem> saleIngList = new ArrayList<>();
            // 按照订单分组
            userMapItem.forEach((orderId, items) -> {
                LeaseOrderItem leaseOrderItem = items.get(0);
                long timestamp = System.currentTimeMillis()/1000;
                //因为同一个订单的queueId相同，所以这里直接使用订单id
                LeaseOrderInfo orderInfo = queueIdMap.get(orderId);
                //买方信息
                LeasePayRecordMessageInfo build = LeasePayRecordMessageInfo.builder()
                        .orderId(String.valueOf(orderId))
                        .orderNumber(orderInfo.getOrderNumber())
                        .queueId(orderInfo.getOrderNumber())
                        .fromAddress(leaseOrderItem.getFromAddress())
                        .toAddress(leaseOrderItem.getAddress())
                        .amount(BigDecimal.ZERO)
                        .realAmount(BigDecimal.ZERO)
                        .needAmount(BigDecimal.ZERO)
                        .blockAmount(BigDecimal.ZERO)
                        .fromChain(leaseOrderItem.getChain())
                        .fromSymbol(leaseOrderItem.getSymbol())
                        .shopId(leaseOrderItem.getShopId())
                        .userId(leaseOrderItem.getUserId())
                        .toChain(leaseOrderItem.getChain())
                        .toSymbol(leaseOrderItem.getSymbol())
                        .build();

                for (LeaseOrderItem item : items) {
                    BigDecimal realAmount = orderItemToPriceMap.get(item.getId());
                    BigDecimal realPayAmount =  realAmount== null ? BigDecimal.ZERO : realAmount;
                    //已支付金额 和实际待支付金额
                    item.setAlreadyPayAmount(item.getAlreadyPayAmount().add(item.getPrice().multiply(BigDecimal.valueOf(item.getNumbers()))));
                    item.setSettlePayRealAmount(item.getSettlePayRealAmount().add(realPayAmount));
                    //设置理论支付金额 和 冻结金额 额 （冻结金额 = 理论支付金额）
                    build.setBlockAmount(build.getBlockAmount().add(item.getPrice().multiply(BigDecimal.valueOf(item.getNumbers()))));
                    build.setAmount(build.getAmount().add(item.getPrice().multiply(BigDecimal.valueOf(item.getNumbers()))));
                    // 实际支付金额 + 理论实际应支付金额
                    build.setRealAmount(build.getRealAmount().add(realPayAmount));
                    build.setNeedAmount(build.getNeedAmount().add(realPayAmount));
                    saleIngList.add(item);
                }
                //实际支付金额即使为0也要记录
                recordMessageInfoList.add(build);
                //实际支付不为0才记录
                //if (build.getRealAmount().compareTo(BigDecimal.ZERO) > 0){
                //    recordMessageInfoList.add(build);
                //}
            });

            //修改订单支付金额等相关信息
            leaseOrderItemService.updateBatchById(saleIngList);
            //保存支付信息到支付记录表中
            if (!recordMessageInfoList.isEmpty()){
                leasePayRecordMessageInfoService.saveBatch(recordMessageInfoList);
            }
        }
        //2.处理完成的订单 (订单部分完成)
        if(!itemCompleteIds.isEmpty()){
            handlerOrderPartComplete(itemCompleteIds,completeMachines);
        }

        //3.处理完成的订单 + 发送mq消息去支付（订单全部完成）
        if (!orderComplete.isEmpty()){
            handlerOrderAllComplete(orderComplete);
        }

    }


    /**
     * 获取订单完成和需要支付的订单id
     * @param orderComplete 订单是否完成（所有子订单完成）
     * @param completeIds 本次完成子订单 id集合
     * @param needPayIds 本次需要支付的订单 id集合
     * @param needPayInfos 本次需要支付的订单信息(租赁数量，租赁天数，单价等)
     * @param oneDayApartOrder
     */
    public void getCompleteOrderAndNeedPayOrder(List<Long> orderComplete,List<LeaseMachine> completeMachines,List<Long> completeIds,List<Long> needPayIds,List<LeaseOrderItem> needPayInfos,List<LeaseOrderItem> oneDayApartOrder){
        LocalDateTime now = LocalDateTime.now();
        Map<Long,Boolean> orderCompleteMap = new HashMap<>();
        for (LeaseOrderItem orderTimeInfoDto : oneDayApartOrder) {
            orderCompleteMap.putIfAbsent(orderTimeInfoDto.getOrderId(), true);
            // 计算订单结束时间（startTime + leaseTime天）
            //LocalDateTime endTime = orderTimeInfoDto.getCreateTime().plusDays(orderTimeInfoDto.getLeaseTime());

            //TODO 开发环境测试用1分钟当一天 差值改为差1分钟
            LocalDateTime endTime = orderTimeInfoDto.getCreateTime().plusMinutes(orderTimeInfoDto.getLeaseTime());

            // 比较 now 和 endTime 的差值是否小于30分
            if (Duration.between(now, endTime).toMinutes() <= 1) {
                completeMachines.add(LeaseMachine.builder()
                        .id(orderTimeInfoDto.getProductMachineId())
                        .canSaleNumbers(orderTimeInfoDto.getNumbers())
                        .saleOutNumbers(orderTimeInfoDto.getNumbers())
                        .saleState(false)
                        .build());
                completeIds.add(orderTimeInfoDto.getId());
                needPayIds.add(orderTimeInfoDto.getId());
                needPayInfos.add(orderTimeInfoDto);
                continue;
            }
            // 比较当前时间的时分秒与startTime的时分秒差值是否小于30分钟
            LocalTime nowTime = now.toLocalTime();
            LocalTime startTime = orderTimeInfoDto.getCreateTime().toLocalTime();
            if (Duration.between(startTime, nowTime).toMinutes() <= 1) {
                needPayIds.add(orderTimeInfoDto.getId());
                needPayInfos.add(orderTimeInfoDto);
            }
            //记录某个订单下所有子项目是否都完成
            orderCompleteMap.put(orderTimeInfoDto.getOrderId(), false);
        }
        orderCompleteMap.forEach(
                (orderId, complete) -> {
                    if (complete) {
                        orderComplete.add(orderId);
                    }
                }
        );
    }


    /**
     * 获取各orderItemId 所需支付的金额
     * @param orderIdToHashrateMap  订单id 与算力的映射
     * @param orderIdToPriceMap  订单id 与价格映射
     * @return
     */
    public Map<Long,BigDecimal> orderPaymentWaveAlgorithm(Map<Long, List<RealHashrateInfoDto>> orderIdToHashrateMap, Map<Long, LeaseOrderItem> orderIdToPriceMap){

        Map<Long,BigDecimal> orderItemIdToWaveMap = new HashMap<>();

        orderIdToHashrateMap.forEach((orderItemId, realPowerList) -> {

            LeaseOrderItem itemInfo = orderIdToPriceMap.get(orderItemId);


            // 计算每个数据点 理论算力的比值
            List<BigDecimal> ratios = realPowerList.stream()
                    .map(dto -> dto.getPower()
                            .divide(itemInfo.getTheoryPower(), 4, RoundingMode.HALF_UP))
                    .collect(Collectors.toList());

            // 补零到48个数据点
            while (ratios.size() < 48) {
                ratios.add(BigDecimal.ZERO);
            }

            // 计算总和并除以48
            BigDecimal finalValue = ratios.stream()
                    .reduce(BigDecimal.ZERO, BigDecimal::add)
                    .divide(BigDecimal.valueOf(48), 2, RoundingMode.HALF_UP);



            BigDecimal payAmount = itemInfo.getPrice()
                    .multiply(BigDecimal.valueOf(itemInfo.getNumbers()));
            if (finalValue.compareTo(BigDecimal.valueOf(0.95)) <= 0){
                payAmount = payAmount.multiply(finalValue);
            }
            orderItemIdToWaveMap.put(orderItemId, payAmount);
        });
        return orderItemIdToWaveMap;
    }

    /**
     * 获取订单项id 与实时算力映射
     **/
    public void getOrderItemIdToHashrateMap(Map<Long, List<RealHashrateInfoDto>> orderIdToHashrateMap,Map<String, PurchasedMachineListDto> miningAnditemIdMap,Map<String, List<RealHashrateInfoDto>> groupedData){
        for (Map.Entry<String, List<RealHashrateInfoDto>> entry : groupedData.entrySet()) {
            String key = entry.getKey();
            List<RealHashrateInfoDto> hashrateList = entry.getValue();

            // 从第一个映射中获取对应的订单信息
            PurchasedMachineListDto orderInfo = miningAnditemIdMap.get(key);
            if (orderInfo != null) {
                // 将订单ID与实时算力关联起来
                orderIdToHashrateMap.put(orderInfo.getOrderItemId(), hashrateList);
            }
        }

    }

    /**
     * 处理订单全部完成
     * @param orderIds 订单子项全部完成的订单id
     */
    public void handlerOrderAllComplete(List<Long> orderIds){
        //修改状态为已完成
        leaseOrderInfoMapper.update(LeaseOrderInfo.builder().status(8).build(), new LambdaQueryWrapper<LeaseOrderInfo>().in(LeaseOrderInfo::getId, orderIds));
        //老版本:发送支付消息
        sendMessageToMq(orderIds);
    }

    /**
     * 处理订单部分完成
     * @param itemIds 已完成订单项id
     * @param completeMachines 已完成机器id
     */
    public void handlerOrderPartComplete(List<Long> itemIds,List<LeaseMachine> completeMachines){
        //修改订单详情表中状态为 0 租约已过期
        leaseOrderItemMapper.update(LeaseOrderItem.builder().status(0).build(), new LambdaUpdateWrapper<LeaseOrderItem>()
                .in(LeaseOrderItem::getId, itemIds));
        //修改商品库存矿机表 矿机状态为 0 未售出
        leaseMachineMapper.updateBatchSaleNumbers(completeMachines);
        //挖矿订单信息 改为状态0 租约已过期
        leaseOrderMiningMapper.update(LeaseOrderMining.builder().status(false).build(), new LambdaUpdateWrapper<LeaseOrderMining>()
                .in(LeaseOrderMining::getOrderItemId, itemIds));
    }

    /**
     * 支付 定时任务
     */
    //@Scheduled(cron = "0 5 0 * * ? ")
    //@Scheduled(cron = "0 0/2 * * * ? ")
    @DSTransactional
    public void paymentTask(){
        // 获取当天 0 点的 时间
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startOfDay = now.toLocalDate().atStartOfDay();
        //1.查找在进行中的订单
        List<LeaseOrderInfo> needPayOrderList = leaseOrderInfoMapper.getNeedPayOrderList();
        if (needPayOrderList.isEmpty()){
            System.out.println("没有进行中的订单");
            return;
        }
        List<Long> infoIds = new ArrayList<>();
        Map<Long, LeaseOrderInfo> queueIdMap = new HashMap<>();
        for (LeaseOrderInfo leaseOrderInfo : needPayOrderList) {
            queueIdMap.put(leaseOrderInfo.getId(), leaseOrderInfo);
            infoIds.add(leaseOrderInfo.getId());
        }

        //2.根据订单号找到对应的订单详情(状态为1 租约生效中) ,并根据这些订单详情找到每个矿机的信息
        List<LeaseOrderItem> leaseOrderItems = leaseOrderItemMapper.selectList(new LambdaQueryWrapper<LeaseOrderItem>()
                .eq(LeaseOrderItem::getStatus,1)
                .in(LeaseOrderItem::getOrderId, infoIds));
        //订单进行过程中,卖方可能修改收款地址。所以每天支付前，需要修改旧收款地址为新地址
        leaseOrderItems = updateOrderItemSellerWalletAddress(leaseOrderItems);

        List<Long> machineIdList = leaseOrderItems.stream().map(LeaseOrderItem::getProductMachineId).collect(Collectors.toList());
        List<LeaseProductMachine> leaseProductMachines = leaseProductMachineMapper.selectBatchIds(machineIdList);

        Map<String, List<LeaseProductMachine>> coinAndMachineMap = leaseProductMachines.stream().collect(Collectors.groupingBy(LeaseProductMachine::getCoin));
        Map<Long, LeaseProductMachine> idAndMachineMap = leaseProductMachines.stream()
                .collect(Collectors.toMap(LeaseProductMachine::getId, Function.identity()));

        List<ProductMachineDto> productMachineList = new ArrayList<>();
        //2.1 查询到矿机集合后，按挖矿币种分组-----> 并查询每一组矿机的24小时的总算力
        coinAndMachineMap.forEach((coin, machines) -> {
            productMachineList.addAll(leaseProductMachineMapper.getRecentlyFiveMinutesData(leaseProductMachines, coin));
        });
        Map<String, ProductMachineDto> machineDtoMap = productMachineList.stream()
                .collect(Collectors.toMap(
                        dto -> dto.getUser() + "-" + dto.getMiner(),
                        dto -> dto
                ));
        //2.2 订单详情集合  按照 order_id 分组
        Map<Long, List<LeaseOrderItem>> userMapItem = leaseOrderItems.stream()
                .collect(Collectors.groupingBy(LeaseOrderItem::getOrderId));
                //.collect(Collectors.groupingBy(
                //        item->  item.getFromAddress() + "-" + item.getChain()+"-" + item.getSymbol()
                //));

        //3.筛选出租期到期的商品
        List<LeaseOrderItem> expireProductList = new ArrayList<>();
        List<LeasePayRecordMessageInfo> recordMessageInfoList = new ArrayList<>();
        Map<Long,Boolean> orderInfoIdAndIsComplete = new HashMap<>();
        List<LeaseOrderItem> saleIngList = new ArrayList<>();
        // 按照订单分组
        userMapItem.forEach((orderId, items) -> {
            LeaseOrderItem leaseOrderItem = items.get(0);
            List<LeaseOrderItem> expire = new ArrayList<>();
            //因为同一个订单的queueId相同，所以这里直接使用订单id
            LeaseOrderInfo orderInfo = queueIdMap.get(leaseOrderItem.getOrderId());
            //买方信息
            LeasePayRecordMessageInfo build = LeasePayRecordMessageInfo.builder()
                    .orderId(String.valueOf(orderId))
                    .orderNumber(orderInfo.getOrderNumber())
                    .queueId(orderInfo.getOrderNumber())
                    .fromAddress(leaseOrderItem.getFromAddress())
                    .toAddress(leaseOrderItem.getAddress())
                    .amount(BigDecimal.ZERO)
                    .realAmount(BigDecimal.ZERO)
                    .needAmount(BigDecimal.ZERO)
                    .blockAmount(BigDecimal.ZERO)
                    .fromChain(leaseOrderItem.getChain())
                    .fromSymbol(leaseOrderItem.getSymbol())
                    .shopId(leaseOrderItem.getShopId())
                    .userId(leaseOrderItem.getUserId())
                    .toChain(leaseOrderItem.getChain())
                    .toSymbol(leaseOrderItem.getSymbol())
                    .build();


            for (LeaseOrderItem item : items) {
                    orderInfoIdAndIsComplete.putIfAbsent(item.getOrderId(), true);
                    LocalDateTime expireTime = item.getCreateTime().plusDays(1).toLocalDate().atStartOfDay().plusDays(item.getLeaseTime());
                    //开发环境
                    LocalDateTime a =  item.getCreateTime().plusMinutes(item.getLeaseTime() * 2);
                    // 租期已过
                    if (startOfDay.isAfter(expireTime) /**开发环境*/|| now.isAfter(a)) {
                        item.setStatus(0);
                        expire.add(item);
                    }else{
                        orderInfoIdAndIsComplete.put(item.getOrderId(), false);
                        //根据算力波动实时计算需支付金额
                        String key = item.getUser() + "-" + item.getMiner();
                        LeaseProductMachine machine = idAndMachineMap.get(item.getProductMachineId());
                        ProductMachineDto productMachineDto = machineDtoMap.get(key);
                        build.setAmount(build.getAmount().add(item.getPrice()));
                        build.setBlockAmount(build.getBlockAmount().add(item.getPrice()));
                        if (productMachineDto != null){
                            //理论算力
                            BigDecimal theoryPower = machine.getTheoryPower().multiply(PowerUnit.getPower(machine.getUnit()))
                                    .divide(BigDecimal.valueOf(1000 * 1000),2,RoundingMode.HALF_UP);
                            //实际算力
                            BigDecimal realPower = productMachineDto.getComputingPower()
                                    .divide(BigDecimal.valueOf(24 * 60 * 60), 6, RoundingMode.HALF_UP);
                            //设置实际支付金额
                            BigDecimal divide = theoryPower.subtract(realPower).divide(theoryPower, 10, RoundingMode.HALF_UP);
                            //设置实际需要发送消息去支付的各订单金额和总金额
                            if (divide.compareTo(BigDecimal.valueOf(0.05)) > 0){
                                BigDecimal add = item.getPrice().multiply(BigDecimal.ONE.subtract(divide));
                                item.setSettlePayRealAmount(item.getSettlePayRealAmount().add(add));
                                build.setRealAmount(build.getRealAmount().add(add));
                                build.setNeedAmount(build.getNeedAmount().add(add));
                            }else{
                                BigDecimal add =  item.getPrice();
                                item.setSettlePayRealAmount(item.getSettlePayRealAmount().add(add));
                                build.setRealAmount(build.getRealAmount().add(add));
                                build.setNeedAmount(build.getNeedAmount().add(add));
                            }
                        }
                        item.setAlreadyPayAmount(item.getAlreadyPayAmount().add(item.getPrice()));

                        saleIngList.add(item);
                    }
                }


            ////TODO 下面这个是一个订单 一个买家对应多个卖家（多个收款地址）的情况
            ////封装卖方收款信息
            //Map<String,RabbitmqPayAutoInfoMessage> sellerPayInfoMessages = new HashMap<>();
            ////买方收款信息  相同订单最后整合成一个卖方信息
            //Map<String, List<LeaseOrderItem>> orderIdsMap = items.stream().collect(Collectors.groupingBy(LeaseOrderItem::getAddress));
            //orderIdsMap.forEach((toAddress, orderItemList) -> {
            //    LeaseOrderItem orderItem = orderItemList.get(0);
            //    RabbitmqPayAutoInfoMessage sellInfo = RabbitmqPayAutoInfoMessage.builder()
            //            .order_id(orderItem.getOrderId().toString())
            //            .to_address(toAddress)
            //            .amount(BigDecimal.ZERO)
            //            .blockAmount(BigDecimal.ZERO)
            //            .needAmount(BigDecimal.ZERO)
            //            .shopId(orderItem.getShopId())
            //            .userId(orderItem.getUserId())
            //            .build();
            //    for (LeaseOrderItem item : orderItemList) {
            //        orderInfoIdAndIsComplete.putIfAbsent(item.getOrderId(), true);
            //        LocalDateTime expireTime = item.getCreateTime().plusDays(1).toLocalDate().atStartOfDay().plusDays(item.getLeaseTime());
            //        //开发环境
            //        LocalDateTime a =  item.getCreateTime().plusMinutes(item.getLeaseTime() * 2);
            //        // 租期已过
            //        if (startOfDay.isAfter(expireTime) /**开发环境*/|| now.isAfter(a)) {
            //            item.setStatus(0);
            //            expire.add(item);
            //        }else{
            //            orderInfoIdAndIsComplete.put(item.getOrderId(), false);
            //            //根据算力波动实时计算需支付金额
            //            String key = item.getUser() + "-" + item.getMiner();
            //            LeaseProductMachine machine = idAndMachineMap.get(item.getProductMachineId());
            //            ProductMachineDto productMachineDto = machineDtoMap.get(key);
            //            sellInfo.setNeedAmount(sellInfo.getNeedAmount().add(item.getPrice()));
            //            sellInfo.setBlockAmount(sellInfo.getBlockAmount().add(item.getPrice()));
            //            if (productMachineDto != null){
            //                //理论算力
            //                BigDecimal theoryPower = machine.getTheoryPower().multiply(PowerUnit.getPower(machine.getUnit()))
            //                        .divide(BigDecimal.valueOf(1000 * 1000),2,RoundingMode.HALF_UP);
            //                //实际算力
            //                BigDecimal realPower = productMachineDto.getComputingPower()
            //                        .divide(BigDecimal.valueOf(24 * 60 * 60), 6, RoundingMode.HALF_UP);
            //                //设置实际支付金额
            //                BigDecimal divide = theoryPower.subtract(realPower).divide(theoryPower, 10, RoundingMode.HALF_UP);
            //                //设置实际需要发送消息去支付的各订单金额和总金额
            //                if (divide.compareTo(BigDecimal.valueOf(0.05)) > 0){
            //                    BigDecimal add = item.getPrice().multiply(BigDecimal.ONE.subtract(divide));
            //                    item.setSettlePayRealAmount(add);
            //                    sellInfo.setAmount(sellInfo.getAmount().add(add));
            //                    build.setTotal_amount(build.getTotal_amount().add(add));
            //                }else{
            //                    BigDecimal add =  item.getPrice();
            //                    item.setSettlePayRealAmount(add);
            //                    build.setTotal_amount(build.getTotal_amount().add(add));
            //                    sellInfo.setAmount(sellInfo.getAmount().add(add));
            //                }
            //            }
            //            item.setAlreadyPayAmount(item.getAlreadyPayAmount().add(item.getPrice()));
            //
            //            saleIngList.add(item);
            //        }
            //    }
            //    sellerPayInfoMessages.put(sellInfo.getTo_address(), sellInfo);
            //
            //});
            //build.setTransactions(sellerPayInfoMessages);
            if (build.getAmount().compareTo(BigDecimal.ZERO) > 0){
                recordMessageInfoList.add(build);
            }
            expireProductList.addAll(expire);
        });


        //4.保存支付消息到支付记录表中
        if (!recordMessageInfoList.isEmpty()){
            leasePayRecordMessageInfoService.saveBatch(recordMessageInfoList);
        }

        //5.租约到期相关信息修改
        if (!expireProductList.isEmpty()){
            List<Long> itemIds = new ArrayList<>();
            List<Long> machineIds = new ArrayList<>();
            for (LeaseOrderItem leaseOrderItem : expireProductList) {
                itemIds.add(leaseOrderItem.getId());
                machineIds.add(leaseOrderItem.getProductMachineId());
            }
            //5.1 修改订单详情表中状态为 0 租约已过期
            leaseOrderItemMapper.update(LeaseOrderItem.builder().status(0).build(), new LambdaUpdateWrapper<LeaseOrderItem>()
                    .in(LeaseOrderItem::getId, itemIds));
            //5.2 修改商品库存矿机表 矿机状态为 0 未售出
            leaseProductMachineMapper.update(LeaseProductMachine.builder().saleState(0).build(), new LambdaUpdateWrapper<LeaseProductMachine>()
                    .in(LeaseProductMachine::getId, machineIds));
            //5.3 修改用户已购矿机表状态为 1 套餐已过期
            List<LeaseUserOwnedProduct> list = leaseUserOwnedProductService.list(new LambdaQueryWrapper<LeaseUserOwnedProduct>()
                    .select(LeaseUserOwnedProduct::getId,LeaseUserOwnedProduct::getSettleIncome,LeaseUserOwnedProduct::getCurrentIncome).in(LeaseUserOwnedProduct::getProductMachineId, machineIds));
            List<LeaseUserOwnedProduct> collect = list.stream().map(item -> {
                item.setCurrentIncome(item.getSettleIncome());
                item.setSettleIncome(BigDecimal.ZERO);
                //item.setDel(true);
                item.setStatus(1);
                return item;
            }).collect(Collectors.toList());
            leaseUserOwnedProductService.updateBatchById(collect);

            //5.4 矿机对应商品 销售量修改
            //Map<Long, Long> productIdAndCountMap = expireProductList.stream().collect(Collectors.groupingBy(LeaseOrderItem::getProductId, Collectors.counting()));
            //Set<Long> longs = productIdAndCountMap.keySet();
            //List<LeaseProduct> leaseProducts = leaseProductService.list(new LambdaQueryWrapper<LeaseProduct>().in(LeaseProduct::getId, longs));
            //leaseProducts.forEach(leaseProduct -> {
            //    leaseProduct.setSaleNumber(leaseProduct.getSaleNumber() - productIdAndCountMap.get(leaseProduct.getId()).intValue());
            //});
            //leaseProductService.updateBatchById(leaseProducts);

            //5.5 找到详情表所有状态为0 租约已过期 ，并且订单info表订单状态为7 进行中的订单 并改为状态8 订单已完成 ；  并且发送支付消息
            List<Long> orderIds = orderInfoIdAndIsComplete.entrySet().stream()
                    .filter(entry -> Boolean.TRUE.equals(entry.getValue()))
                    .map(Map.Entry::getKey)
                    .collect(Collectors.toList());
            if(!orderIds.isEmpty()){
                //订单状态改为已完成
                leaseOrderInfoMapper.update(LeaseOrderInfo.builder().status(8).build(), new LambdaQueryWrapper<LeaseOrderInfo>().in(LeaseOrderInfo::getId, orderIds));
                //发送支付消息
                sendMessageToMq(orderIds);
            }

        }
        //6.正在售出中矿机已支付金额
        leaseOrderItemService.updateBatchById(saleIngList);

    }

    /**
     * 修改卖家钱包被修改后 的 order_item 的 中对应卖家的钱包地址
     * @param orderItemList 今天需要支付的订单
     */
    public List<LeaseOrderItem> updateOrderItemSellerWalletAddress( List<LeaseOrderItem> orderItemList){
        List<ShopChainAndCoinDto> collect = orderItemList.stream()
                .map(LeaseOrderItem -> ShopChainAndCoinDto.builder().shopId(LeaseOrderItem.getShopId())
                        .coin(LeaseOrderItem.getSymbol())
                        .chain(LeaseOrderItem.getChain()).build())
                .distinct()
                .collect(Collectors.toList());
        //查询到对应商铺对应的 chain  然后比较上面的链对应的地址是否改变
        List<ShopConfigDelDto> shopConfigList = leaseShopConfigMapper.selectShopConfigByShopIdAndSymbolAndChain(collect);
        List<LeaseOrderItem> updateOrderItemList = new ArrayList<>();
        // 遍历 orderItemList
        for (LeaseOrderItem orderItem : orderItemList) {
            for (ShopConfigDelDto shopConfig : shopConfigList) {
                // 检查 chain 和 shopId 是否相同
                if (orderItem.getShopId().equals(shopConfig.getShopId()) &&
                        orderItem.getChain().equals(shopConfig.getChain())) {
                    // 检查 address 是否不同
                    if (!orderItem.getAddress().equals(shopConfig.getPayAddress())) {
                        // 更新 orderItem 的 address
                        orderItem.setAddress(shopConfig.getPayAddress());
                        updateOrderItemList.add(orderItem);
                    }
                    break;
                }
            }
        }
        leaseOrderItemService.updateBatchById(updateOrderItemList);
        return orderItemList;

    }



    /**
     *订单完成后---发送支付消息到mq 一个买家对应一个卖家
     * @param orderIds
     */
    public void sendMessageToMq(List<Long> orderIds){
        List<LeasePayRecordMessageInfo> leasePayRecordMessages = leasePayRecordMessageInfoService.list(new LambdaQueryWrapper<LeasePayRecordMessageInfo>()
                .in(LeasePayRecordMessageInfo::getOrderId, orderIds));

        //Map<String, BigDecimal> feeMap = getFee(orderIds);
        Map<String, List<LeasePayRecordMessageInfo>> collect = leasePayRecordMessages.stream()
                .collect(Collectors.groupingBy(LeasePayRecordMessageInfo::getOrderId));
        List<LeasePayRecordMessage> reocrdList = new ArrayList<>();
        //遍历按订单id分组后的map
        collect.forEach((orderId, payRecordMessagesList) -> {
            LeasePayRecordMessageInfo initForm = payRecordMessagesList.get(0);
            //long timestamp = System.currentTimeMillis()/1000;
            //RabbitmqPayAutoMessage build = RabbitmqPayAutoMessage.builder()
            //        .queue_id(initForm.getQueueId())
            //        .chain(initForm.getFromChain())
            //        .symbol(initForm.getFromSymbol())
            //        .from_address(initForm.getFromAddress())
            //        .to_address(initForm.getToAddress())
            //        .fee(feeMap.get(orderId))
            //        .amount(BigDecimal.ZERO)
            //        .blockAmount(BigDecimal.ZERO)
            //        .needAmount(BigDecimal.ZERO)
            //        .timestamp(timestamp)
            //        .sign(HashUtils.sha256(timestamp))
            //        .build();

            LeasePayRecordMessage build = LeasePayRecordMessage.builder()
                    .queueId(initForm.getQueueId())
                    .fromAddress(initForm.getFromAddress())
                    .toAddress(initForm.getToAddress())
                    .orderNumber(initForm.getOrderNumber())
                    .orderId(orderId)
                    .shopId(initForm.getShopId())
                    .userId(initForm.getUserId())
                    .blockAmount(BigDecimal.ZERO)
                    .amount(BigDecimal.ZERO)
                    .realAmount(BigDecimal.ZERO)
                    .needAmount(BigDecimal.ZERO)
                    .fromSymbol(initForm.getFromSymbol())
                    .fromChain(initForm.getFromChain())
                    .toSymbol(initForm.getToSymbol())
                    .toChain(initForm.getToChain())
                    .build();
            for (LeasePayRecordMessageInfo leasePayRecordMessage : payRecordMessagesList) {
                build.setAmount(build.getAmount().add(leasePayRecordMessage.getAmount()));
                build.setBlockAmount(build.getBlockAmount().add(leasePayRecordMessage.getBlockAmount()));
                //现在可以删除NeedAmount这个字段了.新版本不存在需支付真实金额和实际支付真实金额不同的情况
                build.setNeedAmount(build.getNeedAmount().add(leasePayRecordMessage.getNeedAmount()));
                build.setRealAmount(build.getRealAmount().add(leasePayRecordMessage.getRealAmount()));
            }
            reocrdList.add(build);


            //旧版本
            //订单全部完成后不再需要发送支付信息，直接从买家钱包转账到卖家钱包
            //try {
            //    rabbitTemplate.convertAndSend(PAY_AUTO_QUEUE, build);
            //}catch (Exception e){
            //    //设置状态为消息发送失败
            //    build1.setStatus(4);
            //    System.out.println("消息发送失败"+e.getMessage());
            //}finally {
            //    reocrdList.add(build1);
            //}

            //新版本：买家钱包 冻结余额和余额减少  卖家钱包余额增加


        });
        leasePayRecordMessageService.saveBatch(reocrdList);
        int buyerUpdate = leaseUserWalletDataMapper.updateBalanceAndBlockBalance(reocrdList);
        int sellerUpdate = leaseShopConfigMapper.updateBalance(reocrdList);

        if (buyerUpdate > 0 && sellerUpdate > 0){
            for (LeasePayRecordMessage item : reocrdList) {
                String buyerInfo = "订单号：" + item.getOrderNumber() +
                        "理论支付金额：" + item.getAmount() +
                        "实际支付金额：" + item.getRealAmount()+
                        "收款地址：" + item.getToAddress()+
                        "支付链：" + item.getFromChain()+
                        "支付币种" + item.getFromSymbol();

                String sellerInfo = "订单号：" + item.getOrderNumber() +
                        "收款金额：" + item.getRealAmount()+
                        "支付地址：" + item.getFromAddress()+
                        "支付链：" + item.getFromChain()+
                        "支付币种" + item.getFromSymbol() ;
                ledgerLogService.logOperation(item.getFromAddress(), "支付(付款)", buyerInfo);
                ledgerLogService.logOperation(item.getToAddress(), "支付(收款)",sellerInfo);
            }
        }


    }

    /**
     * 获取手续费
     * @param orderIds
     * @return
     */
   private Map<String, BigDecimal> getFee(List< Long> orderIds){
        List<LeaseOrderInfo> leaseOrderInfos = leaseOrderInfoMapper.selectList(new LambdaQueryWrapper<LeaseOrderInfo>()
                .select(LeaseOrderInfo::getFee,LeaseOrderInfo::getOrderNumber)
                .in(LeaseOrderInfo::getId, orderIds));
         return leaseOrderInfos.stream()
                .collect(Collectors.toMap(LeaseOrderInfo::getOrderNumber, LeaseOrderInfo::getFee));
    }




    /**
     * 一些校验失败的支付消息需要重新发送(新版本不再发送支付消息)
     */
    //@Scheduled(cron = "0 0 0/1 * * ? ")
    //@Transactional
    public void checkPushFailPayMessage(){
        //查找出状态为3 校验失败 4 发送消息失败 的消息需要重发
        List<LeasePayRecordMessage> list = leasePayRecordMessageService.list(new LambdaQueryWrapper<LeasePayRecordMessage>()
                .eq(LeasePayRecordMessage::getStatus, 3)
                .ge(LeasePayRecordMessage::getCreateTime, LocalDateTime.now().minusHours(3))
                .or().eq(LeasePayRecordMessage::getStatus, 4));
        if (list.isEmpty()){
            return;
        }
        List<Long> orderIds = list.stream().map(leasePayRecordMessage->Long.valueOf(leasePayRecordMessage.getOrderId())).collect(Collectors.toList());
        Map<String, BigDecimal> feeMap = getFee(orderIds);
        List<LeasePayRecordMessage> againSendList = new ArrayList<>();
        for (LeasePayRecordMessage leasePayRecordMessage : list) {
            Long timestamp = System.currentTimeMillis()/1000;
            RabbitmqPayAutoMessage build = RabbitmqPayAutoMessage.builder()
                    .queue_id(leasePayRecordMessage.getQueueId())
                    .order_id(leasePayRecordMessage.getOrderId())
                    .chain(leasePayRecordMessage.getFromChain())
                    .symbol(leasePayRecordMessage.getFromSymbol())
                    .from_address(leasePayRecordMessage.getFromAddress())
                    .to_address(leasePayRecordMessage.getToAddress())
                    .fee(feeMap.get(leasePayRecordMessage.getOrderId()))
                    .amount(leasePayRecordMessage.getAmount())
                    .timestamp(timestamp)
                    .sign(HashUtils.sha256(timestamp))
                    .build();
            try {
                rabbitTemplate.convertAndSend(PAY_AUTO_QUEUE, build);
                leasePayRecordMessage.setStatus(2);
                againSendList.add(leasePayRecordMessage);
            }catch (Exception e){
                System.out.println("消息发送失败"+e.getMessage());
            }
        }
        leasePayRecordMessageService.updateBatchById(againSendList);

    }


    /**
     * 检测 临时表数据是否需要持久化到矿机表中
     */
    @Scheduled(cron = "0 0 0/1 * * ? ")
    @Transactional
    public void checkMachineTempTable(){
        List<LeaseMachineTempConfig> leaseMachineTempConfigs = leaseMachineTempConfigMapper.selectList(new LambdaQueryWrapper<LeaseMachineTempConfig>()
                .le(LeaseMachineTempConfig::getEffectTime, LocalDateTime.now()));
        if (!leaseMachineTempConfigs.isEmpty()){
            leaseMachineTempConfigMapper.insertBatchByTempList(leaseMachineTempConfigs);
            leaseMachineTempConfigMapper.deleteBatchIds(leaseMachineTempConfigs);
        }
    }



    ///**
    // * 订单完成后---发送支付消息到mq 一个买家对应多个卖家
    // * @param orderIds
    // */
    //public void sendMessageToMq(List<Long> orderIds){
    //    List<LeasePayRecordMessage> leasePayRecordMessages = leasePayRecordMessageMapper.selectList(new LambdaQueryWrapper<LeasePayRecordMessage>()
    //            .in(LeasePayRecordMessage::getOrderId, orderIds));
    //    Map<String, Map<String, List<LeasePayRecordMessage>>> collect = leasePayRecordMessages.stream()
    //            .collect(Collectors.groupingBy(LeasePayRecordMessage::getOrderId, Collectors.groupingBy(LeasePayRecordMessage::getToAddress)));
    //    //遍历按订单id分组后的map
    //    collect.forEach((orderId, payRecordMessagesMap) -> {
    //
    //        long timestamp = System.currentTimeMillis()/1000;
    //        List<LeasePayRecordMessage> orDefault = payRecordMessagesMap.getOrDefault(payRecordMessagesMap.keySet().iterator().next(), new ArrayList<>());
    //        LeasePayRecordMessage initForm = orDefault.get(0);
    //        RabbitmqPayAutoMessage build = RabbitmqPayAutoMessage.builder()
    //                .queue_id(initForm.getQueueId())
    //                .from_address(initForm.getFromAddress())
    //                .chain(initForm.getFromChain())
    //                .symbol(initForm.getFromSymbol())
    //                .total_amount(BigDecimal.ZERO)
    //                .timestamp(timestamp)
    //                .sign(HashUtils.sha256(timestamp))
    //                .build();
    //
    //
    //        Map<String, RabbitmqPayAutoInfoMessage> transactions = new HashMap<>();
    //        //遍历按toAddress 分组后的map
    //        payRecordMessagesMap.forEach((toAddress,payRecordMessageList) -> {
    //            LeasePayRecordMessage init = payRecordMessageList.get(0);
    //            RabbitmqPayAutoInfoMessage sellInfo = RabbitmqPayAutoInfoMessage.builder()
    //                    .to_address(init.getToAddress())
    //                    .amount(BigDecimal.ZERO)
    //                    .blockAmount(BigDecimal.ZERO)
    //                    .needAmount(BigDecimal.ZERO)
    //                    .shopId(init.getShopId())
    //                    .userId(init.getUserId())
    //                    .build();
    //            for (LeasePayRecordMessage leasePayRecordMessage : payRecordMessageList) {
    //                sellInfo.setAmount(sellInfo.getAmount().add(leasePayRecordMessage.getRealAmount()));
    //                sellInfo.setBlockAmount(sellInfo.getBlockAmount().add(leasePayRecordMessage.getBlockAmount()));
    //                sellInfo.setNeedAmount(sellInfo.getNeedAmount().add(leasePayRecordMessage.getNeedAmount()));
    //            }
    //            build.setTotal_amount(build.getTotal_amount().add(sellInfo.getAmount()));
    //            transactions.put(toAddress,sellInfo);
    //        });
    //        build.setTransactions(transactions);
    //        rabbitTemplate.convertAndSend(PAY_AUTO_QUEUE, build);
    //    });
    //}

    //@Scheduled(cron = "0 0/1 * * * ? ")
    //@Transactional
    //public void test(){
    //    System.out.println("发送消息到队列------------------------------------------");
    //    long l = System.currentTimeMillis()/1000;
    //    //支付
    //    rabbitTemplate.convertAndSend(PAY_AUTO_QUEUE, RabbitmqPayAutoMessage.builder()
    //                    .queue_id("1")
    //                    .from_address("1")
    //                    .to_address("1")
    //                    .amount(BigDecimal.valueOf(1))
    //                    .chain("1")
    //                    .symbol("1")
    //                    .order_id("1")
    //                    .timestamp(l)
    //                    .sign(HashUtils.sha256(l))
    //                    .build()
    //           );
    //    //充值
    //    rabbitTemplate.convertAndSend(PAY_RECHARGE_QUEUE, RabbitmqPayRechargeMessage.builder()
    //            .address("2")
    //            .chain("2")
    //            .symbol("2")
    //            .timestamp(l)
    //            .sign(HashUtils.sha256(l))
    //            .build()
    //    );
    //    //提现
    //    rabbitTemplate.convertAndSend(PAY_WITHDRAW_QUEUE, RabbitmqPayWithdrawMessage.builder()
    //            .queue_id("1")
    //            .from_address("1")
    //            .to_address("1")
    //            .amount(BigDecimal.valueOf(1))
    //            .chain("1")
    //            .symbol("1")
    //            .timestamp(l)
    //            .sign(HashUtils.sha256(l))
    //            .build()
    //    );
    //
    //
    //
    //}

    /**
     * 每分钟检查一次超时的订单，是否修改了状态为 6 订单已超时
     */
    //@Scheduled(cron = "0 0/1 * * * ? ")
    //@Transactional
    //public void checkIsExpireOrder(){
    //    LocalDateTime now = LocalDateTime.now();
    //    LocalDateTime createTime = now.minusMinutes(15);
    //    List<LeaseOrderInfo> leaseOrderInfos = leaseOrderInfoMapper.selectList(new LambdaQueryWrapper<LeaseOrderInfo>()
    //            .eq(LeaseOrderInfo::getStatus, PAYMENT_IN_PROGRESS.getCode())
    //            .lt(LeaseOrderInfo::getCreateTime, createTime));
    //
    //    //普通订单状态跟着支付订单走，先修改支付订单状态(查找15m前的支付中订单)
    //    List<LeasePaymentRecord> leasePaymentRecords = leasePaymentRecordMapper.selectList(new LambdaQueryWrapper<LeasePaymentRecord>()
    //            .eq(LeasePaymentRecord::getStatus, PAYMENT_IN_PROGRESS.getCode())
    //            .lt(LeasePaymentRecord::getCreateTime, createTime));
    //    if (leasePaymentRecords.isEmpty()){
    //        return;
    //    }
    //    //1.根据 订单实际时间已超时 但是订单状态为 6支付中 的情况----->修改这些订单的状态为 5订单已超时
    //    int updatePayStatus = leasePaymentRecordMapper.updateBatchStatusForOderIdAndShopId(leasePaymentRecords);
    //
    //    //2.修改机器中售出状态 从2售出中改为 0未售出
    //    List<Long> orderStatusIsPayInData = leaseOrderItemMapper.getMachineByOrderStatusIsPayInData(leasePaymentRecords);
    //    if (orderStatusIsPayInData.isEmpty()){
    //        return;
    //    }
    //    int updateMachineStatus = leaseProductMachineMapper.update(LeaseProductMachine.builder().saleState(0).build(),
    //            new LambdaQueryWrapper<LeaseProductMachine>()
    //                    .eq(LeaseProductMachine::getSaleState, 2).in(LeaseProductMachine::getId, orderStatusIsPayInData));
    //
    //    //3.修改普通订单状态为 5订单已超时
    //    List<Long> orderIds = leaseOrderInfos.stream().map(LeaseOrderInfo::getId).collect(Collectors.toList());
    //    if (orderIds.isEmpty()){
    //        return;
    //    }
    //    int updateOrderStatus = leaseOrderInfoMapper.update(LeaseOrderInfo.builder().status(5).build(),
    //            new LambdaQueryWrapper<LeaseOrderInfo>().eq(LeaseOrderInfo::getStatus, 6).in(LeaseOrderInfo::getId, orderIds));
    //
    //    System.out.println("修改了" + updatePayStatus + "个支付订单状态为5订单已超时。"
    //            + updateMachineStatus + "个机器状态为未售出。"+ updateOrderStatus + "个普通订单状态为5订单已超时");
    //
    //}


    /**
     *         //获取 15 钟内支付订单  再次去校验是否支付全部成功  全部成功则修改订单状态为 1全部支付成功
     */
    //@Scheduled(cron = "0/30 * * * * ? ")
    //@Transactional
    //public void paymentRecord(){
    //    List<LeasePaymentRecord> leasePaymentRecordList = leasePaymentRecordMapper.selectList(new LambdaQueryWrapper<LeasePaymentRecord>()
    //            .eq(LeasePaymentRecord::getDel, false)
    //            .ge(LeasePaymentRecord::getCreateTime, LocalDateTime.now().minusMinutes(15)));
    //
    //    if (!leasePaymentRecordList.isEmpty()){
    //        leasePaymentRecordService.paymentCallbackTask(leasePaymentRecordList);
    //    }
    //}




}
