package com.fzm.mall.server.admin.block_chain.task;

import cn.fzm.chain.simplesdk.client.ParaChainClient;
import cn.fzm.chain.simplesdk.constant.TxStatusEnum;
import cn.fzm.chain.simplesdk.model.TxDetail;
import cn.fzm.chain.simplesdk.model.TxTypeEnum;
import com.alibaba.fastjson.JSON;
import com.fzm.mall.server.admin.block_chain.config.SysAdminProperties;
import com.fzm.mall.server.admin.block_chain.enums.BlockChainTypeEnum;
import com.fzm.mall.server.admin.block_chain.model.Height;
import com.fzm.mall.server.admin.block_chain.service.IHeightService;
import com.fzm.mall.server.admin.block_chain.util.ChainUtil;
import com.fzm.mall.server.admin.finance_center.model.PlatformIntegral;
import com.fzm.mall.server.admin.finance_center.service.*;
import com.fzm.mall.server.admin.goods_center.model.ExternalToken;
import com.fzm.mall.server.admin.goods_center.service.IExternalTokenService;
import com.fzm.mall.server.admin.goods_center.service.IExternalTokenTradeService;
import com.fzm.mall.server.admin.home_page.model.Merchant;
import com.fzm.mall.server.admin.home_page.service.IMerchantService;
import com.fzm.mall.server.admin.user_center.model.User;
import com.fzm.mall.server.admin.user_center.service.IUserService;
import com.fzm.mall.server.admin.util.UUIDUtil;
import io.netty.util.internal.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.List;

/**
 * 充值
 */
