package com.jxy.order.service.impl;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.jxy.common.core.text.Convert;
import com.jxy.common.core.utils.DateUtils;
import com.jxy.common.core.utils.StringUtils;
import com.jxy.common.core.web.Result.AjaxResult;
import com.jxy.common.redis.service.RedisService;
import com.jxy.common.security.utils.SecurityUtils;
import com.jxy.order.dto.*;
import com.jxy.order.entity.*;
import com.jxy.order.enums.Chain;
import com.jxy.order.enums.Coin;
import com.jxy.order.enums.OrderStatus;
import com.jxy.order.mapper.OrderMapper;
import com.jxy.order.service.OrderService;
import com.jxy.order.vo.*;
import com.jxy.system.api.RemoteMailService;
import com.jxy.system.api.RemoteUserService;
import com.jxy.system.api.entity.EmailEntity;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.net.URI;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Description TODO
 * @Date 2023/5/4 14:11
 * @Author 杜懿
 */
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private RemoteUserService remoteUserService;

    @Autowired
    private RemoteMailService remoteMailService;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedisService redisService;


    //@Override
    //public AjaxResult getUserAddress() {
    //
    //    //根据用户id查找用户地址数据  如果没找到则为用户绑定一个地址
    //    UserAddress userAddr = orderMapper.getAddressByUserId(SecurityUtils.getUserId());
    //    if (StringUtils.isNull(userAddr)){
    //        //没有找到说明数据库中还未生成用户地址,需要通知后台生成地址 ps:也可能是未获取到数据
    //        redisTemplate.convertAndSend("UserAddress",SecurityUtils.getUserId());
    //        return AjaxResult.error("后台繁忙,请重新刷新获取用户地址");
    //    }
    //
    //    //构造返回前端的数据
    //    //UserAddressDto dto = new  UserAddressDto();
    //    //BeanUtils.copyProperties(userAddr,dto);
    //
    //    return AjaxResult.success(userAddr);
    //}

    @Override
    public AjaxResult createAddCreditOrder(AddCreditOrderVo vo) {

        System.out.println(vo);
        if(!Coin.judge(vo.getCoin())){
            return AjaxResult.error("coin传参异常!请不要擅自修改参数");
        }

        if(!Chain.judge(vo.getChain())){
            return AjaxResult.error("chain传参异常!请不要擅自修改参数");
        }

        //Thread.;
        //入库地址数据应该使用从用户地址数据库中查到的地址
        //根据用户id查找用户地址数据  根据用户id和chain去查
        UserAddress userAddr = orderMapper.getAddressByUserId(SecurityUtils.getUserId());
        System.out.println(userAddr);
        if (StringUtils.isNull(userAddr)){
            userAddr = UserBoundAddress(SecurityUtils.getUserId(),vo.getChain(),userAddr);
            System.out.println("绑定后地址为:"+userAddr);
            if (StringUtils.isNull(userAddr)){
                return AjaxResult.error("服务器忙,请稍后再试");
            }else {
                if("BSC".equals(vo.getChain().toUpperCase()) && StringUtils.isBlank(userAddr.getAddressBSC())){
                    return AjaxResult.error("服务器忙,请稍后再试");
                }else if("TRX".equals(vo.getChain().toUpperCase()) && StringUtils.isBlank(userAddr.getAddressTRX())){
                    return AjaxResult.error("服务器忙,请稍后再试");
                }else {
                    if(StringUtils.isBlank(userAddr.getAddress())){
                        return AjaxResult.error("服务器忙,请稍后再试");
                    }
                }
            }
        }
        if("BSC".equals(vo.getChain().toUpperCase())){
            if(StringUtils.isBlank(userAddr.getAddressBSC())){
                //用户没有绑定BSC地址 从BSC地址数据库中拿一个地址  修改用户地址表中对应的字段
                userAddr = UserBoundAddress(SecurityUtils.getUserId(),vo.getChain(),userAddr);
                if(StringUtils.isNull(userAddr)){
                    return AjaxResult.error(701,"系统异常,请稍后再试");
                }
                System.out.println("重新获取bsc地址:"+userAddr);
            }
            vo.setAddress(userAddr.getAddressBSC());
        }else if("TRX".equals(vo.getChain().toUpperCase())){
            if(StringUtils.isBlank(userAddr.getAddressTRX())){
                //用户没有绑定BSC地址 从BSC地址数据库中拿一个地址  修改用户地址表中对应的字段
                userAddr = UserBoundAddress(SecurityUtils.getUserId(),vo.getChain(),userAddr);
                if(StringUtils.isNull(userAddr)){
                    return AjaxResult.error(701,"系统异常,请稍后再试");
                }
            }
            vo.setAddress(userAddr.getAddressTRX());
        }else {
            if(StringUtils.isBlank(userAddr.getAddress())){
                //用户没有绑定BSC地址 从BSC地址数据库中拿一个地址  修改用户地址表中对应的字段
                userAddr = UserBoundAddress(SecurityUtils.getUserId(),vo.getChain(),userAddr);
                if(StringUtils.isNull(userAddr)){
                    return AjaxResult.error(701,"系统异常,请稍后再试");
                }
            }
            vo.setAddress(userAddr.getAddress());
        }
        //vo.setAddress(userAddr.getAddress());

        //雪花算法生成订单id 待做
        //String orderId= SnowFlake.nextId()+"";

        //构造入库数据

        AddCreditOrder data = new AddCreditOrder();
        BeanUtils.copyProperties(vo,data);

        data.setUserId(SecurityUtils.getUserId());
        data.setStatus(2);
        Date date = new Date();
        //Calendar ca = Calendar.getInstance();
        //ca.setTime(date);
        //
        //ca.add(Calendar.DATE, -2);
        data.setCreateTime(date);
        System.out.println("入库数据"+data);

        //充值订单数据入库
        if(orderMapper.insertAddCreditOrder(data)){
            System.out.println("入库之后："+data);
            //todo 修改为rocketMQ
            redisTemplate.convertAndSend("UserOrderCreate",data);
            //开启延时订单执行任务
            ScheduledExecutorService ses1 = Executors.newSingleThreadScheduledExecutor();
            ses1.schedule(()->{
                //查看订单状态 如果不是pending(status == 2)说明已经被处理了 直接停止后续的任务
                System.out.println("延时处理订单,时间："+new Date()+"，订单："+data.getId());
                AddCreditOrder dbOrder = orderMapper.getAddCreditOrderById(data.getId());
                if(dbOrder.getStatus() == 2){
                    //通过链上查询api 查询链上交易结果
                    AddCreditOrderVo orderVo = new AddCreditOrderVo();
                    BeanUtils.copyProperties(data,orderVo);
                    OnChainQueryResultDto resultDto = getOnChainTxMsgByAddress(orderVo);
                    if(resultDto.getResult()){
                        int num = resultDto.getList().size();
                        if(num > 0){
                            //list起码有一条数据才行
                            OnChainMsgByAddressDto firstDto = resultDto.getList().get(0);
                            HandleAddCreditOrderVo hcVo = new HandleAddCreditOrderVo();
                            hcVo.setTransferId(data.getId());
                            hcVo.setAmount(firstDto.getAmount());
                            hcVo.setAddress(firstDto.getAddress());
                            hcVo.setTxid(firstDto.getTxid());
                            //判断txid是否已被使用 已被使用直接拒绝订单
                            if(orderMapper.checkTxidIfExist(hcVo.getTxid()) < 1){
                                hcVo.setOper(1);
                            }else {
                                hcVo.setOper(0);
                            }
                            hcVo.setMessage(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,firstDto.getTime())+"从地址"+firstDto.getFrom()+"转入"+firstDto.getAmount()+data.getCoin());
                            System.out.println("请求操作数据库的数据："+hcVo);
                            handleAddCreditOrder(hcVo,SecurityUtils.getUserId());

                            // 第一步  修改订单表：填入txid、amount、修改status为0/1
                            // 第二步  修改用户账户表：填入修改对应币种的金额
                            // 第三步  将这笔交易记录到余额表中
                        }
                        if(num > 1){
                            //充值之后有多笔转账 后续操作:先把第一条（时间排序）放入当前订单  然后后面的几条分别先生成一个已完成的订单 然后再更改用户账户和记录转账信息
                            for(int i=1 ; i<num;i++){
                                OnChainMsgByAddressDto onChainMsgByAddressDto = resultDto.getList().get(i);
                                //判断txid是否已被使用 未被使用才创建新订单
                                if(orderMapper.checkTxidIfExist(onChainMsgByAddressDto.getTxid()) < 1){
                                    //创建新订单

                                    AddCreditOrder dto = new AddCreditOrder();

                                    dto.setUserId(SecurityUtils.getUserId());
                                    dto.setCoin(vo.getCoin());
                                    dto.setAddress(onChainMsgByAddressDto.getAddress());
                                    dto.setChain(vo.getChain());
                                    dto.setCreateTime(onChainMsgByAddressDto.getTime());
                                    dto.setStatus(2);

                                    if(orderMapper.insertAddCreditOrder(dto)){
                                        //插入成功 处理新订单
                                        HandleAddCreditOrderVo hcVo = new HandleAddCreditOrderVo();
                                        hcVo.setTransferId(data.getId());
                                        hcVo.setAmount(onChainMsgByAddressDto.getAmount());
                                        hcVo.setOper(1);
                                        hcVo.setAddress(onChainMsgByAddressDto.getAddress());
                                        hcVo.setTxid(onChainMsgByAddressDto.getTxid());
                                        hcVo.setMessage(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,onChainMsgByAddressDto.getTime())+"从地址"+onChainMsgByAddressDto.getFrom()+"转入"+onChainMsgByAddressDto.getAmount()+data.getCoin());
                                        System.out.println("请求操作数据库的数据："+hcVo);
                                        handleAddCreditOrder(hcVo,SecurityUtils.getUserId());
                                    }
                                }
                            }
                            //对第一条进行处理
                        }
                    }else {
                        //失败了 这里需要按失败去处理订单
                        HandleAddCreditOrderVo hcVo = new HandleAddCreditOrderVo();

                        hcVo.setTransferId(data.getId());
                        hcVo.setOper(0);
                        hcVo.setAddress(data.getAddress());
                        hcVo.setMessage("未查询到链上数据");
                        System.out.println("请求操作数据库的数据："+hcVo);
                        handleAddCreditOrder(hcVo,SecurityUtils.getUserId());
                    }

                }

            },30,TimeUnit.MINUTES);
            //返回用户地址信息
            UserAddressDto uaDto = new UserAddressDto();
            uaDto.setAddress(data.getAddress());
            uaDto.setOrderId(data.getId());
            return AjaxResult.success("充值订单已提交，处理中...",uaDto);
        }else {
            return AjaxResult.success("订单提交失败，请稍后再试");
        }
    }

    @Override
    public AjaxResult handleOrder(OrderChangeByTxidVo vo) {
        long t1 = System.currentTimeMillis();
        AjaxResult result = AjaxResult.success();
        if(StringUtils.isNotNull(vo.getOrderId())){
            //根据订单id以及用户userId立即处理订单
            AddCreditOrder data = orderMapper.getAddCreditOrderByOrderIdAndUserId(vo.getOrderId(),SecurityUtils.getUserId());
            if(StringUtils.isNull(data)){
                return AjaxResult.error("根据当前用户id和订单id未查到订单信息,请勿擅自修改订单id");
            }

            //判断当前用户id和订单中的user_id是否一致
            if(data.getStatus() == 2){
                //通过链上查询api 查询链上交易结果
                AddCreditOrderVo orderVo = new AddCreditOrderVo();
                BeanUtils.copyProperties(data,orderVo);
                OnChainQueryResultDto resultDto = getOnChainTxMsgByAddress(orderVo);
                if(resultDto.getResult()){
                    int num = resultDto.getList().size();
                    if(num < 1){
                        //未查询到订单详情 5分钟后再次处理
                        //ScheduledExecutorService ses1 = Executors.newSingleThreadScheduledExecutor();
                        //ses1.schedule(()->{
                        //    resultDto = getOnChainTxMsgByAddress(orderVo);},5,TimeUnit.MINUTES);
                        HandleAddCreditOrderVo hcVo = new HandleAddCreditOrderVo();
                        //设置为失败订单
                        hcVo.setOper(0);
                        hcVo.setTransferId(data.getId());
                        hcVo.setAddress(data.getAddress());
                        hcVo.setMessage("未在链上查询到相关交易信息");
                        result = handleAddCreditOrder(hcVo, SecurityUtils.getUserId());
                        return AjaxResult.error("未在链上查询到相关交易信息");
                    }

                    if(num > 0){
                        //list起码有一条数据才行
                        OnChainMsgByAddressDto firstDto = resultDto.getList().get(0);
                        HandleAddCreditOrderVo hcVo = new HandleAddCreditOrderVo();
                        hcVo.setTransferId(data.getId());
                        hcVo.setAmount(firstDto.getAmount());
                        hcVo.setAddress(firstDto.getAddress());
                        hcVo.setTxid(firstDto.getTxid());
                        //判断txid是否已被使用 已被使用直接拒绝订单
                        if(orderMapper.checkTxidIfExist(hcVo.getTxid()) < 1){
                            //txid未被使用
                            hcVo.setOper(1);
                        }else {
                            //txid已被使用
                            hcVo.setOper(0);
                        }
                        hcVo.setMessage(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,firstDto.getTime())+"从地址"+firstDto.getFrom()+"转入"+firstDto.getAmount()+data.getCoin());
                        System.out.println("请求操作数据库的数据："+hcVo);
                        long t2 = System.currentTimeMillis();
                        result = handleAddCreditOrder(hcVo, SecurityUtils.getUserId());
                        System.out.println(result);
                        long t3 = System.currentTimeMillis();
                        System.out.println("数据库处理耗时"+(t3-t2));
                        System.out.println("处理结束,耗时"+(t3-t1));
                        ScheduledExecutorService ses1 = Executors.newSingleThreadScheduledExecutor();
                        ses1.schedule(()->{if(num > 1){
                            //充值之后有多笔转账 后续操作:先把第一条（时间排序）放入当前订单  然后后面的几条分别先生成一个已完成的订单 然后再更改用户账户和记录转账信息
                            for(int i=1 ; i<num;i++){
                                OnChainMsgByAddressDto onChainMsgByAddressDto = resultDto.getList().get(i);
                                //先判断txid是否已被使用
                                if(orderMapper.checkTxidIfExist(onChainMsgByAddressDto.getTxid()) < 1){
                                    AddCreditOrder dto = new AddCreditOrder();

                                    dto.setUserId(SecurityUtils.getUserId());
                                    dto.setCoin(data.getCoin());
                                    dto.setAddress(onChainMsgByAddressDto.getAddress());
                                    dto.setChain(data.getChain());
                                    dto.setStatus(2);

                                    if(orderMapper.insertAddCreditOrder(dto)){
                                        //插入成功 处理新订单
                                        HandleAddCreditOrderVo hcVo2 = new HandleAddCreditOrderVo();
                                        hcVo2.setTransferId(dto.getId());
                                        hcVo2.setAmount(onChainMsgByAddressDto.getAmount());
                                        hcVo2.setOper(1);
                                        hcVo2.setAddress(onChainMsgByAddressDto.getAddress());
                                        hcVo2.setTxid(onChainMsgByAddressDto.getTxid());
                                        hcVo2.setMessage(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,onChainMsgByAddressDto.getTime())+"从地址"+onChainMsgByAddressDto.getFrom()+"转入"+onChainMsgByAddressDto.getAmount()+data.getCoin());
                                        System.out.println("请求操作数据库的数据："+hcVo2);
                                        AjaxResult result1 = handleAddCreditOrder(hcVo2, SecurityUtils.getUserId());
                                        System.out.println(result1);
                                    }
                                }
                            }
                            //对第一条进行处理
                        }},3,TimeUnit.SECONDS);

                        return result;
                    }

                }else {
                    //
                    return AjaxResult.error("未在链上查询到相关交易信息");
                }
            }else {
                return AjaxResult.error(801,"此订单已被处理过");
            }
        }
        else {
            return AjaxResult.error("订单id丢失");
        }
        return result;
    }

    @Override
    public AjaxResult cancelOrder(OrderIdVo vo) {
        AddCreditOrder order = orderMapper.getAddCreditOrderByOrderIdAndUserId(vo.getOrderId(), SecurityUtils.getUserId());
        if(StringUtils.isNull(order)){
            return AjaxResult.error("取消订单传参异常");
        }
        HandleAddCreditOrderVo hdVo = new HandleAddCreditOrderVo();
        hdVo.setTransferId(order.getId());
        hdVo.setOper(0);
        if(orderMapper.updateOrderStatusById(hdVo) > 0){
            return AjaxResult.success("订单已关闭");
        }else {
            return AjaxResult.error("后台繁忙,请稍后再试");
        }
    }

    @Override
    public AjaxResult handleOrderByTxid(OrderChangeByTxidVo vo) {

        Long userId = SecurityUtils.getUserId();
        if (redisService.hasKey("user:"+userId+":usedTxid")){
           return AjaxResult.error("当前用户倒计时未结束,该服务不可用，请倒计时结束后再试");
        }

        //redis 记录用户 user:user_id:userTxid
        redisService.setCacheObject("user:"+userId+":usedTxid", userId, 4L, TimeUnit.HOURS
        );
        //判断txid是否已使用
        if(StringUtils.isNotNull(vo.getTxid())){
            //查询txid是否已经在网站内使用过
            if(orderMapper.checkTxidIfExist(vo.getTxid()) > 0){
                return AjaxResult.error(802,"该笔交易已完成或不属于本网站转账！请勿恶意提交交易hash");
            }
        }

        //通过orderId获取订单详细信息
        //AddCreditOrder data = orderMapper.getAddCreditOrderById(vo.getOrderId());

        AddCreditOrder aco = new AddCreditOrder();
        UserAddress address = orderMapper.getAddressByUserId(SecurityUtils.getUserId());
        if (StringUtils.isNull(address)){
            address = UserBoundAddress(SecurityUtils.getUserId(),vo.getChain(),address);
            if (StringUtils.isNull(address)){
                return AjaxResult.error("服务器忙,请稍后再试");
            }else {
                if("BSC".equals(vo.getChain().toUpperCase()) && StringUtils.isBlank(address.getAddressBSC())){
                    return AjaxResult.error("服务器忙,请稍后再试");
                }else if("TRX".equals(vo.getChain().toUpperCase()) && StringUtils.isBlank(address.getAddressTRX())){
                    return AjaxResult.error("服务器忙,请稍后再试");
                }else {
                    if(StringUtils.isBlank(address.getAddress())){
                        return AjaxResult.error("服务器忙,请稍后再试");
                    }
                }
            }
        }
        if("BSC".equals(vo.getChain().toUpperCase())){
            if(StringUtils.isBlank(address.getAddressBSC())){
                //用户没有绑定BSC地址 从BSC地址数据库中拿一个地址  修改用户地址表中对应的字段
                address = UserBoundAddress(SecurityUtils.getUserId(),vo.getChain(),address);
                if(StringUtils.isNull(address)){
                    return AjaxResult.error(701,"系统异常,请稍后再试");
                }
            }
            aco.setAddress(address.getAddressBSC());
        }else if("TRX".equals(vo.getChain().toUpperCase())){
            if(StringUtils.isBlank(address.getAddressTRX())){
                //用户没有绑定BSC地址 从BSC地址数据库中拿一个地址  修改用户地址表中对应的字段
                address = UserBoundAddress(SecurityUtils.getUserId(),vo.getChain(),address);
                if(StringUtils.isNull(address)){
                    return AjaxResult.error(701,"系统异常,请稍后再试");
                }
            }
            aco.setAddress(address.getAddressTRX());
        }else {
            if(StringUtils.isBlank(address.getAddress())){
                //用户没有绑定BSC地址 从BSC地址数据库中拿一个地址  修改用户地址表中对应的字段
                address = UserBoundAddress(SecurityUtils.getUserId(),vo.getChain(),address);
                if(StringUtils.isNull(address)){
                    return AjaxResult.error(701,"系统异常,请稍后再试");
                }
            }
            aco.setAddress(address.getAddress());
        }
        aco.setStatus(2);
        aco.setChain(vo.getChain());
        aco.setCoin(vo.getCoin());
        aco.setUserId(SecurityUtils.getUserId());
        aco.setCreateTime(DateUtils.getNowDate());
        if(orderMapper.insertAddCreditOrder(aco)){
            AddCreditOrder order = orderMapper.getAddCreditOrderById(aco.getId());
            //订单已生成 根据链上txid查询交易信息 查询不到订单状态直接更改为失败
            AddCreditOrderVo vo1 = new AddCreditOrderVo();
            BeanUtils.copyProperties(vo,vo1);
            vo1.setCreateTime(order.getCreateTime());
            //调用根据txid和coin查询链上数据的接口
            System.out.println("入参："+vo);
            System.out.println("txid查询条件："+vo1);
            OnChainQueryByTxidResultDto dto = getETHMsgByTxid(vo1);
            System.out.println("查询返回结果"+dto);

            if(dto.getResult()){
                //查询到了对应的结果 处理订单 :更新用户账户信息 修改账户余额 如果修改失败说明有并发 重新拿取用户账户信息 再次更新

                BigDecimal amount = dto.getData().getAddressAmountMap().get(order.getAddress().toLowerCase());
                UserAccountDto oldAccount = orderMapper.getUserAccountByUserId(SecurityUtils.getUserId());//查询余额

                UserAccountDto newAccount = new UserAccountDto();
                BeanUtils.copyProperties(oldAccount,newAccount);

                UserBalance userBalance = new UserBalance();

                if("USDT".equals(order.getCoin().toUpperCase())){
                    newAccount.setUsdt(newAccount.getUsdt().add(amount));
                    userBalance.setBalanceUSDT(newAccount.getUsdt());
                }
                if("USDC".equals(order.getCoin().toUpperCase())){
                    newAccount.setUsdc(newAccount.getUsdc().add(amount));
                    userBalance.setBalanceUSDC(newAccount.getUsdc());
                }
                if("BUSD".equals(order.getCoin().toUpperCase())){
                    newAccount.setBusd(newAccount.getBusd().add(amount));
                    userBalance.setBalanceBUSD(newAccount.getBusd());
                }

                //新数据更新到数据库中
                if(orderMapper.updateUserAccount(newAccount,oldAccount.getUsdt(),oldAccount.getUsdc(),oldAccount.getBusd())){

                    //更新成功 余额表记录信息

                    BeanUtils.copyProperties(order,userBalance);
                    userBalance.setTxid(vo.getTxid());
                    userBalance.setNotes(0);
                    userBalance.setMessage("通过txid查询到转账金额:"+amount);
                    if(orderMapper.insertUserBalance(userBalance)){
                        //插入成功
                        //修改订单状态
                        HandleAddCreditOrderVo haVo = new HandleAddCreditOrderVo();
                        haVo.setOper(1);
                        haVo.setTxid(vo.getTxid());
                        haVo.setAmount(amount);
                        haVo.setTransferId(aco.getId());
                        orderMapper.updateOrdersById(haVo);
                        newAccount.setTotal(newAccount.getUsdt().add(newAccount.getBusd()).add(newAccount.getUsdc()));
                        // 发送邮件通知用户
                        EmailEntity entity = new EmailEntity();
                        entity.setEmail(SecurityUtils.getLoginUser().getSysUser().getEmail());
                        entity.setSubject("账户充值结果返回");
                        entity.setText("充值成功,当前余额usdt:"+newAccount.getUsdt()+",usdc:"+newAccount.getUsdc()+",busd:"+newAccount.getBusd());
                        remoteMailService.sendTextMail(entity);
                        return AjaxResult.success(newAccount);
                    }else {
                        //抛出异常 回滚事务
                        return AjaxResult.error("后台异常");
                    }
                }else {
                    return AjaxResult.error("服务器繁忙");
                }
            }else {
                HandleAddCreditOrderVo haVo = new HandleAddCreditOrderVo();
                haVo.setOper(0);
                haVo.setTransferId(aco.getId());
                orderMapper.updateOrderStatusById(haVo);
                return AjaxResult.error(1101,dto.getReason());
            }
        }else {
            return AjaxResult.error("数据库通信异常，请稍后再试");
        }
    }

    @Override
    public AjaxResult checkLastUseTxid() {
        UseTxidStatusDto dto = new UseTxidStatusDto();
        Long userId = SecurityUtils.getUserId();
        if (redisService.hasKey("user:"+userId+":usedTxid")){
            //不可用 返回false
            dto.setResult(false);
            dto.setTime(redisService.getExpire("user:"+userId+":usedTxid"));
        }else {
            dto.setResult(true);
            dto.setTime(0L);
        }

        return AjaxResult.success(dto);
    }

    @Override
    public List<AddCreditOrderDto> privateOrder(StatusPageVo vo)
    {

        vo.setUserId(SecurityUtils.getUserId());


        List<AddCreditOrder> list = orderMapper.getAddCreditOrderByUserId(SecurityUtils.getUserId(),vo.getStatus());

        List<AddCreditOrderDto> returnList = list.stream().map(e -> {
            AddCreditOrderDto dto = new AddCreditOrderDto();
            BeanUtils.copyProperties(e,dto);
            dto.setStatus(OrderStatus.getStatusByCode(e.getStatus()));
            return dto;
        }).collect(Collectors.toList());


        return returnList;
    }

    @Override
    public List<AddressInfo> getAllAddress(StatusPageVo vo) {
        List<AddressInfo> list = orderMapper.getAllAddress(vo.getStatus());
        return list;
    }

    @Override
    public List<AddCreditOrderDto> getAddCreditOrderList(OrderStatusVo vo) {

        if(StringUtils.isBlank(vo.getAddress())){
            vo.setAddress(null);
        }else{
            String em = "^[a-zA-Z0-9][\\w\\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\\w\\.-]*[a-zA-Z0-9]\\.[a-zA-Z][a-zA-Z\\.]*[a-zA-Z]$";
            if(!vo.getAddress().matches(em)){
               //address接收到的不是邮箱 则返回空list
                return  new ArrayList<>();
            }
        }

        vo.setUserId(orderMapper.getUserIdByEmail(vo.getAddress()));

        System.out.println(vo);

        List<AddCreditOrderDto> list = orderMapper.getAddCreditOrderByStatus(vo);

        list.stream().forEach(e -> {
            if(StringUtils.isNotBlank(e.getStatus())){
                e.setStatus(OrderStatus.getStatusByCode(Convert.toInt(e.getStatus())));
            }
        });

        return list;
    }

    /**
     * 根据订单id查看订单详情
     * @param id
     * @return
     */
    @Override
    public AjaxResult getAddCreditOrderById(long id) {
        AddCreditOrder order = orderMapper.getAddCreditOrderByOrderIdAndUserId(id,SecurityUtils.getUserId());
        if(StringUtils.isNull(order)){
            //未查到对应订单
            return AjaxResult.error("根据用户id和订单id未查询到订单信息");
        }
        AddCreditOrderDto dto = new AddCreditOrderDto();
        BeanUtils.copyProperties(order,dto);
        dto.setStatus(OrderStatus.getStatusByCode(order.getStatus()));
        return AjaxResult.success(dto);
    }

    @Override
    public AjaxResult AddTotalAddresses(TotalAddressVo vo) {

        if(StringUtils.isBlank(vo.getChain())){
            return AjaxResult.error("缺少地址对应的网络参数");
        }

        if(StringUtils.isNotNull(vo.getAddresses())){
            List<String> list = Arrays.asList(vo.getAddresses());
            int count = 0;
            if("BSC".equals(vo.getChain().toUpperCase())){
                count = orderMapper.batchInsertBSCTotalAddress(list);
            }else  if ("TRX".equals(vo.getChain().toUpperCase())){
                count = orderMapper.batchInsertTRXTotalAddress(list);
            }else if ("ETH".equals(vo.getChain().toUpperCase())){
                count = orderMapper.batchInsertTotalAddress(list);
            }
            if( count> 0){
                return AjaxResult.success("新增地址数量："+count+"");
            }else {
                return AjaxResult.error("地址新增到数据库失败");
            }
        }else {
            return AjaxResult.error("参数缺失");
        }

    }

    /**
     * 根据订单id处理订单  更改状态状态
     * @param vo
     * @return
     */
    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    @GlobalTransactional
    public AjaxResult  handleAddCreditOrder(HandleAddCreditOrderVo vo,Long userId) {
        System.out.println("接收到的vo"+vo);
        System.out.println("用户ID:"+userId);
        if(vo.getOper() != 0 && vo.getOper() != 1 && vo.getOper() != 2){
            //vo.setOper(2);
            return AjaxResult.error("操作传参异常");
        }
        AddCreditOrder order = orderMapper.getAddCreditOrderByOrderIdAndUserId(vo.getTransferId(),userId);
        System.out.println("数据库查询到订单："+order);
        if(StringUtils.isNull(order)){
            //未查到对应订单
            return AjaxResult.error("未找到对应订单");
        }
        if(order.getStatus() == 0 || order.getStatus() == 1){
            //订单如果已经是失败code:0或者成功code:1 则不能再操作
            return AjaxResult.error(801,"订单已被处理，不能再更改");
        }

        UserAccountDto oldAccount = orderMapper.getUserAccountByUserId(SecurityUtils.getUserId());//查询余额
        if (StringUtils.isNull(oldAccount)){
            oldAccount = new UserAccountDto();
            //未查询用户账户信息 可能原因1数据库暂无用户账户数据->构造用户数据插入数据库 插入失败则说明后台数据库请求异常(已有数据/数据库连接失败)
            oldAccount.setUserId(SecurityUtils.getUserId());
            oldAccount.setBusd(BigDecimal.valueOf(0));
            oldAccount.setUsdc(BigDecimal.valueOf(0));
            oldAccount.setUsdt(BigDecimal.valueOf(0));
            if(!orderMapper.insertUserAccount(oldAccount)){
                return AjaxResult.error("后台繁忙,请稍后重试");
            }
        }

        if(vo.getOper() == 1){
            //确认收到转账 更新用户账户信息 修改账户余额 如果修改失败说明有并发 重新拿取用户账户信息 再次更新

            UserAccountDto newAccount = new UserAccountDto();
            BeanUtils.copyProperties(oldAccount,newAccount);

            UserBalance userBalance = new UserBalance();
            BigDecimal amount = Convert.toBigDecimal(vo.getAmount());

            if("USDT".equals(order.getCoin().toUpperCase())){
                newAccount.setUsdt(newAccount.getUsdt().add(amount));
                userBalance.setBalanceUSDT(amount);
            }
            if("USDC".equals(order.getCoin().toUpperCase())){
                newAccount.setUsdc(newAccount.getUsdc().add(amount));
                userBalance.setBalanceUSDC(amount);
            }
            if("BUSD".equals(order.getCoin().toUpperCase())){
                newAccount.setBusd(newAccount.getBusd().add(amount));
                userBalance.setBalanceBUSD(amount);
            }

            //新数据更新到数据库中
            if(orderMapper.updateUserAccount(newAccount,oldAccount.getUsdt(),oldAccount.getUsdc(),oldAccount.getBusd())){
                System.out.println("user_account更新成功");
                //更新成功 余额表记录信息

                BeanUtils.copyProperties(order,userBalance);
                userBalance.setNotes(0);
                userBalance.setMessage(vo.getMessage());
                if(orderMapper.insertUserBalance(userBalance)){
                    System.out.println("user_balance更新成功");
                    //插入成功 发送邮件通知用户
                    //EmailEntity entity = new EmailEntity();
                    //entity.setEmail(SecurityUtils.getLoginUser().getSysUser().getEmail());
                    //entity.setSubject("账户充值结果返回");
                    //entity.setText("充值成功,到账usdt:"+newAccount.getUsdt()+",usdc:"+newAccount.getUsdc()+",busd:"+newAccount.getBusd());
                    //remoteMailService.sendTextMail(entity);

                    orderMapper.updateOrdersById(vo);
                    newAccount.setUserName(SecurityUtils.getUsername());
                    newAccount.setTotal(newAccount.getUsdt().add(newAccount.getUsdc()).add(newAccount.getBusd()));
                    return AjaxResult.success(newAccount);
                }else {
                    //抛出异常 回滚事务
                }
            }

        }else if(vo.getOper() == 0){
            //修改订单状态为失败
            //orderMapper.updateOrderStatusById(vo);
            //邮件通知用户充值异常
            EmailEntity entity = new EmailEntity();
            entity.setEmail(SecurityUtils.getLoginUser().getSysUser().getEmail());
            entity.setSubject("账户充值结果返回");
            entity.setText("充值失败，未查到交易相关信息。");
            remoteMailService.sendTextMail(entity);

            orderMapper.updateOrderStatusById(vo);

            //通知用户结果
            return AjaxResult.error("充值失败，未查到交易记录。");
        }

        orderMapper.updateOrderStatusById(vo);

        //通知用户结果

        return AjaxResult.success(oldAccount);
    }



    @Override
    public AjaxResult getUserAccount() {
        UserAccountDto dto = orderMapper.getUserAccountByUserId(SecurityUtils.getUserId());
        if(StringUtils.isNull(dto)){
            //数据库还没有当前用户信息
            UserAccountDto oldAccount = new UserAccountDto();
            oldAccount.setUserId(SecurityUtils.getUserId());
            oldAccount.setBusd(BigDecimal.valueOf(0));
            oldAccount.setUsdc(BigDecimal.valueOf(0));
            oldAccount.setUsdt(BigDecimal.valueOf(0));
            if(!orderMapper.insertUserAccount(oldAccount)){
                return AjaxResult.error("后台繁忙,获取用户账户信息失败,请稍后重试");
            }
            dto = new UserAccountDto();
            dto.setBusd(BigDecimal.valueOf(0));
            dto.setUsdt(BigDecimal.valueOf(0));
            dto.setUsdc(BigDecimal.valueOf(0));
            dto.setUserName(SecurityUtils.getUsername());
            dto.setTotal(dto.getUsdt().add(dto.getUsdc()).add(dto.getBusd()));
            return AjaxResult.success(dto);
        }else {
            dto.setUserName(SecurityUtils.getUsername());
            dto.setTotal(dto.getUsdt().add(dto.getUsdc()).add(dto.getBusd()));
            return AjaxResult.success(dto);
        }
    }


    //为用户绑定地址
    public UserAddress UserBoundAddress(long  userId,String chain,UserAddress ua){
        String table = "total_address";

        if(StringUtils.isNull(ua)){
            ua = new UserAddress();
        }
        ua.setUserId(userId);
        System.out.println("ua:"+ua);
        if("BSC".equals(chain.toUpperCase())){
            table = table+"_bsc";
        }else if("TRX".equals(chain.toUpperCase())){
            table = table+"_trx";
        }
        //先从地址数据库中选择一个地址 修改地址使用状态为已使用
        String address=orderMapper.getAddressNoUse(table);

        if(StringUtils.isBlank(address)){
            return null;
        }
        if(!orderMapper.updateAddressToUse(address,table)){
            //修改失败 重新拿一个地址
            address=orderMapper.getAddressNoUse(table);
            if(StringUtils.isBlank(address)){
                return null;
            }

            orderMapper.updateAddressToUse(address, table);
        }
        //将该地址与用户id一同存入用户地址表中
        if("BSC".equals(chain.toUpperCase())){
            ua.setAddressBSC(address);
        }else if("TRX".equals(chain.toUpperCase())){
            ua.setAddressTRX(address);
        }else {
            ua.setAddress(address);
        }


        if(orderMapper.insertAddressAndUserId(ua) > 0){
            //邮箱通知
            if(orderMapper.getAddressNoUsedCount() < 50){
                try {
                    EmailEntity entity = new EmailEntity();
                    //todo 改为获取数据库中管理员的邮箱
                    entity.setEmail("2826961034@qq.com");
                    entity.setText("地址剩余不足50个，请通知财务");
                    entity.setSubject("地址告警");
                    remoteMailService.sendTextMail(entity);
                }catch (Exception e){

                }
            }
            return ua;
        }else {
            //数据入库失败 重新拿地址再操作
            if("BSC".equals(chain.toUpperCase())){
                ua.setAddressBSC(orderMapper.getAddressNoUse(table));
            }else if("TRX".equals(chain.toUpperCase())){
                ua.setAddressTRX(orderMapper.getAddressNoUse(table));
            }else {
                ua.setAddress(orderMapper.getAddressNoUse(table));
            }
            orderMapper.updateAddressToUse(address,table);
            orderMapper.insertAddressAndUserId(ua);
            if(orderMapper.getAddressNoUsedCount() < 50){
                try {
                    EmailEntity entity = new EmailEntity();
                    //todo 改为获取数据库中管理员的邮箱
                    entity.setEmail("2826961034@qq.com");
                    entity.setText("地址剩余不足50个，请通知财务");
                    entity.setSubject("地址告警");
                    remoteMailService.sendTextMail(entity);
                }catch (Exception e){

                }
            }
            return ua;
        }
    }

    //获取链上交易信息  仅仅根据txid查询
    public OnChainQueryByTxidResultDto getETHMsgByTxid(AddCreditOrderVo vo){

        System.out.println("txid查询接口收到参数："+vo);

        //构建返回结果数据
        OnChainQueryByTxidResultDto resultDto = new OnChainQueryByTxidResultDto();
        resultDto.setChain(vo.getChain());
        resultDto.setCoin(vo.getCoin());

        String userAddr =orderMapper.getAddressByUserId(SecurityUtils.getUserId()).getAddress();
        if(StringUtils.isNull(userAddr)){
            userAddr = "";
        }
        vo.setAddress(userAddr);

        if("BSC".equals(vo.getChain())){
            //BSC 查到Txid后要根据地址去查  address要先做判空
            if(StringUtils.isNotBlank(vo.getAddress())){
                OnChainQueryResultDto dto = getBSCOnChainTxMsgByTxid(vo);
                if(dto.getResult()){
                    resultDto.setResult(true);
                    OnChainMsgByAddressDto ocDto = dto.getList().get(0);
                    OnChainMsgByTxidDto data = new OnChainMsgByTxidDto();
                    Map<String,BigDecimal> map = new HashMap<>();
                    map.put(vo.getAddress().toLowerCase(),ocDto.getAmount());
                    data.setAddressAmountMap(map);
                    data.setTime(ocDto.getTime());
                    data.setTxid(ocDto.getTxid());
                    resultDto.setData(data);
                    return resultDto;
                }else {
                    //通过地址和txid没有查到链上交易信息
                    resultDto.setReason("未根据Txid找到与address相匹配的信息");
                    resultDto.setResult(false);
                    resultDto.setData(null);
                    return resultDto;
                }

            }
            resultDto.setResult(false);
            resultDto.setReason("服务繁忙，请稍后再试");

            return resultDto;
        }

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type","application/json");
        HttpEntity<String> httpEntity = new HttpEntity<String>(null, headers);
        StringBuffer paramsURL = new StringBuffer("https://54.254.93.204:11447/balance/"+vo.getChain().toUpperCase()+"/info?txid="+vo.getTxid()+"&coin="+vo.getCoin().toUpperCase());
        URI uri = URI.create(paramsURL.toString());

        System.out.println("地址    "+paramsURL.toString());
        String s = HttpUtil.get(paramsURL.toString());

        System.out.println("链上查询结果："+s);

        if(StringUtils.isBlank(s)){
            resultDto.setResult(false);
            resultDto.setReason("未查询到txid相关信息，请检查txid、网络、币种是否有误，可稍后再试");
            return resultDto;
        }

        //eth需要先把时间轴转化为毫秒
        if("ETH".equals(vo.getChain().toUpperCase())){
            JSONObject jsonObject = null;
            try {
                jsonObject = JSON.parseObject(s);
            }catch (JSONException e){
                resultDto.setResult(false);
                resultDto.setReason("链上数据查询接口调用失败请检查txid、网络、币种是否真实");
                return  resultDto;
            }
            System.out.println("jsonObject:"+jsonObject);
            Long ts = Convert.toLong(jsonObject.get("timestamp"));
            OnChainMsgByTxidDto dto = JSONObject.parseObject(s, OnChainMsgByTxidDto.class);
            System.out.println("转换结果："+dto);
            dto.setTime(new Date(ts*1000));

            //if(vo.getCreateTime().after(dto.getTime())){
            //    //转账时间在订单生成之前 可能是链上转账过程先执行 后执行订单生成过程
            //}

            JSONArray tos = jsonObject.getJSONArray("to");
            System.out.println("tos"+tos);
            List<String> addrs = tos.toJavaList(String.class);
            System.out.println("addrs"+addrs);

            JSONArray amounts = jsonObject.getJSONArray("amount");
            System.out.println("amounts"+amounts);
            List<BigDecimal> amountList = amounts.toJavaList(BigDecimal.class);
            System.out.println("amountList"+amountList);


            Map<String,BigDecimal> map = new HashMap<>();

            for (int i =0; i < addrs.size(); i++){
                String addr = addrs.get(i);
                System.out.println("vo.getAddress():"+vo.getAddress());
                System.out.println("addr:"+addr);
                if (vo.getAddress().toLowerCase().equals(addr.toLowerCase())){
                    //i不能大于amountlist的长度
                    System.out.println("size"+amountList.size()+",i"+i);
                    if(amountList.size() >= i){
                        //相同地址直接把amount加起来
                        if(map.containsKey(addr)){
                            map.put(addr,map.get(addr).add(amountList.get(i).divide(getAmountUnit(vo),2,BigDecimal.ROUND_DOWN)));
                        }else{
                            System.out.println(amountList.get(i));
                            System.out.println(getAmountUnit(vo));
                            System.out.println(amountList.get(i).divide(getAmountUnit(vo),2,BigDecimal.ROUND_DOWN));
                            map.put(addr,amountList.get(i).divide(getAmountUnit(vo),2,BigDecimal.ROUND_DOWN));
                        }

                    }
                }
            }

            System.out.println(map);

            if(map.size() < 1){
                resultDto.setResult(false);
                resultDto.setReason("txid交易中未包含正确地址对应的数据");
                return resultDto;
            }

            dto.setAddressAmountMap(map);
            resultDto.setData(dto);
            resultDto.setResult(true);
            resultDto.setReason("已查询到相关信息");
            return resultDto;
        }
        else if ("TRC".equals(vo.getChain().toUpperCase())){
            JSONObject jsonObject = null;
            try {
                jsonObject = JSON.parseObject(s);
            }catch (JSONException e){
                resultDto.setResult(false);
                resultDto.setReason("链上数据查询接口调用失败请检查txid、网络、币种是否真实");
                return  resultDto;
            }
            OnChainMsgByTxidDto dto = JSONObject.parseObject(s, OnChainMsgByTxidDto.class);
            String address = jsonObject.getString("to");
            if(vo.getAddress().toLowerCase().equals(address.toLowerCase())){
                Map<String,BigDecimal> map = new HashMap<>();
                map.put(address,jsonObject.getBigDecimal("amount").divide(getAmountUnit(vo),2,BigDecimal.ROUND_DOWN));
                dto.setAddressAmountMap(map);
                resultDto.setResult(true);
                resultDto.setData(dto);
                return resultDto;
            }else {
                resultDto.setResult(false);
                resultDto.setReason("txid查询到的交易信息中包含的地址信息与本网站提供的地址不一致");
                return resultDto;
            }
        }else {
            resultDto.setResult(false);
            resultDto.setReason("接收到未定义的交易网络"+vo.getChain());
            return resultDto;
        }
    }

    //获取链上交易信息  仅仅根据地址查询
    public OnChainQueryResultDto getOnChainTxMsgByAddress(AddCreditOrderVo vo){

        //构造查询返回结果
        OnChainQueryResultDto resultDto = new OnChainQueryResultDto();
        resultDto.setChain(vo.getChain());
        resultDto.setCoin(vo.getCoin());

        //https://54.254.93.204:11447
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type","application/json");
        HttpEntity<String> httpEntity = new HttpEntity<String>(null, headers);
        StringBuffer paramsURL = new StringBuffer("https://54.254.93.204:11447/balance/"+vo.getChain().toUpperCase()+"/address?address="+vo.getAddress()+"&coin="+vo.getCoin().toUpperCase());
        URI uri = URI.create(paramsURL.toString());
        System.out.println(paramsURL.toString());

        String s = HttpUtil.get(paramsURL.toString());

        if(StringUtils.isBlank(s)){
            resultDto.setResult(false);
            return resultDto;
        }

        System.out.println("接口返回数据："+s+"[aaa]");

        //eth和BSC需要先把时间轴转化为毫秒
        if("ETH".equals(vo.getChain().toUpperCase()) || "BSC".equals(vo.getChain().toUpperCase())){
            List<String> dataList = JSONObject.parseArray(s, String.class);

            for(int i=0; i< dataList.size();i++){
                String e = dataList.get(i);
                JSONObject jsonObject = JSON.parseObject(e);

                Long ts = Convert.toLong(jsonObject.get("timestamp"));
                jsonObject.put("timestamp",ts*1000);
                dataList.set(i,jsonObject.toString());
            }
            s = dataList.toString();
        }

        JSONObject.DEFFAULT_DATE_FORMAT = "dd/MM/yyyy HH:mm:ss";
        List<OnChainMsgByAddressDto> list = JSONArray.parseArray(s, OnChainMsgByAddressDto.class);
        System.out.println("所有数据:"+list);
        System.out.println(vo.getCreateTime());

        //赛选出 to和address相等 即转入本公司地址的交易信息
        List<OnChainMsgByAddressDto>  byAddressList = list.stream().filter(e1 -> vo.getAddress().toLowerCase().equals(e1.getAddress().toLowerCase())).collect(Collectors.toList());
        System.out.println("根据地址筛选后的数据:"+byAddressList);
        //筛选出时间符合要求的数据
        List<OnChainMsgByAddressDto> list2 = byAddressList.stream().filter(e2 -> e2.getTime().after(vo.getCreateTime())).collect(Collectors.toList());
        System.out.println("时间筛选后的数据:"+list2);

        if(list2.size() > 0){
            //有订单创建之后的链上交易数据 说明转账成功
            resultDto.setResult(true);
            BigDecimal unit = getAmountUnit(vo);
            //list2中的amount进制转换
            list2.stream().forEach(e -> e.setAmount(e.getAmount().divide(unit,2,BigDecimal.ROUND_DOWN)));
            resultDto.setList(list2);
        }else{
            resultDto.setResult(false);
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return resultDto;
    }


    public OnChainQueryResultDto getBSCOnChainTxMsgByTxid(AddCreditOrderVo vo){

        //构造查询返回结果
        OnChainQueryResultDto resultDto = new OnChainQueryResultDto();
        resultDto.setChain(vo.getChain());
        resultDto.setCoin(vo.getCoin());

        //https://54.254.93.204:11447
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type","application/json");
        HttpEntity<String> httpEntity = new HttpEntity<String>(null, headers);
        StringBuffer paramsURL = new StringBuffer("https://54.254.93.204:11447/balance/BSC/address?address="+vo.getAddress()+"&coin="+vo.getCoin().toUpperCase());
        URI uri = URI.create(paramsURL.toString());
        System.out.println(paramsURL.toString());

        String s = HttpUtil.get(paramsURL.toString());

        if(StringUtils.isBlank(s)){
            resultDto.setResult(false);
            return resultDto;
        }

        System.out.println("接口返回数据："+s+"[aaa]");

        //BSC需要先把时间轴转化为毫秒
        List<String> dataList = JSONObject.parseArray(s, String.class);

        for(int i=0; i< dataList.size();i++){
            String e = dataList.get(i);
            JSONObject jsonObject = JSON.parseObject(e);

            Long ts = Convert.toLong(jsonObject.get("timestamp"));
            jsonObject.put("timestamp",ts*1000);
            dataList.set(i,jsonObject.toString());
        }
        s = dataList.toString();

        JSONObject.DEFFAULT_DATE_FORMAT = "dd/MM/yyyy HH:mm:ss";
        List<OnChainMsgByAddressDto> list = JSONArray.parseArray(s, OnChainMsgByAddressDto.class);
        System.out.println("所有数据:"+list);
        System.out.println(vo.getCreateTime());

        //赛选出 to和address相等 即转入本公司地址的交易信息
        List<OnChainMsgByAddressDto>  byAddressList = list.stream().filter(e1 -> vo.getAddress().toLowerCase().equals(e1.getAddress().toLowerCase())).collect(Collectors.toList());
        System.out.println("根据地址筛选后的数据:"+byAddressList);
        //筛选出txid符合要求的数据
        List<OnChainMsgByAddressDto> list2 = byAddressList.stream().filter(e2 -> e2.getTxid().toLowerCase().equals(vo.getTxid().toLowerCase())).collect(Collectors.toList());
        System.out.println("txid筛选后的数据:"+list2);

        if(list2.size() > 0){
            //有订单创建之后的链上交易数据 说明转账成功
            resultDto.setResult(true);
            BigDecimal unit = getAmountUnit(vo);
            //list2中的amount进制转换
            list2.stream().forEach(e -> e.setAmount(e.getAmount().divide(unit,2,BigDecimal.ROUND_DOWN)));
            resultDto.setList(list2);
        }else{
            resultDto.setResult(false);
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();

        }

        return resultDto;
    }


    public BigDecimal getAmountUnit(AddCreditOrderVo vo){

        BigDecimal unit = BigDecimal.valueOf(1);
        if("ETH".equals(vo.getChain())){
            if("USDC".equals(vo.getCoin().toUpperCase())){
                unit = BigDecimal.valueOf(Math.pow(10,6));
            }else if("USDT".equals(vo.getCoin().toUpperCase())){
                unit = BigDecimal.valueOf(Math.pow(10,6));
            }else if("BUSD".equals(vo.getCoin().toUpperCase())){
                unit = BigDecimal.valueOf(Math.pow(10,18));
            }
        }

        if("TRX".equals(vo.getChain())){
            if("USDC".equals(vo.getCoin().toUpperCase())){
                unit = BigDecimal.valueOf(Math.pow(10,6));
            }else if("USDT".equals(vo.getCoin().toUpperCase())){
                unit = BigDecimal.valueOf(Math.pow(10,6));
            }else if("BUSD".equals(vo.getCoin().toUpperCase())){
                unit = BigDecimal.valueOf(Math.pow(10,18));
            }
        }

        if("BSC".equals(vo.getChain())){
            unit = BigDecimal.valueOf(Math.pow(10,18));
        }

        return unit;
    }

    @Override
    public UserAccountDto updateUserAccountAfterRefuseWithdraw(Long userId, String coin, BigDecimal amount) {

        UserAccountDto oldAccount = orderMapper.getUserAccountByUserId(userId);//查询余额
        if (StringUtils.isNull(oldAccount)){
            oldAccount = new UserAccountDto();
            //未查询用户账户信息 可能原因1数据库暂无用户账户数据->构造用户数据插入数据库 插入失败则说明后台数据库请求异常(已有数据/数据库连接失败)
            oldAccount.setUserId(userId);
            oldAccount.setBusd(BigDecimal.valueOf(0));
            oldAccount.setUsdc(BigDecimal.valueOf(0));
            oldAccount.setUsdt(BigDecimal.valueOf(0));
            if(!orderMapper.insertUserAccount(oldAccount)){
                return null;
            }
        }
        UserAccountDto newAccount = new UserAccountDto();
        BeanUtils.copyProperties(oldAccount,newAccount);

        if("USDT".equals(coin.toUpperCase())){
            newAccount.setUsdt(newAccount.getUsdt().add(amount));
        }
        if("USDC".equals(coin.toUpperCase())){
            newAccount.setUsdc(newAccount.getUsdc().add(amount));
        }
        if("BUSD".equals(coin.toUpperCase())){
            newAccount.setBusd(newAccount.getBusd().add(amount));
        }

        //新数据更新到数据库中
        if(orderMapper.updateUserAccount(newAccount,oldAccount.getUsdt(),oldAccount.getUsdc(),oldAccount.getBusd())){
            return newAccount;
        }else {
            return null;
        }
    }

}