@Component
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class SlcRechargeTask {
    private final static String CHAIN33_TOKEN = "token";
    private final static String CCNY = "CCNY";
    private final static String CHAIN33_COINS = "coins";
    private final static String CHAIN33_EVM = "evm";

    private final SysAdminProperties adminProperties;
    private final ParaChainClient paraClient;
    private final IHeightService heightService;
    private final IExternalTokenService externalTokenService;
    private final IExternalTokenTradeService externalTokenTradeService;
    private final IMerchantAssetsService merchantAssetsService;
    private final IMerchantAssetsFlowService merchantAssetsFlowService;
    private final IMerchantService merchantService;
    private final IUserService userService;
    private final IUserAssetService userAssetService;
    private final IUserAssetRecordService userAssetRecordService;
    private final IPlatformIntegralService platformIntegralService;
    private final ChainUtil chainUtil;

    /**
     * 充值线程启动 固定间隔检测充值线程是否存活
     */
    @PostConstruct
    public void rechargeTask() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Thread para = null;
                //Thread main = null;
                while (true) {
                    if (para == null || !para.isAlive()) {
                        log.info("【充值程序】平行链充值程序异常，重新启动");
                        para = new Thread(new ParaRechargeAction());
                        para.start();
                    }
					/*if (main == null || !main.isAlive()) {
						log.info("【充值程序】主链充值程序异常，重新启动");
						main = new Thread(new MainRechargeAction());
						main.start();
					}*/
                    try {
                        log.info("【充值程序】运行中，休息10min再检查一下状态");
                        Thread.sleep(1000 * 60 * 10);
                    } catch (InterruptedException ie) {

                    }
                }
            }
        }).start();
    }

    /**
     * 主链从块里查找所有交易，并确认是否是充值交易 CCNY token BTY coins
     */
    /*private class MainRechargeAction implements Runnable {

        @Override
        public void run() {
            // 从数据库获取已经确认的最新的块高度
            BlockHeightQO blockHeight = blockSev.getMainCurrentHeight(BlockChainTypeEnum.MAIN.getValue());
            long current_height = blockHeight.getHeight();
            int setup = 1;
            final List<TxInfoByBlock> list = new ArrayList<TxInfoByBlock>();

            while (true) {
                long leastHeight = mainClient.blockLastHeader();
                if (current_height != leastHeight) {
                    // log.info("【主链充值程序】充值交易查询开始，当前确认高度:" + current_height + ",链上高度:" +
                    // leastHeight);
                }
                // 如果已经确认到最新高度，那么稍等一会再确认
                if (current_height >= leastHeight) {
                    try {
                        Thread.sleep(10 * 1000);
                    } catch (InterruptedException ie) {
                    }
                    continue;
                }

                String blockHashByHeight = mainClient.blockHashByHeight(current_height);
                if (StringUtil.isNullOrEmpty(blockHashByHeight)) {
                } else {
                    List<String> txHashs = mainClient.blockTxhashByBlockhash(blockHashByHeight);
                    for (String txHash : txHashs) {
                        if (StringUtil.isNullOrEmpty(txHash)) {
                            continue;
                        }

                        TxDetail txDetail = mainClient.queryTxDetailByHash(txHash);

                        // 获取执行器
                        String execer = txDetail.getExecer();
                        String assetType = txDetail.getAssetType();
                        if (StringUtil.isNullOrEmpty(execer) || StringUtil.isNullOrEmpty(assetType)) {
                            continue;
                        }

                        // TOKEN CCNY
                        if ((CHAIN33_TOKEN).equals(execer) && CCNY.equalsIgnoreCase(assetType)) {
                            log.info("【主链充值程序】解析到CCNY的交易,区块高度:{},Hash:{},详情:{}", current_height, txHash,
                                    JSON.toJSONString(txDetail));

                            // 判断交易是否成功
                            TxStatusEnum statusEnum = txDetail.getResult();
                            if (statusEnum == null || statusEnum != TxStatusEnum.SUCCESS) {
                                log.info("【主链充值程序】-TOKEN-交易状态不是SUCCESS,过滤");
                                continue;
                            }

                            String fromAddr = txDetail.getFrom();
                            // 判断目标地址 如果不是系统内用户的地址 直接过滤
                            String toAddr = txDetail.getTo();
                            UserAddressVO toUserAddress = uAssetService.getUidByAddress(toAddr);
                            if (StringUtil.isNullOrEmpty(toAddr) || toUserAddress == null
                                    || StringUtil.isNullOrEmpty(toUserAddress.getUid())) {
                                log.info("【主链充值程序】-TOKEN-目标地址不是系统地址,过滤");
                                continue;
                            }

                            // 需要过滤掉除了提币之外所有的入币操作
                            // 方法一:可以检查来源地址是否是系统内部地址，如果是，在判断是否是提币交易的hash，是则放行，不是则拦截
                            // 方法二:查询当前的交易hash以及代扣hash是否出现在除了提币之外的其他交易上，出现了则拦截
                            // 这里使用方法一
                            UserAddressVO fromUserAddress = uAssetService.getUidByAddress(fromAddr);
                            if (fromUserAddress != null && !StringUtil.isNullOrEmpty(fromUserAddress.getUid())) {
                                // 检索提币交易记录的hash是否包含当前hash以及代扣hash
                                ArrayList<String> hashList = Lists.newArrayList();
                                hashList.add(txDetail.getHash());
                                String grpTxHash = mainClient.getGrpTxHashFromReal(txDetail.getHash());
                                if (!StringUtil.isNullOrEmpty(grpTxHash)) {
                                    hashList.add(grpTxHash);
                                }
                                int hashCount = coinOutService.searchHash(hashList);
                                if (hashCount <= 0) {
                                    log.info("【主链充值程序】-TOKEN-系统内部非提币交易的Hash,过滤");
                                    continue;
                                }
                            }

                            // 金额数量需要除10的8次方
                            BigDecimal amount = txDetail.getAmount();
                            amount = amount.divide(BigDecimal.valueOf(100000000L));

                            // 增加用户资产 + 资产变动记录
                            coinService.addUserCoin(toUserAddress.getUid(), 1, txDetail.getAssetType(), 0,
                                    amount.toPlainString(), 4, fromAddr);

                            log.info("【主链充值程序】解析到一条充值记录,UID:{},资产类型:{},数量:{}", toUserAddress.getUid(),
                                    txDetail.getAssetType(), amount);

                            // 添加进当前高度的充值集合
                            TxInfoByBlock txinfo = new TxInfoByBlock();
                            txinfo.setFrom(txDetail.getFrom());
                            txinfo.setBlocktime(txDetail.getBlocktime() + "");
                            txinfo.setHash(txDetail.getHash());
                            txinfo.setHeight((int) txDetail.getHeight());
                            txinfo.setIstoken(true);
                            txinfo.setNote(txDetail.getNote());
                            txinfo.setTo(txDetail.getTo());
                            txinfo.setTokenSymbol(txDetail.getAssetType());
                            txinfo.setTxIndex(txDetail.getIndex());
                            txinfo.setValue(
                                    txDetail.getAmount().divide(BigDecimal.valueOf(100000000L)).toPlainString());
                            list.add(txinfo);

                            // 发起转币 ===> 系统账户
                            String hash = mainClient.localTran(RC4Util.decrypt(toUserAddress.getPrivateKey(), null),
                                    adminProperties.getAddr(),
                                    (amount.multiply(BigDecimal.valueOf(100000000L))).longValue(), "", true,
                                    txDetail.getAssetType());
                            log.info("【主链充值程序】将用户地址的充值资产转入系统账户 UID:{},数量:{},Hash:{}", toUserAddress.getUid(), amount,
                                    hash);
                        }
                    }
                }

                // 保存当前高度的充值记录信息
                if (!list.isEmpty()) {
                    txBlockManageService.savaRechargeRecord(current_height, list, 0);
                    list.clear();
                }

                current_height += setup;
                blockHeight.setHeight(current_height);
                blockSev.updateCurrentHeight(blockHeight);

                try {
                    Thread.sleep(1 * 1000);
                } catch (InterruptedException e) {
                }
            }
        }
    }*/

    /**
     * 平行链从块里查找所有交易，并确认是否是充值交易 大黄鱼币 coins 商品币 token
     */
    private class ParaRechargeAction implements Runnable {

        public void run() {
            // 从数据库获取已经确认的最新的块高度
            Height blockHeight = heightService.getParaCurrentHeight(BlockChainTypeEnum.PARA.getValue());
            log.info("【平行链充值程序】-从数据库获取已经确认的最新的块高度:" + blockHeight.getHeight());
            long current_height = blockHeight.getHeight();
            int setup = 1;
//            final List<TxInfoByBlock> list = new ArrayList<TxInfoByBlock>();

            while (true) {
                log.info("【平行链充值程序】-当前解析高度:" + current_height);

                long leastHeight = paraClient.blockLastHeader();
                log.info("【平行链充值程序】-当前链最后高度:" + leastHeight);
                if (current_height != leastHeight) {
                    // log.info("【平行链充值程序】充值交易查询开始，当前确认高度:" + current_height + ",链上高度:" +
                    // leastHeight);
                }
                if (current_height > leastHeight) { // 如果已经确认到最新高度，那么稍等一会再确认
                    try {
                        Thread.sleep(10 * 1000);
                    } catch (InterruptedException ie) {
                    }
                    continue;
                }
//wechatpay:
//  app-id: wxbdddd81913c795e9
//  mch-id: 1604477044
//  private-key: MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDCwTnXfToW1zn/9RuT/++d8l1VeUorxPtQt62IaliqMztUEiehQ2dOtadPzvUu9VSadaEWwfhMsowosIUaOij/6qfZcm4V9PgziNS33n7WGPFAhhiIHujb6VvQDirKdAKX9DqH9DoSg0bwcSK1OdWPsRC5nhHPgDJvKzibVJeV/e36lI7ZdvB93yCChB9XFoCVhwHHteZY+sLX4RSLBzCK4z/YOiytaYkYK4YZ7QjGyCcCLNXaMa9aBEfrUKAJOePBvrPl5ieNhPyY3pPdAarqKoUaSQ74B6I9zmwNZiuJc22K70/sb6iEzPRgdiV63iDzwDp8nJm/vMZqxAigr0L5AgMBAAECggEBAIK0CSyst2KC2UMFbZe7CUY4VRk7CGMtlPiL/ONzc8PuFCAM+xnIUbnKQdpW68ezEC+FSDIsxYY7wcLBDOMYK1HtWu6dVHJZ8IUtjI1FvlvTa33BQQ+BpweHqn2MNH2gs+jlGK8LYjnwbpiJZSC5CrGfxLi98/gNckuXdysP75fSIiHnWFX2AZ3jrp+yL7dT1hkPqjZjdHespU9WRKGxSfRYFnsbPdpGYv4+RGRTTlf/fAw4n30jGc8Ua1zsGhIjlZp/x4SBnArHO+rupPH2kYDmVNJVZOqaIIJMZOprRDUzfUEIguAwJLqU2OVTsM8FEr6nV2UEbPg/A91XTqIRKbECgYEA7jNKHv+oYs3kbwGoGkgPwHnkDQbUkrfNAG1kdPTyqMCrINfeOvoDMjbcjbMlI/Gv3TaO98Ou6JTKkiavVAIg4HY0cU6fQUB4PcK9UW69ztDk7O3z4KjVE8xYMegdTb++d85QPDLHC+I2qB55o9Ux/sq+0DM8kLVkJm8UISSV0d0CgYEA0U7VjLTruNuwYAhXvIb+bjiNx52duqINGGO/zBJwoo3s1biWy3Uho6db12bqnVsSD2UXebjJblPyZr94cAaTbIEzxLd1Fl0kRIBtN4IQLWzEUwRK8PlDr2/PM+s7CIrFttsL0JsT9uBtAsMdcYa4VB/U/8s/WQzKddRbg5MsOc0CgYEA17/dAvbNrbCPl3wIpsVefxfoV2Q4ZivUou5ybvzuTas1VSoxP3n0KydF3ZLFsSjYAaXJGOFFK6SZVodzhsPmw2hNV9O+q3uZbVdV4sxLX2gV8gQVQQeq96O+vnVfFWz3N8zHH79eSoU6vEveIWaZQg6hhjLiSLADZkx2Dw70JIECgYEAtWAiL68rwWImYeF43fcBDdRWEA+mee8pd+QgdR/ZmRNxkvZFPgO/ZciGDo+xaTBc4xhQEnutmbyHBsCPBky8fb8sdCAiB4IpBm9ftUUw7ZweOG403sKyA5nZLP1/h3RxxnXktB1eXIW4ETexEQqUOtnmws6Gk41A+IBP2SG0plUCgYBn6abQwTpR1Ima5ZcJtRokADWeTUL3TGKEpHDw6ywxsmaEUACh9dhb/rEsvMitE7em2Dg1eyqialFMD50azw9dZrrb6bCcV5U4wfT8x+iQXWYXYPJbRx+5SFYOSZkKUrHVsgdLX+dDXsg88yuMUtSQ5NpWkCE1oULt9EfRAF1HyQ==
//  mch-serial-no: 72A62544B0A08A214FAEC780108692EDC6E7D5FA
//  api-V3-key: D864DA53FEF8ACD41519064967DC10D2
//  notify_url: https://146.56.197.42:8096/mallpay/wechatpay/pay/notify
//  plat-account: xxxxxxxxx
//  cert-url: https://api.mch.weixin.qq.com/v3/certificates
//  refund-notify-url: xxx
                String blockHashByHeight = paraClient.blockHashByHeight(current_height);
                log.info("【平行链充值程序】-blockHashByHeight:" + blockHashByHeight);
                if (StringUtil.isNullOrEmpty(blockHashByHeight)) {
                } else {
                    List<String> txHashs = paraClient.blockTxhashByBlockhash(blockHashByHeight);
                    log.info("【平行链充值程序】-txHashs:" + txHashs);
                    for (String txHash : txHashs) {
                        if (StringUtil.isNullOrEmpty(txHash)) {
                            continue;
                        }

                        TxDetail txDetail = paraClient.queryTxDetailByHash(txHash);
//                        System.err.println(txHash);
//                        System.err.println(paraClient.queryTxDetailByHash(txHash));
//                        TxDetail txDetail = paraClient.evmQueryTxByRealhash(txHash, "1MbJCfsBwEkTJhfbEgQ5ScHYTMPL3Nf8KF", "0xdefc650e", true);
                        log.info("【平行链充值程序】-txDetail:" + txDetail);
                        if (txDetail == null) {
                            continue;
                        }

                        // 获取执行器
                        String execer = txDetail.getExecer();
                        if (StringUtil.isNullOrEmpty(execer)) {
                            continue;
                        }

                        // 判断币的类型 COINS
                        /*if ((adminProperties.getTitle() + CHAIN33_COINS).equals(execer)) {
                            log.info("【平行链充值程序】解析到COINS交易,区块高度:{},Hash:{},详情:{}", current_height, txHash,
                                    JSON.toJSONString(txDetail));

                            // 判断交易是否成功
                            TxStatusEnum statusEnum = txDetail.getResult();
                            if (statusEnum == null || statusEnum != TxStatusEnum.SUCCESS) {
                                log.info("【平行链充值程序】-COINS-交易状态不是SUCCESS,过滤");
                                continue;
                            }

                            String fromAddr = txDetail.getFrom();
                            // 判断目标地址 如果不是系统内用户的地址 直接过滤
                            String toAddr = txDetail.getTo();
                            Merchant toUserAddress = merchantService.queryByAddress(toAddr, false);
                            if (StringUtil.isNullOrEmpty(toAddr) || toUserAddress == null
                                    || StringUtil.isNullOrEmpty(toUserAddress.getMerchantId())) {
                                log.info("【平行链充值程序】-COINS-目标地址不是系统地址,过滤");
                                continue;
                            }

                            // 需要过滤掉除了提币之外所有的入币操作
                            // 方法一:可以检查来源地址是否是系统内部地址，如果是，在判断是否是提币交易的hash，是则放行，不是则拦截
                            // 方法二:查询当前的交易hash以及代扣hash是否出现在除了提币之外的其他交易上，出现了则拦截
                            // 这里使用方法一
                            Merchant fromUserAddress = merchantService.queryByAddress(fromAddr, false);
                            if (fromUserAddress != null && !StringUtil.isNullOrEmpty(fromUserAddress.getMerchantId())) {
                                // 检索提币交易记录的hash是否包含当前hash以及代扣hash
                                *//*ArrayList<String> hashList = Lists.newArrayList();
                                hashList.add(txDetail.getHash());
                                String grpTxHash = paraClient.getGrpTxHashFromReal(txDetail.getHash());
                                if (!StringUtil.isNullOrEmpty(grpTxHash)) {
                                    hashList.add(grpTxHash);
                                }
                                int hashCount = coinOutService.searchHash(hashList);
                                if (hashCount <= 0) {
                                    log.info("【平行链充值程序】-EVM-系统内部非提币交易的Hash,过滤");
                                    continue;
                                }*//*
                                log.info("【平行链充值程序】-COINS-系统内部提币交易的Hash,过滤");
                            }

                            // 金额数量需要除10的8次方
                            BigDecimal amount = txDetail.getAmount();
                            amount = amount.divide(BigDecimal.valueOf(100000000L));

                            merchantAssetsService.updateAssets(toUserAddress.getMerchantId(), toUserAddress.getExternalTokenAddr(),
                                    txDetail.getAssetType(), amount);
                            *//*coinService.addUserCoin(toUserAddress.getUid(), 1, txDetail.getAssetType(), 1,
                                    amount.toPlainString(), 4, fromAddr);*//*
                            merchantAssetsFlowService.saveOutRecharge(toUserAddress.getMerchantId(), txDetail.getAssetType(),
                                    amount, 20, fromAddr);

                            log.info("【平行链充值程序】解析到一条充值记录,UID:{},资产类型:{},数量:{}", toUserAddress.getMerchantId(),
                                    txDetail.getAssetType(), amount);

                            externalTokenService.addToken(toUserAddress.getMerchantId(), txDetail.getAssetType(), amount, 2);
                            ExternalToken externalToken = externalTokenService.queryByLabelNameAndMerchantId(txDetail.getAssetType(), toUserAddress.getMerchantId());
                            String commodityPassId;
                            if (externalToken != null) {
                                commodityPassId = externalToken.getCommodityPassId();
                            } else {
                                commodityPassId = UUIDUtil.getUUID();
                            }
                            externalTokenTradeService.addTrade(commodityPassId, fromAddr, amount);

                            // 添加进当前高度的充值集合
                            *//*TxInfoByBlock txinfo = new TxInfoByBlock();
                            txinfo.setFrom(txDetail.getFrom());
                            txinfo.setBlocktime(txDetail.getBlocktime() + "");
                            txinfo.setHash(txDetail.getHash());
                            txinfo.setHeight((int) txDetail.getHeight());
                            txinfo.setIstoken(false);
                            txinfo.setNote(txDetail.getNote());
                            txinfo.setTo(txDetail.getTo());
                            txinfo.setTokenSymbol(txDetail.getAssetType());
                            txinfo.setTxIndex(txDetail.getIndex());
                            txinfo.setValue(
                                    txDetail.getAmount().divide(BigDecimal.valueOf(100000000L)).toPlainString());
                            list.add(txinfo);*//*

                            // 发起转币 ===> 系统账户
                            *//*String hash = paraClient.localTran(RC4Util.decrypt(toUserAddress.getPrivateKey(), null),
                                    adminProperties.getAddr(),
                                    (amount.multiply(BigDecimal.valueOf(100000000L))), "", false,
                                    txDetail.getAssetType(), false);
                            log.info("【平行链充值程序】将用户地址的充值资产转入系统账户 UID:{},数量:{},Hash:{}", toUserAddress.getUid(), amount,
                                    hash);*//*

                        }*/

                        // TOKEN 商品币
                        /*if ((adminProperties.getTitle() + CHAIN33_TOKEN).equals(execer)) {
                            log.info("【平行链充值程序】解析到TOKEN交易,区块高度:{},Hash:{},详情:{}", current_height, txHash,
                                    JSON.toJSONString(txDetail));

                            // 判断交易是否成功
                            TxStatusEnum statusEnum = txDetail.getResult();
                            if (statusEnum == null || statusEnum != TxStatusEnum.SUCCESS) {
                                log.info("【平行链充值程序】-TOKEN-交易状态不是SUCCESS,过滤");
                                continue;
                            }

                            String fromAddr = txDetail.getFrom();
                            // 判断目标地址 如果不是系统内用户的地址 直接过滤
                            String toAddr = txDetail.getTo();
                            Merchant toMerchant = merchantService.queryByAddress(toAddr);
                            User toUser = userService.queryByAddress(toAddr);
                            if (StringUtil.isNullOrEmpty(toAddr) || (
                                    (toMerchant == null || StringUtil.isNullOrEmpty(toMerchant.getMerchantId()))
                                            &&
                                            (toUser == null || StringUtil.isNullOrEmpty(toUser.getUid())))
                            ) {
                                log.info("【平行链充值程序】-TOKEN-目标地址不是系统地址,过滤");
                                continue;
                            }

                            // 需要过滤掉除了提币之外所有的入币操作
                            // 方法一:可以检查来源地址是否是系统内部地址，如果是，在判断是否是提币交易的hash，是则放行，不是则拦截
                            // 方法二:查询当前的交易hash以及代扣hash是否出现在除了提币之外的其他交易上，出现了则拦截
                            // 这里使用方法一
                            PlatformIntegral fromPlatform = platformIntegralService.queryByAddress(fromAddr);
                            Merchant fromMerchant = merchantService.queryByAddress(fromAddr);
                            User fromUser = userService.queryByAddress(fromAddr);
                            if ((fromPlatform != null && !StringUtil.isNullOrEmpty(fromPlatform.getAccount()))
                                    ||
                                    (fromMerchant != null && !StringUtil.isNullOrEmpty(fromMerchant.getMerchantId()))
                                    ||
                                    (fromUser != null && !StringUtil.isNullOrEmpty(fromUser.getUid()))
                            ) {
                                // 检索提币交易记录的hash是否包含当前hash以及代扣hash
                                *//*ArrayList<String> hashList = Lists.newArrayList();
                                hashList.add(txDetail.getHash());
                                String grpTxHash = paraClient.getGrpTxHashFromReal(txDetail.getHash());
                                if (!StringUtil.isNullOrEmpty(grpTxHash)) {
                                    hashList.add(grpTxHash);
                                }
                                int hashCount = coinOutService.searchHash(hashList);
                                if (hashCount <= 0) {
                                    log.info("【平行链充值程序】-EVM-系统内部非提币交易的Hash,过滤");
                                    continue;
                                }*//*
                                log.info("【平行链充值程序】-TOKEN-系统内部提币交易的Hash,过滤");
                                continue;
                            }

                            // 金额数量需要除10的8次方
                            BigDecimal amount = txDetail.getAmount();
                            amount = amount.divide(BigDecimal.valueOf(100000000L));

                            // 转给商户
                            if (toMerchant != null) {
                                merchantAssetsService.updateAssets(toMerchant.getMerchantId(), toMerchant.getTokenIssueAddr(),
                                        txDetail.getAssetType(), amount);
                            *//*coinService.addUserCoin(toUserAddress.getUid(), 1, txDetail.getAssetType(), 1,
                                    amount.toPlainString(), 4, fromAddr);*//*
                                merchantAssetsFlowService.saveOutRecharge(toMerchant.getMerchantId(), txDetail.getAssetType(),
                                        amount, 19, fromAddr);

                                log.info("【平行链充值程序】解析到一条充值记录,UID:{},资产类型:{},数量:{}", toMerchant.getMerchantId(),
                                        txDetail.getAssetType(), amount);

                                externalTokenService.addToken(toMerchant.getMerchantId(), txDetail.getAssetType(), amount, 1);
                                ExternalToken externalToken = externalTokenService.queryByLabelNameAndMerchantId(txDetail.getAssetType(), toMerchant.getMerchantId());
                                String commodityPassId;
                                if (externalToken != null) {
                                    commodityPassId = externalToken.getCommodityPassId();
                                } else {
                                    commodityPassId = UUIDUtil.getUUID();
                                }
                                externalTokenTradeService.addTrade(commodityPassId, fromAddr, amount);
                            }

                            // 转给用户
                            if (toUser != null) {
                                userAssetService.updateAsset(toUser.getUid(), txDetail.getAssetType(), amount);
                                userAssetRecordService.saveOutRecharge(toUser.getUid(), txDetail.getAssetType(), amount, 23, fromAddr, txHash);
                            }


                            // 添加进当前高度的充值集合
                            *//*TxInfoByBlock txinfo = new TxInfoByBlock();
                            txinfo.setFrom(txDetail.getFrom());
                            txinfo.setBlocktime(txDetail.getBlocktime() + "");
                            txinfo.setHash(txDetail.getHash());
                            txinfo.setHeight((int) txDetail.getHeight());
                            txinfo.setIstoken(true);
                            txinfo.setNote(txDetail.getNote());
                            txinfo.setTo(txDetail.getTo());
                            txinfo.setTokenSymbol(txDetail.getAssetType());
                            txinfo.setTxIndex(txDetail.getIndex());
                            txinfo.setValue(
                                    txDetail.getAmount().divide(BigDecimal.valueOf(100000000L)).toPlainString());
                            list.add(txinfo);*//*

                            // 发起转币 ===> 系统账户
                            *//*String hash = paraClient.localTran(RC4Util.decrypt(toUserAddress.getPrivateKey(), null),
                                    adminProperties.getAddr(),
                                    (amount.multiply(BigDecimal.valueOf(100000000L))), "", true,
                                    txDetail.getAssetType(), false);
                            log.info("【平行链充值程序】将用户地址的充值资产转入系统账户 UID:{},数量:{},Hash:{}", toUserAddress.getUid(), amount,
                                    hash);*//*
                        }*/

                        // EVM NFT
                        if ((adminProperties.getTitle() + CHAIN33_EVM).equals(execer) &&
                                txDetail.getType().equals(TxTypeEnum.TRAN_EVM)) {
                            log.info("【平行链充值程序】解析到EVM交易,区块高度:{},Hash:{},详情:{}", current_height, txHash,
                                    JSON.toJSONString(txDetail));

                            // 判断交易是否成功
                            TxStatusEnum statusEnum = txDetail.getResult();
                            if (statusEnum == null || statusEnum != TxStatusEnum.SUCCESS) {
                                log.info("【平行链充值程序】-EVM-交易状态不是SUCCESS,过滤");
                                continue;
                            }

                            String fromAddr = txDetail.getFrom();
                            // 判断目标地址 如果不是系统内用户的地址 直接过滤
                            String toAddr = txDetail.getTo();

                            //TODO 商户地址在哪儿生成，解析哪些地址，在哪儿获取,名字在哪儿获取
                            Merchant toMerchant = merchantService.queryByAddress(toAddr);
                            User toUser = userService.queryByAddress(toAddr);
                            if (StringUtil.isNullOrEmpty(toAddr) || (
                                    (toMerchant == null || StringUtil.isNullOrEmpty(toMerchant.getMerchantId()))
                                            &&
                                            (toUser == null || StringUtil.isNullOrEmpty(toUser.getUid())))
                            ) {
                                log.info("【平行链充值程序】-EVM-目标地址不是系统地址,过滤");
                                continue;
                            }

                            // 需要过滤掉除了提币之外所有的入币操作
                            // 方法一:可以检查来源地址是否是系统内部地址，如果是，在判断是否是提币交易的hash，是则放行，不是则拦截
                            // 方法二:查询当前的交易hash以及代扣hash是否出现在除了提币之外的其他交易上，出现了则拦截
                            // 这里使用方法一
                            PlatformIntegral fromPlatform = platformIntegralService.queryByAddress(fromAddr);
                            Merchant fromMerchant = merchantService.queryByAddress(fromAddr);
                            User fromUser = userService.queryByAddress(fromAddr);
                            if ((fromPlatform != null && !StringUtil.isNullOrEmpty(fromPlatform.getAccount()))
                                    || (fromMerchant != null && !StringUtil.isNullOrEmpty(fromMerchant.getMerchantId()))
                                    ||
                                    (fromUser != null && !StringUtil.isNullOrEmpty(fromUser.getUid()))
                            ) {
                                // 检索提币交易记录的hash是否包含当前hash以及代扣hash
                                /*ArrayList<String> hashList = Lists.newArrayList();
                                hashList.add(txDetail.getHash());
                                String grpTxHash = paraClient.getGrpTxHashFromReal(txDetail.getHash());
                                if (!StringUtil.isNullOrEmpty(grpTxHash)) {
                                    hashList.add(grpTxHash);
                                }
                                int hashCount = coinOutService.searchHash(hashList);
                                if (hashCount <= 0) {
                                    log.info("【平行链充值程序】-EVM-系统内部非提币交易的Hash,过滤");
                                    continue;
                                }*/
                                log.info("【平行链充值程序】-EVM-系统内部提币交易的Hash,过滤");
                                continue;
                            }

                            // 金额数量需要除10的8次方
                            BigDecimal amount = txDetail.getAmount();
//                            amount = amount.divide(BigDecimal.valueOf(100000000L));

                            // 转给商户
                            if (toMerchant != null) {
                                /*for (int i = 0; i < txDetail.getTokenIds().length; i++) {
                                    merchantAssetsService.updateAssets(toMerchant.getMerchantId(), toMerchant.getTokenIssueAddr(),
                                            chainUtil.getGoodsAttribute(txDetail.getTokenIds()[i], toAddr)[6], new BigDecimal(txDetail.getAmounts()[i]));
                                    merchantAssetsFlowService.saveOutRecharge(toMerchant.getMerchantId(), chainUtil.getGoodsAttribute(txDetail.getTokenIds()[i], toAddr)[6],
                                            new BigDecimal(txDetail.getAmounts()[i]), 18, fromAddr);

                                    log.info("【平行链充值程序】解析到一条充值记录,UID:{},资产类型:{},数量:{}", toMerchant.getMerchantId(),
                                            txDetail.getTokenIds()[i], new BigDecimal(txDetail.getAmounts()[i]));

                                    externalTokenService.addToken(toMerchant.getMerchantId(),
                                            chainUtil.getGoodsAttribute(txDetail.getTokenIds()[i], toAddr)[6],
                                            txDetail.getTokenIds()[i],
                                            Integer.parseInt(chainUtil.getGoodsAttribute(txDetail.getTokenIds()[i], toAddr)[2]),
                                            chainUtil.getGoodsAttribute(txDetail.getTokenIds()[i], toAddr)[5],
                                            new BigDecimal(txDetail.getAmounts()[i]),
                                            3,
                                            Long.parseLong(chainUtil.getGoodsAttribute(txDetail.getTokenIds()[i], toAddr)[3]),
                                            chainUtil.getGoodsAttribute(txDetail.getTokenIds()[i], toAddr)[4]
                                    );
                                    ExternalToken externalToken = externalTokenService.queryByLabelNameAndMerchantId(chainUtil.getGoodsAttribute(txDetail.getTokenIds()[i], toAddr)[6], toMerchant.getMerchantId());
                                    String commodityPassId;
                                    if (externalToken != null) {
                                        commodityPassId = externalToken.getCommodityPassId();
                                    } else {
                                        commodityPassId = UUIDUtil.getUUID();
                                    }
                                    externalTokenTradeService.addTrade(commodityPassId, fromAddr, new BigDecimal(txDetail.getAmounts()[i]));
                                }*/
                                merchantAssetsService.updateAssets(toMerchant.getMerchantId(), toMerchant.getTokenIssueAddr(),
                                        "NFT-" + txDetail.getTokenId(), amount);
                            /*coinService.addUserCoin(toUserAddress.getUid(), 1, txDetail.getAssetType(), 1,
                                    amount.toPlainString(), 4, fromAddr);*/
                                merchantAssetsFlowService.saveOutRecharge(toMerchant.getMerchantId(), "NFT-" + txDetail.getTokenId(),
                                        amount, 18, fromAddr);

                                log.info("【平行链充值程序】解析到一条充值记录,UID:{},资产类型:{},数量:{}", toMerchant.getMerchantId(),
                                        txDetail.getTokenId(), amount);

                                externalTokenService.addToken(toMerchant.getMerchantId(),
                                        "NFT-" + txDetail.getTokenId(),
                                        txDetail.getTokenId(),
                                        0,
                                        "",
                                        amount,
                                        3,
                                        0L,
                                        ""
                                );
                                ExternalToken externalToken = externalTokenService.queryByLabelNameAndMerchantId("NFT-" + txDetail.getTokenId(), toMerchant.getMerchantId());
                                String commodityPassId;
                                if (externalToken != null) {
                                    commodityPassId = externalToken.getCommodityPassId();
                                } else {
                                    commodityPassId = UUIDUtil.getUUID();
                                }
                                externalTokenTradeService.addTrade(commodityPassId, fromAddr, amount);

                            }

                            // 转给用户
                            /*if (toUser != null) {
                                for (int i = 0; i < txDetail.getTokenIds().length; i++) {
                                    userAssetService.updateAsset(toUser.getUid(), "NFT-" + txDetail.getTokenId(), new BigDecimal(txDetail.getAmounts()[i]));
                                    userAssetRecordService.saveOutRecharge(toUser.getUid(), "NFT-" + txDetail.getTokenId(), new BigDecimal(txDetail.getAmounts()[i]), 24, fromAddr, txHash);
                                }
                            }*/

                            //TODO 是否需要
                            // 添加进当前高度的充值集合
                            /*TxInfoByBlock txinfo = new TxInfoByBlock();
                            txinfo.setFrom(txDetail.getFrom());
                            txinfo.setBlocktime(txDetail.getBlocktime() + "");
                            txinfo.setHash(txDetail.getHash());
                            txinfo.setHeight((int) txDetail.getHeight());
                            txinfo.setIstoken(true);
                            txinfo.setNote(txDetail.getNote());
                            txinfo.setTo(txDetail.getTo());
                            txinfo.setTokenSymbol(txDetail.getAssetType());
                            txinfo.setTxIndex(txDetail.getIndex());
                            txinfo.setValue(   147BdcZm7sAkmyCsbMu1fxPUZYZCjaptX8
                                    txDetail.getAmount().divide(BigDecimal.valueOf(100000000L)).toPlainString());
                            list.add(txinfo);*/

                            // 发起转币 ===> 系统账户
                            /*String hash = paraClient.localTran(RC4Util.decrypt(toUserAddress.getPrivateKey(), null),
                                    adminProperties.getAddr(),
                                    (amount.multiply(BigDecimal.valueOf(100000000L))), "", true,
                                    txDetail.getAssetType(), false);
                            log.info("【平行链充值程序】将用户地址的充值资产转入系统账户 UID:{},数量:{},Hash:{}", toUserAddress.getUid(), amount,
                                    hash);*/
                        }
                    }
                }

                // 保存当前高度的充值记录信息
                /*if (!list.isEmpty()) {
                    txBlockManageService.savaRechargeRecord(current_height, list, 1);
                    list.clear();
                }*/

                current_height += setup;
                blockHeight.setHeight(current_height);
                heightService.updateById(blockHeight);

                try {
                    Thread.sleep(1 * 1000);
                } catch (InterruptedException e) {
                }
            }
        }
    }
}
