package com.bizzan.bitrade.engine;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bizzan.bitrade.constant.NotifyType;
import com.bizzan.bitrade.constant.TransactionType;
import com.bizzan.bitrade.entity.*;
import com.bizzan.bitrade.handler.MarketHandler;
import com.bizzan.bitrade.job.ExchangePushJob;
import com.bizzan.bitrade.consumer.ExperienceGiftCloseMsg;
import com.bizzan.bitrade.service.ContractCoinService;
import com.bizzan.bitrade.service.ContractOrderEntrustService;
import com.bizzan.bitrade.service.ExperienceGiftRecordService;
import com.bizzan.bitrade.service.FollowWalletService;
import com.bizzan.bitrade.service.MemberContractPositionService;
import com.bizzan.bitrade.service.MemberContractWalletService;
import com.bizzan.bitrade.service.MemberService;
import com.bizzan.bitrade.service.MemberTransactionService;
import com.bizzan.bitrade.service.RedisLock;
import com.bizzan.bitrade.service.UserPurseService;
import com.bizzan.bitrade.util.RedisManager;
import com.bizzan.bitrade.util.DateUtil;
import com.bizzan.bitrade.util.GeneratorUtil;
import com.bizzan.bitrade.util.MessageResult;
import com.bizzan.bitrade.vo.TradingAccount;
import com.mysql.cj.x.protobuf.MysqlxCrud;
import org.java_websocket.client.WebSocketClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

import javax.persistence.EntityManager;

/**
 * 合约撮合引擎
 */
public class ContractCoinMatch {

    private Logger logger = LoggerFactory.getLogger(ContractCoinMatch.class);

    private String symbol;                                           // 交易对：BTC/USDT
    private String baseSymbol;                                       // 基币：USDT
    private String coinSymbol;                                       // 币种：BTC
    private CoinThumb thumb;                                         // 交易对行情
    private LinkedList<ContractTrade> lastedTradeList;               // 最新成交明细
    private int lastedTradeListSize = 50;

    private long lastUpdateTime = 0L;                                // 上次价格更新时间（主要用于控制价格刷新周期，因为websokcet获取的价格变化较快）
    private boolean isTriggerComplete = true;                        // 价格刷新是否完成，触发委托及爆仓
    private BigDecimal nowPrice = BigDecimal.ZERO;                   // 当前最新价格

    private ContractCoinService contractCoinService;                  // 合约币种服务
    private ContractOrderEntrustService contractOrderEntrustService;  // 合约委托单服务
    private MemberTransactionService memberTransactionService;
    private MemberService memberService;
    private MemberContractWalletService memberContractWalletService;
    private MemberContractPositionService memberContractPositionService;
    private UserPurseService userPurseService;
    private FollowWalletService followWalletService;
    private TradingAccountMonitor tradingAccountMonitor;
    private KafkaTemplate<String, String> kafkaTemplate;
    private RedisManager redisManager;
    private EntityManager entityManager;
    private RedisLock redisLock;
    private ExperienceGiftRecordService experienceGiftRecordService;  // 体验金券服务（用于内存缓存）
    public RedisLock getRedisLock() {
		return redisLock;
	}

	public void setRedisLock(RedisLock redisLock) {
		this.redisLock = redisLock;
	}

	private ContractCoin contractCoin;

    private List<ContractOrderEntrust> contractOrderEntrustList = new ArrayList<>();      // 委托列表(计划委托)
    private List<MemberContractWallet> memberContractWalletList = new ArrayList<>();      // 用户仓位信息

    private List<MarketHandler> handlers;                             // 行情、概要等处理者
    private ExchangePushJob exchangePushJob;                          // 推送任务

    //卖盘盘口信息
    private TradePlate sellTradePlate;
    //买盘盘口信息
    private TradePlate buyTradePlate;

    private boolean isStarted = false;                                // 是否启动完成（用于初始化时，获取一些数据库未处理的订单的，如果没获取完，不允许处理）

    private LinkedList<ContractOrderEntrust> openOrderList = new LinkedList<ContractOrderEntrust>(); // 开仓订单
    private LinkedList<ContractOrderEntrust> closeOrderList = new LinkedList<ContractOrderEntrust>(); // 平仓订单

    private LinkedList<ContractOrderEntrust> openOrderSpotList = new LinkedList<ContractOrderEntrust>(); // 开仓止盈止损订单
    private LinkedList<ContractOrderEntrust> closeOrderSpotList = new LinkedList<ContractOrderEntrust>(); // 平仓止盈止损订单
    
    private static Map<Long, List<ContractOrderEntrust>> orderListMap = new ConcurrentHashMap();
    
    private ReentrantLock lock = new ReentrantLock(true);

    /**
     * 构造函数
     * @param symbol
     */
    public ContractCoinMatch(String symbol) {
        this.symbol = symbol;
        this.coinSymbol = symbol.split("/")[0];
        this.baseSymbol = symbol.split("/")[1];
        this.handlers = new ArrayList<>();
        this.lastedTradeList = new LinkedList<>();
        this.buyTradePlate = new TradePlate(symbol, ContractOrderDirection.BUY);
        this.sellTradePlate = new TradePlate(symbol, ContractOrderDirection.SELL);
        // 初始化行情
        this.initializeThumb();
    }

    public void trade(ContractOrderEntrust order) {
    	logger.info("进入交易引擎");
        if(!this.isStarted) return;
        if(!symbol.equalsIgnoreCase(order.getSymbol())){
            logger.info("unsupported symbol,coin={},base={}", order.getCoinSymbol(), order.getBaseSymbol());
            return ;
        }
        if(order.getIsCut()!=1) {
	        if(order.getVolume().compareTo(BigDecimal.ZERO) <=0 || order.getVolume().subtract(order.getTradedVolume()).compareTo(BigDecimal.ZERO)<=0){
	            return ;
	        }
        }
        if(order.getEntrustType() == ContractOrderEntrustType.OPEN) { // 开仓
            if(order.getType() == ContractOrderType.MARKET_PRICE) { // 市价，直接成交
                this.dealOpenOrder(order);
            }else if(order.getType() == ContractOrderType.LIMIT_PRICE) { // 限价
                //if(order.getDirection() == ContractOrderDirection.BUY && order.getEntrustPrice().compareTo(nowPrice) >= 0
                //        || order.getDirection() == ContractOrderDirection.SELL && order.getEntrustPrice().compareTo(nowPrice) <= 0){ // 出价高于当前价，直接成交
                if(order.getIsLimitPrice()==1) {
                	this.dealOpenOrder(order);
                }else{
                    // 放入列表中
                    synchronized (openOrderList) {
                        logger.info("开仓订单进入监控队列");
                        openOrderList.addLast(order);
                        this.addToMap(order);
                        updateTradingAccount(order);
                    }
                }
            }else if(order.getType() == ContractOrderType.SPOT_LIMIT) { // 计划委托
                // 体验金仓位不支持开仓计划委托单（止盈止损仅允许平仓方向），直接忽略
                if (order.getExperienceRecordId() != null) {
                    logger.warn("体验金开仓计划委托单不允许，忽略 orderId={}", order.getId());
                } else {
                    synchronized (openOrderSpotList) {
                        boolean exists = openOrderSpotList.stream().anyMatch(o -> o.getId().longValue() == order.getId().longValue());
                        if (exists) {
                            logger.warn("openOrderSpotList 重复订单，跳过: orderId={}", order.getId());
                        } else {
                            logger.info("开仓计划委托订单进入监控队列");
                            openOrderSpotList.add(order);
                            this.addToMap(order);
                        }
                    }
                }
            }
        }else if(order.getEntrustType() == ContractOrderEntrustType.CLOSE) { // 平仓
            if(order.getType() == ContractOrderType.MARKET_PRICE) { // 市价，直接成交
                this.dealCloseOrder(order);
            }else if(order.getType() == ContractOrderType.LIMIT_PRICE) { // 限价
                //if(order.getDirection() == ContractOrderDirection.BUY && order.getEntrustPrice().compareTo(nowPrice) > 0
                //        || order.getDirection() == ContractOrderDirection.SELL && order.getEntrustPrice().compareTo(nowPrice) < 0){ // 出价高于当前价，直接成交
                if(order.getTradedPrice().compareTo(BigDecimal.ZERO)>0) {
                	this.dealCloseOrder(order);
                }else{
                    // 放入列表中
                    synchronized (closeOrderList) {
                        logger.info("平仓订单进入监控队列");
                        closeOrderList.addLast(order);
                        this.addToMap(order);
                    }
                    updateTradingAccount(order);
                }
            }else if(order.getType() == ContractOrderType.SPOT_LIMIT) { // 计划委托
                // 体验金订单只入 orderListMap 供前端展示，不进入止盈止损触发队列
                if (order.getExperienceRecordId() != null) {
                    logger.info("体验金平仓计划委托订单跳过止盈止损队列，仅入内存Map orderId={}", order.getId());
                    this.addToMap(order);
                } else {
                    synchronized (closeOrderSpotList) {
                        boolean exists = closeOrderSpotList.stream().anyMatch(o -> o.getId().longValue() == order.getId().longValue());
                        if (exists) {
                            logger.warn("closeOrderSpotList 重复订单，跳过: orderId={}", order.getId());
                        } else {
                            logger.info("平仓计划委托订单进入监控队列");
                            closeOrderSpotList.add(order);
                            this.addToMap(order);
                            updateTradingAccount(order);
                        }
                    }
                }
            }
        }
    }

    /**
     * 成交开仓委托
     * @param order
     */
    @Transactional(rollbackFor = Exception.class)
    public void dealOpenOrder(ContractOrderEntrust order){
        logger.info("成交开仓订单");
        
        // 计算开仓价（滑点 > 市价用）
        /*BigDecimal openPrice = BigDecimal.ZERO;
        if(order.getType() == ContractOrderType.LIMIT_PRICE && order.getIsLimitPrice()==1) {
        	openPrice = order.getEntrustPrice();
        } else {
            openPrice = nowPrice;
            logger.info("symbol={},contractid={}, nowPrice={}", symbol, contractCoin.getId(), nowPrice);
	        if (order.getDirection() == ContractOrderDirection.BUY) { // 买入，滑点计算，做多，更高价格成交
	            if (contractCoin.getSpreadType() == 1) { // 滑点类型：百分比
	                openPrice = nowPrice.add(nowPrice.multiply(contractCoin.getSpread())); // 已当前价成交（或滑点价成交）
	            } else { // 滑点类型：固定额
	                openPrice = nowPrice.add(contractCoin.getSpread());
	            }
	        } else { // 卖出，滑点计算，做空，更低价格成交
	            if (contractCoin.getSpreadType() == 1) { // 滑点类型：百分比
	                openPrice = nowPrice.subtract(nowPrice.multiply(contractCoin.getSpread())); // 已当前价成交（或滑点价成交）
	            } else { // 滑点类型：固定额
	                openPrice = nowPrice.subtract(contractCoin.getSpread());
	            }
	        }
            logger.info("openPrice={}", openPrice);
        }
        order.setTradedPrice(openPrice);*/
        
        memberContractPositionService.processOpenOrder(order);

        // 同步最新用户持仓数据
        updateTradingAccount(order);
        //memberWalletChange(memberContractWallet.getId());
        //syncMemberPosition();
        
        //止盈止损单开仓
        if(order.getType() == ContractOrderType.LIMIT_PRICE)
        	openCutOrder(order);
    }
    
    @Transactional(rollbackFor = Exception.class)
    public void openCutOrder(ContractOrderEntrust order) {
    	if((order.getLossPrice()==null || order.getLossPrice().compareTo(BigDecimal.ZERO)<=0)
    			&& (order.getProfitPrice()==null || order.getProfitPrice().compareTo(BigDecimal.ZERO)<=0))
    		return;
    	
    	List<ContractOrderEntrust> cutList = contractOrderEntrustService.findPositionCuts(order.getPositionId());
        if(cutList.size()>0) {
        	return;
        }
    	
    	MemberContractPosition memberContractPosition = memberContractPositionService.findOne(order.getPositionId());
    	
    	BigDecimal volume = order.getVolume();
    	// 1、计算开仓手续费(合约张数 * 合约面值 * 开仓费率）
        BigDecimal closeFee = volume.multiply(contractCoin.getShareNumber()).multiply(contractCoin.getCloseFee()).setScale(8, BigDecimal.ROUND_DOWN);

        // 新建合约委托单
        ContractOrderEntrust orderEntrust = new ContractOrderEntrust();
        orderEntrust.setContractId(contractCoin.getId()); // 合约ID
        orderEntrust.setMemberId(order.getMemberId()); // 用户ID
        orderEntrust.setSymbol(contractCoin.getSymbol()); // 交易对符号
        orderEntrust.setBaseSymbol(contractCoin.getSymbol().split("/")[1]); // 基币/结算币
        orderEntrust.setCoinSymbol(contractCoin.getSymbol().split("/")[0]); // 币种符号
        orderEntrust.setDirection(order.getDirection()==ContractOrderDirection.BUY?ContractOrderDirection.SELL:ContractOrderDirection.BUY); // 平仓方向：平空/平多
        orderEntrust.setContractOrderEntrustId(GeneratorUtil.getOrderId("CE"));
        orderEntrust.setVolume(BigDecimal.ZERO); // 平仓张数
        orderEntrust.setTradedVolume(BigDecimal.ZERO); // 已交易数量
        orderEntrust.setTradedPrice(BigDecimal.ZERO); // 成交价格
        orderEntrust.setPrincipalUnit("USDT"); // 保证金单位
        orderEntrust.setPrincipalAmount(BigDecimal.ZERO); // 保证金数量
        orderEntrust.setCreateTime(DateUtil.getTimeMillis()); // 开仓时间
        orderEntrust.setType(ContractOrderType.SPOT_LIMIT);
        orderEntrust.setProfitPrice(order.getProfitPrice()); // 触发价
        orderEntrust.setProfitEntrustPrice(order.getProfitEntrustPrice()); // 委托价格
        orderEntrust.setLossPrice(order.getLossPrice()); // 触发价
        orderEntrust.setLossEntrustPrice(order.getLossEntrustPrice()); // 委托价格
        orderEntrust.setEntrustType(ContractOrderEntrustType.CLOSE); // 开仓
        orderEntrust.setTriggeringTime(0L); // 触发时间，暂时无效
        orderEntrust.setShareNumber(contractCoin.getShareNumber());
        orderEntrust.setProfitAndLoss(BigDecimal.ZERO); // 盈亏（仅平仓计算）
        orderEntrust.setPatterns(order.getPatterns()); // 仓位模式
        orderEntrust.setCloseFee(closeFee);
        orderEntrust.setCurrentPrice(order.getEntrustPrice());
        orderEntrust.setIsBlast(0); // 不是爆仓单
        orderEntrust.setIsFromSpot(1);
        orderEntrust.setIsCut(1);
        orderEntrust.setPositionId(memberContractPosition.getId());
        orderEntrust.setPositionType(memberContractPosition.getType());
        orderEntrust.setLeverage(memberContractPosition.getLeverage().intValue());
        orderEntrust.setCloseType(CloseType.CUT);
        orderEntrust.setDecimalScale(order.getDecimalScale());
        orderEntrust.setMoneyType(order.getMoneyType());
        orderEntrust.setOpenType(memberContractPosition.getOpenType());
        orderEntrust.setUsdtOpenPrice(memberContractPosition.getOpenPrice());
        
        //int success = memberContractPositionService.freezePosition(memberContractPosition.getId(), volume);
        int success = 1;
        if(success == 1) {
	        // 保存委托单
	        orderEntrust.setStatus(ContractOrderEntrustStatus.ENTRUST_ING); // 委托状态：委托中
	        contractOrderEntrustService.save(orderEntrust);
			trade(orderEntrust);
				
        } else {
        	orderEntrust.setStatus(ContractOrderEntrustStatus.ENTRUST_FAILURE);
        	contractOrderEntrustService.save(orderEntrust);
        }
    }
    
    @Transactional(rollbackFor = Exception.class)
    public void test(MemberContractPosition position) {
    	MemberContractPosition position1 = memberContractPositionService.findOne(position.getId());
    	position1.setBlastedAmount(BigDecimal.ONE);
    }
    
    @Transactional(rollbackFor = Exception.class)
    public void dealAllCloseOrder(MemberContractPosition position, BigDecimal tradedPrice, long dealTime) {
    	BigDecimal releasedPosition = this.cancelCloseOrdersByPositionId(position.getId());
    	logger.info("position={}, releasedPosition={}", JSON.toJSONString(position), releasedPosition);
    	//BigDecimal volume = position.getAvailablePosition().add(releasedPosition);
    	//position = memberContractPositionService.findOne(position.getId());
    	BigDecimal volume = memberContractPositionService.findOne(position.getId()).getAvailablePosition();
		if(volume.compareTo(BigDecimal.ZERO)<=0)
			return;
		
		ContractOrderEntrust orderEntrust = new ContractOrderEntrust();
        orderEntrust.setContractId(contractCoin.getId()); // 合约ID
        orderEntrust.setMemberId(position.getMemberId()); // 用户ID
        orderEntrust.setSymbol(contractCoin.getSymbol()); // 交易对符号
        orderEntrust.setBaseSymbol(contractCoin.getSymbol().split("/")[1]); // 基币/结算币
        orderEntrust.setCoinSymbol(contractCoin.getSymbol().split("/")[0]); // 币种符号
        if(position.getDirection() == ContractOrderDirection.BUY)
        	orderEntrust.setDirection(ContractOrderDirection.SELL); // 平仓方向：平空/平多
        else
        	orderEntrust.setDirection(ContractOrderDirection.BUY);
        orderEntrust.setContractOrderEntrustId(GeneratorUtil.getOrderId("CE"));
        orderEntrust.setVolume(volume); // 平仓张数
        orderEntrust.setTradedVolume(BigDecimal.ZERO); // 已交易数量
        orderEntrust.setTradedPrice(tradedPrice); // 成交价格
        orderEntrust.setPrincipalUnit("USDT"); // 保证金单位
        orderEntrust.setPrincipalAmount(BigDecimal.ZERO); // 保证金数量
        orderEntrust.setCreateTime(DateUtil.getTimeMillis()); // 开仓时间
        orderEntrust.setType(ContractOrderType.MARKET_PRICE);
        orderEntrust.setTriggerPrice(BigDecimal.ZERO); // 触发价
        orderEntrust.setEntrustPrice(BigDecimal.ZERO); // 委托价格
        orderEntrust.setEntrustType(ContractOrderEntrustType.CLOSE); // 平仓
        orderEntrust.setTriggeringTime(0L); // 触发时间，暂时无效
        orderEntrust.setShareNumber(contractCoin.getShareNumber());
        orderEntrust.setProfitAndLoss(BigDecimal.ZERO); // 盈亏（仅平仓计算）
        orderEntrust.setPatterns(ContractOrderPattern.CROSSED); // 仓位模式
        orderEntrust.setCloseFee(BigDecimal.ZERO);
        orderEntrust.setCurrentPrice(nowPrice);
        orderEntrust.setIsBlast(0); // 不是爆仓单
        orderEntrust.setIsFromSpot(0);
        orderEntrust.setPrincipalAmount(BigDecimal.ZERO); // 全部多仓保证金
        orderEntrust.setPositionId(position.getId());
        orderEntrust.setLeverage(position.getLeverage().intValue());
        orderEntrust.setUsdtOpenPrice(position.getOpenPrice());
        orderEntrust.setCloseType(position.getCloseType());
        orderEntrust.setMoneyType(position.getMoneyType());
        orderEntrust.setPositionType(position.getType());
        //orderEntrust.setTradedPrice(nowPrice);
        orderEntrust.setDecimalScale(position.getDecimalScale() != null ? position.getDecimalScale() : contractCoin.getCoinScale());
        if (position.getCloseType() == CloseType.BLAST) {
        	orderEntrust.setProfitAndLoss(position.getBlastedAmount());
        }
        if (position.getFollowPositionId() != null) {
        	orderEntrust.setFollowId(position.getFollowPositionId());
        }
        // 体验金仓位：传递 recordId，并标记 isReward=1 跳过返佣
        if (position.getExperienceRecordId() != null) {
            orderEntrust.setExperienceRecordId(position.getExperienceRecordId());
            orderEntrust.setIsReward(1);
        }
        if(dealTime != 0)
        	orderEntrust.setDealTime(dealTime);
        
        ContractOrderEntrust retObj;
        int successCount = memberContractPositionService.freezePosition(position.getId(), volume);
        if(successCount == 1) {
	        // 保存委托单
	        orderEntrust.setStatus(ContractOrderEntrustStatus.ENTRUST_ING); // 委托状态：委托中
	        retObj = contractOrderEntrustService.save(orderEntrust);
        } else {
        	orderEntrust.setStatus(ContractOrderEntrustStatus.ENTRUST_FAILURE);
	        retObj = contractOrderEntrustService.save(orderEntrust);
	        return;
        }

        try {
    		this.trade(retObj);
    	} catch (Exception e) {
    	    // processCloseOrder rolled back its own transaction, but freezePosition and the ENTRUST_ING
    	    // order are already committed (ContractCoinMatch is not a Spring bean, so @Transactional
    	    // on this method is decorative). Recover: cancel the stuck order and thaw the position.
    	    logger.error("[dealAllCloseOrder] trade failed for positionId={} orderId={}, recovering",
    	            position.getId(), retObj.getId(), e);
    	    try {
    	        contractOrderEntrustService.updateStatusAndDealTime(retObj.getId(),
    	                ContractOrderEntrustStatus.ENTRUST_FAILURE, DateUtil.getTimeMillis());
    	        memberContractPositionService.thawPosition(position.getId(), volume);
    	    } catch (Exception ex) {
    	        logger.error("[dealAllCloseOrder] recovery also failed for positionId={}", position.getId(), ex);
    	    }
    	}
    }
    
    @Transactional(rollbackFor = Exception.class)
    public void dealAllCloseOrder(MemberContractPosition position) {
    	BigDecimal tradedPrice = this.getAdjustedNowPrice(position.getDirection()==ContractOrderDirection.BUY?ContractOrderDirection.SELL:ContractOrderDirection.BUY);
		if(tradedPrice.compareTo(BigDecimal.ZERO)<=0)
    		return;
		
    	this.dealAllCloseOrder(position, tradedPrice, 0);
    }

    /**
     * 成交平仓委托
     * @param order
     */
    @Transactional(rollbackFor = Exception.class)
    public void dealCloseOrder(ContractOrderEntrust order) {
    	logger.info("成交平仓委托");
    	
        try {
	        // 计算滑点成交价（市价下单时用此价格）
	        /*BigDecimal dealPrice = BigDecimal.ZERO;
	        if(order.getType() == ContractOrderType.LIMIT_PRICE && order.getIsLimitPrice()==1) {
	        	dealPrice = order.getEntrustPrice();
	        } else {
	        	dealPrice = nowPrice;
		        if (order.getDirection() == ContractOrderDirection.BUY) { // 买入平空，滑点计算，更低价格
		            if (contractCoin.getSpreadType() == 1) { // 滑点类型：百分比
		                dealPrice = nowPrice.add(nowPrice.multiply(contractCoin.getSpread())); // 已当前价成交（或滑点价成交）
		            } else { // 滑点类型：固定额
		                dealPrice = nowPrice.add(contractCoin.getSpread());
		            }
		        } else { // 卖出，滑点计算，做空，更低价格成交
		            if (contractCoin.getSpreadType() == 1) { // 滑点类型：百分比
		                dealPrice = nowPrice.subtract(nowPrice.multiply(contractCoin.getSpread())); // 已当前价成交（或滑点价成交）
		            } else { // 滑点类型：固定额
		                dealPrice = nowPrice.subtract(contractCoin.getSpread());
		            }
		        }
	        }
	        order.setTradedPrice(dealPrice);*/
	        
	        memberContractPositionService.processCloseOrder(order);
	
	        // 同步最新用户持仓数据
	        updateTradingAccount(order);
	        //memberWalletChange(memberContractWallet.getId());
	        // 同步最新用户持仓数据
	        // syncMemberPosition();
        } catch(Exception e) {
    		logger.error(e.getMessage(), e.getCause());
    	}
    	finally {
    		//redisLock.unlockOrder(order.getId());
    	}
    }

    /**
     * 启动引擎，加载未处理订单
     */
    public void run(){
        logger.info(symbol + " 合约引擎启动，加载数据库订单....");
        contractCoin = contractCoinService.findBySymbol(symbol);
        if(contractCoin == null) {
            logger.info(contractCoin.getSymbol() + "引擎启动失败，找不到合约交易对");
            return;
        }
        // 数据库查找订单，加载到列表中
        contractOrderEntrustList = contractOrderEntrustService.loadUnMatchOrders(contractCoin.getId());
        if(contractOrderEntrustList != null && contractOrderEntrustList.size() > 0) {
            logger.info(contractCoin.getSymbol() + "加载订单，共计 " + contractOrderEntrustList.size());
            for (ContractOrderEntrust item : contractOrderEntrustList) {
                // 体验金订单处理：仅允许平仓方向的止盈止损单（CLOSE+SPOT_LIMIT）入内存Map供前端展示
                // 开仓方向的计划委托单（OPEN+SPOT_LIMIT）在体验金场景下不合法，直接忽略
                if (item.getExperienceRecordId() != null) {
                    if (item.getType() == ContractOrderType.SPOT_LIMIT
                            && item.getEntrustType() == ContractOrderEntrustType.CLOSE) {
                        logger.info("体验金平仓止盈止损单加载至内存Map itemId={}", item.getId());
                        this.addToMap(item);
                    } else {
                        logger.info("跳过体验金非平仓止盈止损订单加载 itemId={}, type={}, entrustType={}",
                                item.getId(), item.getType(), item.getEntrustType());
                    }
                    continue;
                }
                if (item.getEntrustType() == ContractOrderEntrustType.OPEN) { // 开仓单
                    if (item.getType() == ContractOrderType.SPOT_LIMIT) { // 计划委托单（止盈止损单）
                        openOrderSpotList.add(item);
                    } else {
                        openOrderList.add(item);
                    }

                } else { // 平仓单
                    if (item.getType() == ContractOrderType.SPOT_LIMIT) { // 计划委托单（止盈止损单）
                        closeOrderSpotList.add(item);
                    } else {
                        closeOrderList.add(item);
                    }
                }
                this.addToMap(item);
            }
        }
        // 加载用户持仓信息
        //this.syncMemberPosition();
        this.isStarted = true;
    }
    
    public void stop() {
    	this.isStarted = false;
    }

    /**
     * 更新盘口（买卖盘，火币Websocket获取到的是20条）
     * @param buyPlateItems
     * @param sellPlateItems
     */
    public void refreshPlate(List<TradePlateItem> buyPlateItems, List<TradePlateItem> sellPlateItems) {
        if(!this.isStarted) return;

        this.buyTradePlate.setItems(buyPlateItems);
        this.sellTradePlate.setItems(sellPlateItems);

        this.exchangePushJob.addPlates(symbol, sellTradePlate);
        this.exchangePushJob.addPlates(symbol, buyTradePlate);

        //logger.info("{} 盘口刷新：买盘大小-{}, 卖盘大小-{}", symbol, buyPlateItems.size(), sellPlateItems.size());
    }

    /**
     * 更新行情
     * @param thumb
     */
    public void refreshThumb(CoinThumb thumb) {
        if(!this.isStarted) return;

        this.thumb.setHigh(thumb.getHigh());
        this.thumb.setLow(thumb.getLow());
        this.thumb.setOpen(thumb.getClose());
        this.thumb.setClose(thumb.getClose());
        this.thumb.setTurnover(thumb.getTurnover());
        this.thumb.setVolume(thumb.getVolume());
        this.thumb.setUsdRate(thumb.getClose());
        // 计算变化（变化金额以及变化比例，其中变化比例会出现负数）
        //this.thumb.setChange(thumb.getClose().subtract(thumb.getOpen()));
        //if(thumb.getOpen().compareTo(BigDecimal.ZERO) > 0) {
        //    this.thumb.setChg(this.thumb.getChange().divide(this.thumb.getOpen(), 4, RoundingMode.UP));
        //}
        this.thumb.setChange(thumb.getChange());
        this.thumb.setChg(thumb.getChg());
        //logger.info("symbol={}, open={}, close={}, chg={}", symbol, thumb.getOpen(), thumb.getClose(), thumb.getChg());
        this.thumb.setTime(System.currentTimeMillis());
        

        
        //logger.info("{} 行情刷新：Hight-{}, Low-{}, Open-{}, Close-{}", symbol, thumb.getHigh(), thumb.getLow(), thumb.getOpen(), thumb.getClose());
        // 推送行情
        //handleCoinThumb();
        //this.exchangePushJob.addThumb(symbol, thumb);
    }

    /**
     * 更新价格
     * 更新价格时，涉及到计划委托、止盈止损检测、爆仓检查，有一定耗时操作
     */
    public void refreshPrice(CoinThumb thumb) {
    	BigDecimal newPrice = thumb.getClose();
        // 尚未启动
        if(!this.isStarted) return;

        // 上一次任务尚未完成
        /*if(!isTriggerComplete) {
            return;
        }*/

        int queueLength = lock.getQueueLength();
        if(queueLength > 10) {
        	logger.info("太多任务等待, queueLength={}, symbol={}, 跳过价格={}", queueLength, this.symbol, newPrice);
            return;
        }
        try {
        	lock.lock();

            // 价格未发生变化，无需继续操作
            if (this.nowPrice.compareTo(newPrice) == 0) {
                return;
            }
            this.nowPrice = newPrice;
            
            long currentTime = Calendar.getInstance().getTimeInMillis();
            // 控制1秒+更新一次
            lastUpdateTime = currentTime;
            
	        // 开始检查委托
	        isTriggerComplete = false;
	        this.process(thumb);
	    } catch(Exception e) {
	    	logger.error("刷新价格执行异常", e);
	    } finally {
	    	lock.unlock();
	    }

    }

    /**
     * 更新成交明细
     * @param tradeArrayList
     */
    public void refreshLastedTrade(List<ContractTrade> tradeArrayList) {
        synchronized (lastedTradeList) {
            for (ContractTrade trade : tradeArrayList) {
                if (lastedTradeList.size() > lastedTradeListSize) {
                    this.lastedTradeList.removeLast();
                    this.lastedTradeList.addFirst(trade);
                } else {
                    this.lastedTradeList.addFirst(trade);
                }
            }
//        logger.info("{} 盘面更新：大小-{}", symbol, tradeArrayList.size());
            // 添加成交明细
            this.exchangePushJob.addTrades(symbol, tradeArrayList);
        }
    }

    /**
     * 处理委托单
     */
    public void process(CoinThumb thumb) {
        long startTick = System.currentTimeMillis();
    	try {
	        //this.processBlastCheck(newPrice);              // 1、爆仓处理
    		//logger.info("{}, processBlastCheck", symbol);
	        this.processOpenSpotEntrustList(thumb.getClose());     // 2、开仓计划委托处理
    		//logger.info("{}, processOpenSpotEntrustList", symbol);
	        this.processCloseSpotEntrustList(thumb.getClose());    // 3、平仓计划委托处理
    		//logger.info("{}, processCloseSpotEntrustList", symbol);
    	} catch (Exception e) {
    		logger.info("{}, error1:{}", symbol, e.getMessage());
    		logger.error(symbol, e);
    	}
    	try {
    		this.processCloseEntrustList(thumb);        // 4、平仓委托处理
    		//logger.info("{}, processCloseEntrustList", symbol);
	        this.processOpenEntrustList(thumb);         // 5、开仓委托处理
    		//logger.info("{}, processOpenEntrustList", symbol);
    	} catch (Exception e) {
    		logger.info("{}, error2:{}", symbol, e.getMessage());
    		logger.error(symbol, e);
    	}
    	try {
    	    this.checkExperienceGiftPositions(thumb.getClose()); // 6、体验金仓位行情检查
    	} catch (Exception e) {
    	    logger.error("{}, checkExperienceGiftPositions error:{}", symbol, e.getMessage(), e);
    	}
        this.isTriggerComplete = true;
        //logger.info("委托处理耗时：{}", System.currentTimeMillis() - startTick);
    }

    /**
     * 体验金仓位行情检查（每次价格刷新时调用，仅检查当前交易对）
     * <p>
     * 触发条件优先级：盈利触顶 > 用户止盈/止损 > 爆仓
     * 触发后立即从内存缓存移除（防止下一个 tick 重复触发），再发送 Kafka 平仓消息。
     *
     * @param currentPrice 当前最新价格
     */
    private void checkExperienceGiftPositions(BigDecimal currentPrice) {
        // 未注入 service 时跳过（兼容单元测试或部分部署场景）
        if (experienceGiftRecordService == null) return;
        Map<Long, ExperienceGiftRecord> inUseCache = experienceGiftRecordService.getInUseCache();
        if (inUseCache.isEmpty()) return;

        for (ExperienceGiftRecord record : inUseCache.values()) {
            // 仅处理当前交易对
            if (!this.symbol.equals(record.getCoinSymbol())) continue;
            if (record.getAutoClosePrice() == null || record.getPositionId() == null
                    || record.getPositionDirection() == null) continue;
            // 重复发送过滤：已标记处理中的券跳过（防止连续 tick 重复触发）
            if (experienceGiftRecordService.isProcessing(record.getId())) continue;

            boolean expiredHit     = false;
            boolean profitLimitHit = false;
            boolean blastHit       = false;
            boolean stopProfitHit  = false;
            boolean stopLossHit    = false;

            // 1. 过期检查：当前时间 >= 到期时间则强制平仓
            if (record.getExpireAt() != null
                    && System.currentTimeMillis() >= record.getExpireAt().getTime()) {
                expiredHit = true;
            }

            // 2. 盈利触顶检查（系统设置的 autoClosePrice）
            if (record.getPositionDirection() == ContractOrderDirection.BUY) {
                profitLimitHit = currentPrice.compareTo(record.getAutoClosePrice()) >= 0;
            } else if (record.getPositionDirection() == ContractOrderDirection.SELL) {
                profitLimitHit = currentPrice.compareTo(record.getAutoClosePrice()) <= 0;
            }

            // 3. 用户止盈/止损检查
            if (!expiredHit && !profitLimitHit) {
                boolean hasStopProfit = record.getStopProfitPrice() != null
                        && record.getStopProfitPrice().compareTo(BigDecimal.ZERO) > 0;
                boolean hasStopLoss = record.getStopLossPrice() != null
                        && record.getStopLossPrice().compareTo(BigDecimal.ZERO) > 0;
                if (record.getPositionDirection() == ContractOrderDirection.BUY) {
                    // 多单：价格 >= 止盈触发；价格 <= 止损触发
                    if (hasStopProfit && currentPrice.compareTo(record.getStopProfitPrice()) >= 0) stopProfitHit = true;
                    if (!stopProfitHit && hasStopLoss && currentPrice.compareTo(record.getStopLossPrice()) <= 0) stopLossHit = true;
                } else if (record.getPositionDirection() == ContractOrderDirection.SELL) {
                    // 空单：价格 <= 止盈触发；价格 >= 止损触发
                    if (hasStopProfit && currentPrice.compareTo(record.getStopProfitPrice()) <= 0) stopProfitHit = true;
                    if (!stopProfitHit && hasStopLoss && currentPrice.compareTo(record.getStopLossPrice()) >= 0) stopLossHit = true;
                }
            }

            // 4. 爆仓检查（仅在未触发过期/盈利/止盈止损时才查仓位）
            MemberContractPosition pos = null;
            if (!expiredHit && !profitLimitHit && !stopProfitHit && !stopLossHit) {
                pos = memberContractPositionService.findOne(record.getPositionId());
                if (pos != null && pos.getStatus() == ContractPositionStatus.STARTED) {
                    pos.setCurrentPrice(currentPrice);
                    BigDecimal currentLoss = BigDecimal.ZERO.subtract(pos.getCurrentProfit());
                    if (currentLoss.compareTo(record.getAmount()) >= 0) {
                        blastHit = true;
                    }
                }
            } else if (stopProfitHit || stopLossHit) {
                // 止盈/止损需要仓位数据计算 pnl
                pos = memberContractPositionService.findOne(record.getPositionId());
            }

            // 无触发条件，跳过
            if (!expiredHit && !profitLimitHit && !blastHit && !stopProfitHit && !stopLossHit) continue;

            // 立即从缓存移除，防止当前 process() 循环或下一个 tick 重复触发
            experienceGiftRecordService.removeFromCache(record.getId());
            // 标记为处理中（双重防护：万一缓存移除与下一 tick 存在竞态，processingIds 作为兜底过滤）
            experienceGiftRecordService.markProcessing(record.getId());

            // 构建平仓消息
            ExperienceGiftCloseMsg msg = new ExperienceGiftCloseMsg();
            msg.setRecordId(record.getId());
            msg.setPositionId(record.getPositionId());
            msg.setMemberId(record.getMemberId());
            msg.setCoinSymbol(record.getCoinSymbol());

            if (expiredHit) {
                // 到期强平：按当前市价结算，需查仓位计算实际 pnl
                msg.setCloseReason(ExperienceGiftCloseReason.EXPIRED);
                msg.setClosePrice(currentPrice);
                if (pos == null) {
                    pos = memberContractPositionService.findOne(record.getPositionId());
                }
                if (pos != null) {
                    BigDecimal pnl;
                    if (pos.getMoneyType() == ContractMoneyType.COIN) {
                        pnl = currentPrice.subtract(pos.getOpenPrice()).multiply(pos.getCurrentPosition());
                    } else {
                        pnl = currentPrice.subtract(pos.getOpenPrice())
                                .multiply(pos.getCurrentPosition())
                                .multiply(pos.getShareNumber())
                                .divide(pos.getOpenPrice(), 8, RoundingMode.HALF_UP);
                    }
                    if (pos.getDirection() == ContractOrderDirection.SELL) {
                        pnl = BigDecimal.ZERO.subtract(pnl);
                    }
                    msg.setPnl(pnl);
                }
            } else if (profitLimitHit) {
                // 盈利触顶：按 autoClosePrice 结算，pnl = maxProfit
                msg.setCloseReason(ExperienceGiftCloseReason.PROFIT_LIMIT);
                msg.setClosePrice(record.getAutoClosePrice());
                msg.setPnl(record.getMaxProfit());
            } else if (stopProfitHit || stopLossHit) {
                // 用户止盈/止损：按当前价结算，计算 pnl
                msg.setCloseReason(stopProfitHit ? ExperienceGiftCloseReason.STOP_PROFIT : ExperienceGiftCloseReason.STOP_LOSS);
                msg.setClosePrice(currentPrice);
                if (pos != null) {
                    BigDecimal pnl;
                    if (pos.getMoneyType() == ContractMoneyType.COIN) {
                        pnl = currentPrice.subtract(pos.getOpenPrice()).multiply(pos.getCurrentPosition());
                    } else {
                        pnl = currentPrice.subtract(pos.getOpenPrice())
                                .multiply(pos.getCurrentPosition())
                                .multiply(pos.getShareNumber())
                                .divide(pos.getOpenPrice(), 8, RoundingMode.HALF_UP);
                    }
                    if (pos.getDirection() == ContractOrderDirection.SELL) {
                        pnl = BigDecimal.ZERO.subtract(pnl);
                    }
                    msg.setPnl(pnl);
                }
            } else {
                // 爆仓：亏损等于体验金面额
                msg.setCloseReason(ExperienceGiftCloseReason.BLASTED);
                msg.setClosePrice(currentPrice);
                msg.setPnl(BigDecimal.ZERO.subtract(record.getAmount()));
            }

            kafkaTemplate.send("swap-experience-gift-close", JSON.toJSONString(msg));
            logger.info("体验金仓位触发平仓 recordId={}, symbol={}, reason={}, price={}",
                    record.getId(), this.symbol, msg.getCloseReason(), msg.getClosePrice());
        }

        // 每次 tick 检查完毕后清理超过 1 分钟的处理中标记，防止内存持续增长
        experienceGiftRecordService.cleanExpiredProcessing();
    }

    /**
     * 处理开仓限价委托订单
     */
    public void processOpenEntrustList(CoinThumb thumb) {
        synchronized (openOrderList) {
        	//logger.info("openOrderList.size()={}", openOrderList.size());
            Iterator<ContractOrderEntrust> orderIterator = openOrderList.iterator();
            while ((orderIterator.hasNext())) {
                ContractOrderEntrust order = orderIterator.next();
                if(order.getEntrustPrice()==null) {
            		orderIterator.remove();
            		continue;
            	}
                if(order.getDirection() == ContractOrderDirection.BUY) { // 多单
                	if(order.getEntrustPrice().compareTo(thumb.getClose()) >= 0) {
	                    if(order.getEntrustPrice().compareTo(thumb.getLow()) > 0 || (order.getEntrustPrice().compareTo(thumb.getClose()) == 0 && order.getTriggerCounter() > 50)) {
	                    	logger.info("[买入开多]触发成交开仓多单委托订单, 实时价/委托价：" + thumb.getClose() + "/" + order.getEntrustPrice() + ", Order: " + JSON.toJSONString(order));
	                    	kafkaTemplate.send("swap-order-entrust-deal", JSON.toJSONString(order));
	                    	orderIterator.remove();
	                        this.removeFromMap(order);
	                    } else {
	                    	order.setTriggerCounter(order.getTriggerCounter()+1);
	                    	logger.info("TriggerCounter={}", order.getTriggerCounter());
	                    }
                	}
                }else{ // 空单
                    if(order.getEntrustPrice().compareTo(thumb.getClose()) <= 0) {
                    	if(order.getEntrustPrice().compareTo(thumb.getHigh()) < 0 || (order.getEntrustPrice().compareTo(thumb.getClose()) == 0 && order.getTriggerCounter() > 50)) {
	                        logger.info("[卖出开空]触发成交开仓空单委托订单, 实时价/委托价：" + thumb.getClose() + "/" + order.getEntrustPrice() + ", Order: " + JSON.toJSONString(order));
	                        kafkaTemplate.send("swap-order-entrust-deal", JSON.toJSONString(order));
	                        orderIterator.remove();
	                        this.removeFromMap(order);
                    	} else {
	                    	order.setTriggerCounter(order.getTriggerCounter()+1);
	                    	logger.info("TriggerCounter={}", order.getTriggerCounter());
	                    }
                    }
                }
            }
        }
    }

    /**
     * 处理平仓限价委托订单
     */
    public void processCloseEntrustList(CoinThumb thumb) {
        synchronized (closeOrderList) {
            Iterator<ContractOrderEntrust> orderIterator = closeOrderList.iterator();
            while ((orderIterator.hasNext())) {
                ContractOrderEntrust order = orderIterator.next();
                if(order.getEntrustPrice()==null) {
            		orderIterator.remove();
            		continue;
            	}
                if(order.getDirection() == ContractOrderDirection.BUY){
                    if(order.getEntrustPrice().compareTo(thumb.getClose()) >= 0) {
                    	if(order.getEntrustPrice().compareTo(thumb.getLow()) > 0 || (order.getEntrustPrice().compareTo(thumb.getClose()) == 0 && order.getTriggerCounter() > 50)) {
	                        logger.info("[买入平空]触发成交平仓空单委托订单, 实时价/委托价：" + thumb.getClose() + "/" + order.getEntrustPrice() + ", Order: " + JSON.toJSONString(order));
	                        kafkaTemplate.send("swap-order-entrust-deal", JSON.toJSONString(order));
	                        orderIterator.remove();
	                        this.removeFromMap(order);
                    	} else {
	                    	order.setTriggerCounter(order.getTriggerCounter()+1);
	                    	logger.info("TriggerCounter={}", order.getTriggerCounter());
	                    }
                    }
                }else{
                    if(order.getEntrustPrice().compareTo(thumb.getClose()) <= 0) {
                    	if(order.getEntrustPrice().compareTo(thumb.getHigh()) < 0 || (order.getEntrustPrice().compareTo(thumb.getClose()) == 0 && order.getTriggerCounter() > 50)) {
	                        logger.info("[卖出平多]触发成交平仓空单委托订单, 实时价/委托价：" + thumb.getClose() + "/" + order.getEntrustPrice() + ", Order: " + JSON.toJSONString(order));
	                        kafkaTemplate.send("swap-order-entrust-deal", JSON.toJSONString(order));
	                        orderIterator.remove();
	                        this.removeFromMap(order);
                    	} else {
	                    	order.setTriggerCounter(order.getTriggerCounter()+1);
	                    	logger.info("TriggerCounter={}", order.getTriggerCounter());
	                    }
                    }
                }
            }
        }
    }

    /**
     * 处理计划委托开仓委托订单
     * @param newPrice
     */
    public void processOpenSpotEntrustList(BigDecimal newPrice) {
        synchronized (openOrderSpotList) {
            Iterator<ContractOrderEntrust> orderIterator = openOrderSpotList.iterator();
            while ((orderIterator.hasNext())) {
                ContractOrderEntrust order = orderIterator.next();
                // 这里分为两种可能性计划委托
                // 1、用户委托时，委托的触发价格大于当时的价格，到现在这个时候，触发价格小于行情价，说明价格涨到触发价，该触发了 （开多时相当于止盈，开空时相当于止损）
                // 2、用户委托时，委托的触发价格小于当时的价格，到现在这个时候，触发价格大于行情价，说明价格跌到触发价，该触发了 （开多时相当于止损，开空时相当于止盈）
                if((order.getTriggerPrice().compareTo(order.getCurrentPrice()) >= 0 && order.getTriggerPrice().compareTo(newPrice) <= 0)
                        || (order.getTriggerPrice().compareTo(order.getCurrentPrice()) <= 0 && order.getTriggerPrice().compareTo(newPrice) >= 0)) {

                    //MemberContractWallet wallet = memberContractWalletService.findByMemberIdAndContractCoin(order.getMemberId(), contractCoin);
                    //BigDecimal leverage = order.getDirection() == ContractOrderDirection.BUY ? wallet.getUsdtBuyLeverage() : wallet.getUsdtSellLeverage();
                    //BigDecimal leverage = wallet.getUsdtBuyLeverage();
                    // 检查保证金是否足够开单
                    // 0、计算当前开仓订单所需保证金
                    // 合约张数 * 合约面值 / 合约倍数 （该计算方式适合于金本位，即USDT作为保证金模式）
                    //BigDecimal principalAmount = order.getVolume().multiply(contractCoin.getShareNumber().divide(leverage, 8, BigDecimal.ROUND_HALF_DOWN));
                    //BigDecimal principalAmount = order.getPrincipalAmount();
                    // 1、计算开仓手续费(合约张数 * 合约面值 * 开仓费率）
                    //BigDecimal openFee = order.getVolume().multiply(contractCoin.getShareNumber()).multiply(contractCoin.getOpenFee());
                    //BigDecimal openFee = order.getOpenFee();

                    // 当前账户为逐仓模式时，只需比较可用余额
                    /*if (wallet.getUsdtPattern() == ContractOrderPattern.FIXED) {
                        if (principalAmount.add(openFee).compareTo(wallet.getUsdtBalance()) > 0) {
                            logger.info("计划委托失败，余额不足：" + order.getMemberId() + " - " + order.getId() + " - " + order.getContractOrderEntrustId());
                            continue;
                        }
                    }
                    // 全仓模式，需要计算空仓和多仓总权益
                    if (wallet.getUsdtPattern() == ContractOrderPattern.CROSSED) {
                        // 计算金本位权益（多仓 + 空仓）
                        BigDecimal usdtTotalProfitAndLoss = BigDecimal.ZERO;
                        // 多仓计算方法：（当前价格 / 开仓均价 - 1）* （可用仓位 + 冻结仓位） * 合约面值
                        if (wallet.getUsdtBuyPrice().compareTo(BigDecimal.ZERO) > 0 && wallet.getUsdtBuyPosition().compareTo(BigDecimal.ZERO) > 0) {
                            usdtTotalProfitAndLoss = usdtTotalProfitAndLoss.add(newPrice.divide(wallet.getUsdtBuyPrice(), 8, BigDecimal.ROUND_HALF_DOWN).subtract(BigDecimal.ONE).multiply(wallet.getUsdtBuyPosition().add(wallet.getUsdtFrozenBuyPosition())).multiply(wallet.getUsdtShareNumber()));
                        }

                        // 空仓计算方法：（1 - 当前价格 / 开仓均价）* （可用仓位 + 冻结仓位） * 合约面值
                        if (wallet.getUsdtSellPrice().compareTo(BigDecimal.ZERO) > 0 && wallet.getUsdtSellPosition().compareTo(BigDecimal.ZERO) > 0) {
                            usdtTotalProfitAndLoss = usdtTotalProfitAndLoss.add(BigDecimal.ONE.subtract(newPrice.divide(wallet.getUsdtSellPrice(), 8, BigDecimal.ROUND_HALF_DOWN)).multiply(wallet.getUsdtSellPosition().add(wallet.getUsdtFrozenSellPosition())).multiply(wallet.getUsdtShareNumber()));
                        }

                        // 加上仓位保证金
                        usdtTotalProfitAndLoss = usdtTotalProfitAndLoss.add(wallet.getUsdtBuyPrincipalAmount());
                        // 经过上面的计算，可能会得到一个正值，也可能得到一个负值，如果是负值，因为是全仓模式，就需要用余额减去该数值，然后计算余额是否足够
                        if (usdtTotalProfitAndLoss.compareTo(BigDecimal.ZERO) < 0) {
                            if (principalAmount.add(openFee).compareTo(wallet.getUsdtBalance().add(usdtTotalProfitAndLoss)) > 0) {
                                logger.info("计划委托失败：" + order.getMemberId() + " - " + order.getId() + " - " + order.getContractOrderEntrustId());
                                continue;
                            }
                        } else { // 如果持仓权益是正值，则直接跟可用余额比较即可
                            if (principalAmount.add(openFee).compareTo(wallet.getUsdtBalance()) > 0) {
                                logger.info("计划委托失败：" + order.getMemberId() + " - " + order.getId() + " - " + order.getContractOrderEntrustId());
                                continue;
                            }
                        }
                    }*/
                	// 触发委托
                	kafkaTemplate.send("swap-order-spot-entrust-open", JSON.toJSONString(order));
                	orderIterator.remove();
                    this.removeFromMap(order);
                }
            }
        }
    }

    /**
     * 处理计划委托平仓委托订单
     * @param newPrice
     */
    public void processCloseSpotEntrustList(BigDecimal newPrice) {
        //logger.info("计划委托平仓处理开始：{}", newPrice);
        synchronized (closeOrderSpotList) {
            Iterator<ContractOrderEntrust> orderIterator = closeOrderSpotList.iterator();

            //logger.info("计划委托平仓处理订单列表, size: {}", closeOrderSpotList.size());
            while ((orderIterator.hasNext())) {
                ContractOrderEntrust order = orderIterator.next();
                // 这里分为两种可能性计划委托
                // 1、用户委托时，委托的触发价格大于当时的价格，到现在这个时候，触发价格小于行情价，说明价格涨到触发价，该触发了 （买入平空时相当于止损，卖出平多时相当于止盈）
                // 2、用户委托时，委托的触发价格小于当时的价格，到现在这个时候，触发价格大于行情价，说明价格跌到触发价，该触发了 （买入平空时相当于止盈，卖出平多时相当于止损）
                //logger.info("计划委托平仓判断处理. {} - {} - {}", order.getProfitPrice(), order.getCurrentPrice(), newPrice);
                boolean profitTriggered = order.getProfitPrice()!=null && order.getProfitPrice().compareTo(BigDecimal.ZERO)>0 
                		&& ((order.getProfitPrice().compareTo(order.getCurrentPrice()) >= 0 && order.getProfitPrice().compareTo(newPrice) <= 0)
                        || (order.getProfitPrice().compareTo(order.getCurrentPrice()) <= 0 && order.getProfitPrice().compareTo(newPrice) >= 0));
                boolean lossTriggered = order.getLossPrice()!=null && order.getLossPrice().compareTo(BigDecimal.ZERO)>0 
                		&& ((order.getLossPrice().compareTo(order.getCurrentPrice()) >= 0 && order.getLossPrice().compareTo(newPrice) <= 0)
                        || (order.getLossPrice().compareTo(order.getCurrentPrice()) <= 0 && order.getLossPrice().compareTo(newPrice) >= 0));
                //logger.info("profitTriggered={}, lossTriggered={}", profitTriggered, lossTriggered);
                if (profitTriggered || lossTriggered) {
                    //if(!redisLock.lockPosition(order.getPositionId()))
                	//	continue;
                    logger.info("触发计划：计划委托平仓处理. {} - {} - {}", order.getTriggerPrice(), order.getCurrentPrice(), newPrice);
                    //MemberContractWallet wallet = memberContractWalletService.findByMemberIdAndContractCoin(order.getMemberId(), contractCoin);
                    if(profitTriggered)
                    	order.setCutType(1);
                    else
                    	order.setCutType(0);
                    order.setTriggerPrice(newPrice);
                    
                    kafkaTemplate.send("swap-order-spot-entrust-close", JSON.toJSONString(order));
                    orderIterator.remove();
                    this.removeFromMap(order);
                }
            }
        }
    }
    
    public BigDecimal cancelCloseOrdersByPositionId(Long positionId) {
    	List<ContractOrderEntrust> closingList = contractOrderEntrustService.queryAllEntrustLimitClosingOrdersByPositionId(positionId);
    	BigDecimal releasedPosition = BigDecimal.ZERO;
    	for(ContractOrderEntrust item : closingList) {
    		releasedPosition = releasedPosition.add(cancelContractOrderEntrust(item, false));
        }
    	// MARKET_PRICE close orders are processed immediately and never enter the in-memory list,
    	// but if processCloseOrder threw (e.g. NPE), the order is left stuck as ENTRUST_ING.
    	// Cancel them directly: mark CANCELLED + thaw the frozen position volume.
    	List<ContractOrderEntrust> marketList = contractOrderEntrustService.queryAllEntrustMarketClosingOrdersByPositionId(positionId);
    	for (ContractOrderEntrust item : marketList) {
    	    contractOrderEntrustService.updateStatusAndDealTime(item.getId(),
    	            ContractOrderEntrustStatus.ENTRUST_CANCEL, DateUtil.getTimeMillis());
    	    memberContractPositionService.thawPosition(positionId, item.getVolume());
    	    releasedPosition = releasedPosition.add(item.getVolume());
    	    logger.warn("[cancelCloseOrders] recovered stuck MARKET_PRICE close order id={} positionId={} volume={}",
    	            item.getId(), positionId, item.getVolume());
    	}
    	return releasedPosition;
    }
    
    public BigDecimal cancelCloseOrdersByPositionId(Long positionId, BigDecimal volume) {
    	List<ContractOrderEntrust> closingList = contractOrderEntrustService.queryAllEntrustLimitClosingOrdersByPositionId(positionId);
    	BigDecimal releasedPosition = BigDecimal.ZERO;
    	for(ContractOrderEntrust item : closingList) {
    		releasedPosition = releasedPosition.add(cancelContractOrderEntrust(item, false));
    		if(releasedPosition.compareTo(volume)>=0)
    			break;
        }
    	return releasedPosition;
    }
    
    public List<ContractOrderEntrust> findRunningCutOrders(Long positionId) {
    	List<ContractOrderEntrust> cutOrderList = new ArrayList<ContractOrderEntrust>();

    	// 普通止盈止损单从 closeOrderSpotList 中查找
    	Iterator<ContractOrderEntrust> orderIterator = closeOrderSpotList.iterator();
        while ((orderIterator.hasNext())) {
            ContractOrderEntrust order = orderIterator.next();
            if(order.getPositionId().longValue() == positionId.longValue()) {
            	if(order.getVolume().compareTo(BigDecimal.ZERO)==0) {
            		cutOrderList.add(0, order);
            	} else {
            		cutOrderList.add(order);
            	}
            }
        }

        // 体验金止盈止损单存在 orderListMap 中，单独补充
        for (List<ContractOrderEntrust> memberOrders : orderListMap.values()) {
            for (ContractOrderEntrust order : memberOrders) {
                if (order.getExperienceRecordId() != null
                        && order.getIsCut() == 1
                        && order.getPositionId() != null
                        && order.getPositionId().longValue() == positionId.longValue()
                        && order.getType() == ContractOrderType.SPOT_LIMIT
                        && order.getEntrustType() == ContractOrderEntrustType.CLOSE) {
                    cutOrderList.add(order);
                }
            }
        }

        return cutOrderList;
    }
    
    public List<ContractOrderEntrust> findRunningOpenOrdersByMemberId(long memberId) {
    	List<ContractOrderEntrust> list = new ArrayList<ContractOrderEntrust>();
    	Iterator<ContractOrderEntrust> spotOrderIterator = openOrderSpotList.iterator();
        while ((spotOrderIterator.hasNext())) {
            ContractOrderEntrust order = spotOrderIterator.next();
            if(order.getMemberId().longValue() == memberId)
            	list.add(order);
        }
        Iterator<ContractOrderEntrust> orderIterator = openOrderList.iterator();
        while ((orderIterator.hasNext())) {
            ContractOrderEntrust order = orderIterator.next();
            if(order.getMemberId().longValue() == memberId)
            	list.add(order);
        }
        return list;
    }

    /**
     * 同步仓位信息
     */
    public void syncMemberPosition() {
        // 同步最新用户仓位
        synchronized (memberContractWalletList) {
            memberContractWalletList = memberContractWalletService.findAllNeedSync(contractCoin);
            logger.info(contractCoin.getSymbol() + "=====>同步最新用户仓位信息, size: " + memberContractWalletList.size());
        }
    }

    /**
     * 爆仓检查
     */
    public void processBlastCheck(BigDecimal newPrice) {
        // 同步最新用户仓位
        synchronized (memberContractWalletList){
            Iterator<MemberContractWallet> walletIterator = memberContractWalletList.iterator();
            while(walletIterator.hasNext()) {
                MemberContractWallet wallet = walletIterator.next();
                if(wallet.getUsdtPattern() == ContractOrderPattern.FIXED) { // 逐仓
                    // 计算当前价格是否爆仓 - 多单计算
                    if(wallet.getUsdtBuyPrice().compareTo(BigDecimal.ZERO) > 0) {
                        BigDecimal buyPL = newPrice.divide(wallet.getUsdtBuyPrice(), 8, BigDecimal.ROUND_DOWN).subtract(BigDecimal.ONE).multiply(wallet.getUsdtBuyPosition().add(wallet.getUsdtFrozenBuyPosition())).multiply(wallet.getUsdtShareNumber());
                        // 保证金率低于最低保证金率，则爆仓
                        if (buyPL.compareTo(BigDecimal.ZERO) < 0) {
                            // 计算保证金率
                            // （合约收益 + 保证金数量 - 平仓手续费）/ （（可用持仓 + 冻结持仓）* 合约面值） < coin.maintenanceMarginRate
                            BigDecimal minNeedPrinc = wallet.getUsdtBuyPosition().add(wallet.getUsdtFrozenBuyPosition()).multiply(wallet.getUsdtShareNumber()).divide(wallet.getUsdtBuyLeverage(), 8, BigDecimal.ROUND_DOWN);
                            BigDecimal closeFee = wallet.getUsdtBuyPosition().add(wallet.getUsdtFrozenBuyPosition()).multiply(wallet.getUsdtShareNumber()).multiply(contractCoin.getCloseFee());

                            // 当前保证金率 = （合约收益 + 保证金 - 平仓手续费） / 合约最低需要保证金
                            BigDecimal curRate = buyPL.add(wallet.getUsdtBuyPrincipalAmount()).subtract(closeFee).divide(minNeedPrinc, 8, BigDecimal.ROUND_DOWN);
                            if (curRate.compareTo(contractCoin.getMaintenanceMarginRate()) <= 0) {
                                // 爆多单处理
                                blastBuy(wallet, newPrice);
                                // 发送逐仓多单爆仓邮件通知
                                sendPositionBlastEmailByWallet(wallet, "BUY");
                                // 更新一下用户钱包
                                MemberContractWallet queryWallet = memberContractWalletService.findOne(wallet.getId());
                                memberContractWalletList.set(memberContractWalletList.indexOf(wallet), queryWallet);
                            }
                        }
                    }

                    // 计算当前价格是否爆仓 - 空单计算
                    if(wallet.getUsdtSellPrice().compareTo(BigDecimal.ZERO) > 0) {
                        BigDecimal sellPL = BigDecimal.ONE.subtract(newPrice.divide(wallet.getUsdtSellPrice(), 8, BigDecimal.ROUND_DOWN)).multiply(wallet.getUsdtSellPosition().add(wallet.getUsdtFrozenSellPosition())).multiply(wallet.getUsdtShareNumber());
                        // 保证金率低于最低保证金率，则爆仓
                        if (sellPL.compareTo(BigDecimal.ZERO) < 0) {
                            // 计算保证金率
                            // （合约收益 + 保证金数量）/ （（可用持仓 + 冻结持仓）* 合约面值） < coin.maintenanceMarginRate
                            // 需要的保证金 = （可用空仓位 + 冻结空仓位 ）* 合约面值 / 合约倍数
                            BigDecimal minNeedPrinc = wallet.getUsdtSellPosition().add(wallet.getUsdtFrozenSellPosition()).multiply(wallet.getUsdtShareNumber()).divide(wallet.getUsdtSellLeverage());
                            BigDecimal closeFee = wallet.getUsdtSellPosition().add(wallet.getUsdtFrozenSellPosition()).multiply(wallet.getUsdtShareNumber()).multiply(contractCoin.getCloseFee());
                            // 当前保证金率 = （合约收益 + 保证金 - 平仓手续费） / 合约最低需要保证金
                            BigDecimal curRate = sellPL.add(wallet.getUsdtSellPrincipalAmount()).subtract(closeFee).divide(minNeedPrinc, 8, BigDecimal.ROUND_DOWN);
                            if (curRate.compareTo(contractCoin.getMaintenanceMarginRate()) <= 0) {
                                // 爆空单处理
                                blastSell(wallet, newPrice);
                                // 发送逐仓空单爆仓邮件通知
                                sendPositionBlastEmailByWallet(wallet, "SELL");
                                // 更新一下用户钱包
                                MemberContractWallet queryWallet = memberContractWalletService.findOne(wallet.getId());
                                memberContractWalletList.set(memberContractWalletList.indexOf(wallet), queryWallet);
                            }
                        }
                    }
                }else{ // 全仓
                    // 计算当前价格是否爆仓
                    // 计算多单收益
                    BigDecimal buyPL = BigDecimal.ZERO;
                    if(wallet.getUsdtBuyPrice().compareTo(BigDecimal.ZERO) > 0){
                        buyPL = newPrice.divide(wallet.getUsdtBuyPrice(), 8, BigDecimal.ROUND_DOWN).subtract(BigDecimal.ONE).multiply(wallet.getUsdtBuyPosition().add(wallet.getUsdtFrozenBuyPosition())).multiply(wallet.getUsdtShareNumber());
                    }
                    // 计算空单收益
                    BigDecimal sellPL = BigDecimal.ZERO;
                    if(wallet.getUsdtSellPrice().compareTo(BigDecimal.ZERO) > 0){
                        sellPL = BigDecimal.ONE.subtract(newPrice.divide(wallet.getUsdtSellPrice(), 8, BigDecimal.ROUND_DOWN)).multiply(wallet.getUsdtSellPosition().add(wallet.getUsdtFrozenSellPosition())).multiply(wallet.getUsdtShareNumber());
                    }
                    // 多单与空单收益之和
                    // 多空总收益为负数，并且多仓保证金 + 空仓保证金 + USDT余额都不足以支付亏损时爆仓
                    if(buyPL.add(sellPL).compareTo(BigDecimal.ZERO) < 0) {

                        BigDecimal buyPositionValue = wallet.getUsdtBuyPosition().add(wallet.getUsdtFrozenBuyPosition()).multiply(wallet.getUsdtShareNumber()).divide(wallet.getUsdtBuyLeverage(), 8, BigDecimal.ROUND_DOWN);
                        BigDecimal sellPositionValue = wallet.getUsdtSellPosition().add(wallet.getUsdtFrozenSellPosition()).multiply(wallet.getUsdtShareNumber()).divide(wallet.getUsdtSellLeverage(), 8, BigDecimal.ROUND_DOWN);

                        BigDecimal buyCloseFee = wallet.getUsdtBuyPosition().add(wallet.getUsdtFrozenBuyPosition()).multiply(wallet.getUsdtShareNumber()).multiply(contractCoin.getCloseFee());
                        BigDecimal sellCloseFee = wallet.getUsdtSellPosition().add(wallet.getUsdtFrozenSellPosition()).multiply(wallet.getUsdtShareNumber()).multiply(contractCoin.getCloseFee());

                        // 全仓保证金率 （多单收益 + 空单收益 + 多单保证金 + 空单保证金 + 账户可用USDT余额 + 账户冻结USDT金额 - 平多手续费 - 平空手续费）/ （多单最低保证金 + 空单最低保证金）
                        //BigDecimal curRate = buyPL.add(sellPL).add(wallet.getUsdtBuyPrincipalAmount()).add(wallet.getUsdtSellPrincipalAmount()).add(wallet.getUsdtBalance()).add(wallet.getUsdtFrozenBalance()).subtract(buyCloseFee).subtract(sellCloseFee).divide(buyPositionValue.add(sellPositionValue), 8, BigDecimal.ROUND_DOWN);
                        BigDecimal curRate = buyPL.add(sellPL).add(wallet.getUsdtBuyPrincipalAmount()).add(wallet.getUsdtSellPrincipalAmount()).add(wallet.getUsdtBalance()).add(wallet.getUsdtFrozenBalance()).divide(buyPositionValue.add(sellPositionValue), 8, BigDecimal.ROUND_DOWN);
                        //logger.info("爆仓检查 - 保证金率："+curRate + "，维持保证金率：" + contractCoin.getMaintenanceMarginRate());
                        if(curRate.compareTo(contractCoin.getMaintenanceMarginRate()) <= 0) {
                            logger.info("爆仓检查 - 保证金率："+curRate);
                            // 爆 多单 和 空单
                            blastAll(wallet, newPrice);
                            // 更新钱包
                            MemberContractWallet queryWallet = memberContractWalletService.findOne(wallet.getId());
                            memberContractWalletList.set(memberContractWalletList.indexOf(wallet), queryWallet);
                        }
                    }
                }
            }
        }
    }

    // 爆多单
    public void blastBuy(MemberContractWallet wallet, BigDecimal price) {
        logger.info("多仓爆仓，用户ID：{}，爆仓执行价：{}", wallet.getMemberId(), price);
        // 计算收益
        BigDecimal buyPL = price.divide(wallet.getUsdtBuyPrice(), 8, BigDecimal.ROUND_DOWN).subtract(BigDecimal.ONE).multiply(wallet.getUsdtBuyPosition().add(wallet.getUsdtFrozenBuyPosition())).multiply(wallet.getUsdtShareNumber());
        BigDecimal closeFee = wallet.getUsdtBuyPosition().add(wallet.getUsdtFrozenBuyPosition()).multiply(wallet.getUsdtShareNumber()).multiply(contractCoin.getCloseFee());
        // 新建合约委托单
        ContractOrderEntrust orderEntrust = new ContractOrderEntrust();
        orderEntrust.setContractId(contractCoin.getId()); // 合约ID
        orderEntrust.setMemberId(wallet.getMemberId()); // 用户ID
        orderEntrust.setSymbol(contractCoin.getSymbol()); // 交易对符号
        orderEntrust.setBaseSymbol(contractCoin.getSymbol().split("/")[1]); // 基币/结算币
        orderEntrust.setCoinSymbol(contractCoin.getSymbol().split("/")[0]); // 币种符号
        orderEntrust.setDirection(ContractOrderDirection.SELL); // 平仓方向：平空/平多
        orderEntrust.setContractOrderEntrustId(GeneratorUtil.getOrderId("CE"));
        orderEntrust.setVolume(wallet.getUsdtBuyPosition().add(wallet.getUsdtFrozenBuyPosition())); // 平仓张数
        orderEntrust.setTradedVolume(wallet.getUsdtBuyPosition().add(wallet.getUsdtFrozenBuyPosition())); // 已交易数量
        orderEntrust.setTradedPrice(price); // 成交价格
        orderEntrust.setPrincipalUnit("USDT"); // 保证金单位
        //orderEntrust.setPrincipalAmount(BigDecimal.ZERO); // 保证金数量
        orderEntrust.setPrincipalAmount(wallet.getUsdtBuyPrincipalAmount()); // 保证金数量
        orderEntrust.setCreateTime(DateUtil.getTimeMillis()); // 开仓时间
        orderEntrust.setType(ContractOrderType.MARKET_PRICE);
        orderEntrust.setTriggerPrice(BigDecimal.ZERO); // 触发价
        orderEntrust.setEntrustPrice(BigDecimal.ZERO); // 委托价格
        orderEntrust.setEntrustType(ContractOrderEntrustType.CLOSE); // 平仓
        orderEntrust.setTriggeringTime(0L); // 触发时间，暂时无效
        orderEntrust.setShareNumber(wallet.getUsdtShareNumber());
        orderEntrust.setProfitAndLoss(buyPL); // 盈亏（仅平仓计算）
        orderEntrust.setPatterns(wallet.getUsdtPattern()); // 仓位模式
        //orderEntrust.setCloseFee(closeFee);
        orderEntrust.setCloseFee(BigDecimal.ZERO);
        orderEntrust.setCurrentPrice(price);
        orderEntrust.setIsBlast(1); // 是爆仓单
        orderEntrust.setStatus(ContractOrderEntrustStatus.ENTRUST_SUCCESS); // 委托状态：委托中
        orderEntrust.setUsdtOpenPrice(wallet.getUsdtBuyPrice());
        orderEntrust.setUsdtOpenTime(wallet.getUsdtBuyTime());
        orderEntrust.setLeverage(wallet.getUsdtBuyLeverage().intValue());
        ContractOrderEntrust retObj = contractOrderEntrustService.save(orderEntrust);
        if(retObj != null) {
            logger.info("多仓，清空仓位");
            // 更新平台收益
            contractCoinService.increaseTotalProfit(contractCoin.getId(), BigDecimal.ZERO.subtract(buyPL));

            // 统一处理用户盈亏
            handlePl(wallet.getMemberId(), buyPL);

            // 更新平台平仓手续费
            //contractCoinService.increaseTotalCloseFee(contractCoin.getId(), closeFee);
            // 统一处理手续费
            //handleFee(wallet.getMemberId(), closeFee);
            // 多仓清空（可用仓位 + 冻结仓位），多仓保证金清空
            memberContractWalletService.blastBuy(wallet.getId());
            //memberContractWalletService.increaseUsdtBalance(wallet.getId(), wallet.getUsdtBuyPrincipalAmount().add(buyPL).subtract(closeFee));
            memberContractWalletService.increaseUsdtBalance(wallet.getId(), wallet.getUsdtBuyPrincipalAmount().add(buyPL));
            //addTransaction(wallet.getMemberId(), BigDecimal.ZERO.subtract(closeFee), TransactionType.CONTRACT_FEE);
            
            wallet.setUsdtBuyPosition(BigDecimal.ZERO);
            wallet.setUsdtFrozenBuyPosition(BigDecimal.ZERO);
            wallet.setUsdtBuyPrincipalAmount(BigDecimal.ZERO);
            // 撤销所有卖出平多单（包含计划委托）
            List<ContractOrderEntrust> closingList = contractOrderEntrustService.queryAllEntrustClosingOrdersByContractCoin(wallet.getMemberId(), contractCoin.getId(), ContractOrderDirection.SELL);
            for(ContractOrderEntrust item : closingList) {
                cancelContractOrderEntrust(item, true);
            }
        }
    }

    // 爆空单
    public void blastSell(MemberContractWallet wallet, BigDecimal price) {
        logger.info("空仓爆仓，用户ID：{}，爆仓执行价：{}", wallet.getMemberId(), price);
        BigDecimal sellPL = BigDecimal.ONE.subtract(price.divide(wallet.getUsdtSellPrice(), 8, BigDecimal.ROUND_DOWN)).multiply(wallet.getUsdtSellPosition().add(wallet.getUsdtFrozenSellPosition())).multiply(wallet.getUsdtShareNumber());
        BigDecimal closeFee = wallet.getUsdtSellPosition().add(wallet.getUsdtFrozenSellPosition()).multiply(wallet.getUsdtShareNumber()).multiply(contractCoin.getCloseFee());
        // 新建合约委托单
        ContractOrderEntrust orderEntrust = new ContractOrderEntrust();
        orderEntrust.setContractId(contractCoin.getId()); // 合约ID
        orderEntrust.setMemberId(wallet.getMemberId()); // 用户ID
        orderEntrust.setSymbol(contractCoin.getSymbol()); // 交易对符号
        orderEntrust.setBaseSymbol(contractCoin.getSymbol().split("/")[1]); // 基币/结算币
        orderEntrust.setCoinSymbol(contractCoin.getSymbol().split("/")[0]); // 币种符号
        orderEntrust.setDirection(ContractOrderDirection.BUY); // 平仓方向：平空/平多
        orderEntrust.setContractOrderEntrustId(GeneratorUtil.getOrderId("CE"));
        orderEntrust.setVolume(wallet.getUsdtSellPosition().add(wallet.getUsdtFrozenSellPosition())); // 平仓张数
        orderEntrust.setTradedVolume(wallet.getUsdtSellPosition().add(wallet.getUsdtFrozenSellPosition())); // 已交易数量
        orderEntrust.setTradedPrice(price); // 成交价格
        orderEntrust.setPrincipalUnit("USDT"); // 保证金单位
        orderEntrust.setPrincipalAmount(wallet.getUsdtSellPrincipalAmount()); // 保证金数量
        orderEntrust.setCreateTime(DateUtil.getTimeMillis()); // 开仓时间
        orderEntrust.setType(ContractOrderType.MARKET_PRICE);
        orderEntrust.setTriggerPrice(BigDecimal.ZERO); // 触发价
        orderEntrust.setEntrustPrice(BigDecimal.ZERO); // 委托价格
        orderEntrust.setEntrustType(ContractOrderEntrustType.CLOSE); // 平仓
        orderEntrust.setTriggeringTime(0L); // 触发时间，暂时无效
        orderEntrust.setShareNumber(wallet.getUsdtShareNumber());
        orderEntrust.setProfitAndLoss(sellPL); // 盈亏（保证金 - 平仓手续费）
        orderEntrust.setPatterns(wallet.getUsdtPattern()); // 仓位模式
        //orderEntrust.setCloseFee(closeFee);
        orderEntrust.setCloseFee(BigDecimal.ZERO);
        orderEntrust.setCurrentPrice(price);
        orderEntrust.setIsBlast(1); // 是爆仓单
        orderEntrust.setStatus(ContractOrderEntrustStatus.ENTRUST_SUCCESS); // 委托状态：委托成功
        orderEntrust.setUsdtOpenPrice(wallet.getUsdtSellPrice());
        orderEntrust.setUsdtOpenTime(wallet.getUsdtSellTime());
        orderEntrust.setLeverage(wallet.getUsdtBuyLeverage().intValue());
        ContractOrderEntrust retObj = contractOrderEntrustService.save(orderEntrust);
        if(retObj != null) {
            logger.info("空仓，清空仓位");
            // 更新平台收益
            contractCoinService.increaseTotalProfit(contractCoin.getId(), BigDecimal.ZERO.subtract(sellPL));
            // 统一处理用户盈亏
            handlePl(wallet.getMemberId(), sellPL);
            // 更新平台平仓手续费
            //contractCoinService.increaseTotalCloseFee(contractCoin.getId(), closeFee);
            // 统一处理手续费
            //handleFee(wallet.getMemberId(), closeFee);

            // 空仓清空（可用仓位 + 冻结仓位），空仓保证金清空
            memberContractWalletService.blastSell(wallet.getId());
            //memberContractWalletService.increaseUsdtBalance(wallet.getId(), wallet.getUsdtSellPrincipalAmount().add(sellPL).subtract(closeFee));
            memberContractWalletService.increaseUsdtBalance(wallet.getId(), wallet.getUsdtSellPrincipalAmount().add(sellPL));
            //addTransaction(wallet.getMemberId(), BigDecimal.ZERO.subtract(closeFee), TransactionType.CONTRACT_FEE);
            // 更新钱包
            wallet.setUsdtSellPosition(BigDecimal.ZERO);
            wallet.setUsdtFrozenSellPosition(BigDecimal.ZERO);
            wallet.setUsdtSellPrincipalAmount(BigDecimal.ZERO);

            // 查询所有平空单
            // 撤销所有卖出平多单（包含计划委托）
            List<ContractOrderEntrust> closingList = contractOrderEntrustService.queryAllEntrustClosingOrdersByContractCoin(wallet.getMemberId(), contractCoin.getId(), ContractOrderDirection.BUY);
            for(ContractOrderEntrust item : closingList) {
                cancelContractOrderEntrust(item, true);
            }
        }
    }

    // 爆全仓
    public void blastAll(MemberContractWallet wallet, BigDecimal price) {
        logger.info("全仓爆仓，用户ID：{}，执行价：{}", wallet.getMemberId(), price);
        
        if(!redisLock.lockWalletForClose(wallet.getId()))
    		return;

        try {
	        net.sf.json.JSONObject jsonObject = new net.sf.json.JSONObject();
	        net.sf.json.JSONArray positionJsonArray = new net.sf.json.JSONArray();
	        String contractName = this.coinSymbol + "-" + this.baseSymbol;

	        // 平多
	        BigDecimal buyPosition = wallet.getUsdtBuyPosition().add(wallet.getUsdtFrozenBuyPosition());
	        if(buyPosition.compareTo(BigDecimal.ZERO)>0) {
	        	blastBuy(wallet, price);
	        	net.sf.json.JSONObject buyPos = new net.sf.json.JSONObject();
	        	buyPos.put("contractName", contractName);
	        	buyPos.put("volume", buyPosition);
	        	buyPos.put("leverage", wallet.getUsdtBuyLeverage());
	        	buyPos.put("direction", 0); // 看涨
	        	positionJsonArray.add(buyPos);
	        }

	        // 平空
	        BigDecimal sellPosition = wallet.getUsdtSellPosition().add(wallet.getUsdtFrozenSellPosition());
	        if(sellPosition.compareTo(BigDecimal.ZERO)>0) {
	        	blastSell(wallet, price);
	        	net.sf.json.JSONObject sellPos = new net.sf.json.JSONObject();
	        	sellPos.put("contractName", contractName);
	        	sellPos.put("volume", sellPosition);
	        	sellPos.put("leverage", wallet.getUsdtSellLeverage());
	        	sellPos.put("direction", 1); // 看跌
	        	positionJsonArray.add(sellPos);
	        }

	        //如果爆仓后余额小于0，恢复为0
	        MemberContractWallet newWallet = memberContractWalletService.findOne(wallet.getId());
	        if(newWallet.getUsdtBalance().compareTo(BigDecimal.ZERO) < 0) {
	        	memberContractWalletService.increaseUsdtBalance(wallet.getId(), BigDecimal.ZERO.subtract(newWallet.getUsdtBalance()));
	        	contractCoinService.increaseTotalProfit(contractCoin.getId(), newWallet.getUsdtBalance());
	        }

	        jsonObject.put("positions", positionJsonArray);
	        logger.info("jsonObject={}", jsonObject.toString());
	        // 24小时内同一用户只发一次爆仓通知，防止行情每次推送都重复触发
	        if (redisManager == null || redisManager.tryMarkBlastEmail(wallet.getMemberId())) {
	            memberService.notifyByEmail(wallet.getMemberId(), NotifyType.BLAST, jsonObject);
	        } else {
	            logger.info("blast email skipped (already sent within 24h), memberId={}", wallet.getMemberId());
	        }

        } catch(Exception e) {
    		logger.error(e.getMessage(), e.getCause());
    	}
    	finally {
    		redisLock.unlockWalletForClose(wallet.getId());
    	}

        // 清空可用余额
        //memberContractWalletService.decreaseUsdtBalance(wallet.getId(), wallet.getUsdtBalance());

        // 更新平台收益
        //contractCoinService.increaseTotalProfit(contractCoin.getId(), wallet.getUsdtBalance());

        // 统一处理用户盈亏(全部亏光)
        //handlePl(wallet.getMemberId(), BigDecimal.ZERO.subtract(wallet.getUsdtBalance()));
    }
    
    public void cancelOpenOrdersByMemberId(Long memberId) {
    	List<ContractOrderEntrust> orderList = contractOrderEntrustService.findOpenByMemberIdAndContractId(memberId, contractCoin.getId());
    	for(ContractOrderEntrust order : orderList) {
    		cancelContractOrderEntrust(order, false);
    	}
    }
    
    public int modifyContractOrderEntrust(ContractOrderEntrust modifiedOrder, BigDecimal profitPrice, BigDecimal lossPrice) {
    	BigDecimal currentPrice = nowPrice;
    	if(modifiedOrder.getCloseType() == CloseType.CUT) {
    		if(modifiedOrder.getDirection() == ContractOrderDirection.BUY) {
            	if(profitPrice.compareTo(BigDecimal.ZERO)>0 && profitPrice.compareTo(currentPrice)>=0) {
            		return 1;
            	}
            	if(lossPrice.compareTo(BigDecimal.ZERO)>0 && lossPrice.compareTo(currentPrice)<=0) {
            		return 2;
            	}
            } else {
            	if(profitPrice.compareTo(BigDecimal.ZERO)>0 && profitPrice.compareTo(currentPrice)<=0) {
            		return 3;
            	}
            	if(lossPrice.compareTo(BigDecimal.ZERO)>0 && lossPrice.compareTo(currentPrice)>=0) {
            		return 4;
            	}
            }

    		// 普通止盈止损单：在 closeOrderSpotList 中更新
    		synchronized(closeOrderSpotList) {
    			Iterator<ContractOrderEntrust> orderIterator = closeOrderSpotList.iterator();
                while ((orderIterator.hasNext())) {
                	ContractOrderEntrust order = orderIterator.next();
                	if (order.getId().longValue() == modifiedOrder.getId().longValue()) {
                		order.setProfitPrice(profitPrice);
                		order.setLossPrice(lossPrice);
                		order.setCurrentPrice(currentPrice);
                		modifiedOrder.setProfitPrice(profitPrice);
                		modifiedOrder.setLossPrice(lossPrice);
                		modifiedOrder.setCurrentPrice(currentPrice);
                		contractOrderEntrustService.save(modifiedOrder);
                    	return 0;
                	}
                }
    		}

    		// 体验金止盈止损单：在 orderListMap 中更新
    		if (modifiedOrder.getExperienceRecordId() != null) {
    			for (List<ContractOrderEntrust> memberOrders : orderListMap.values()) {
    				for (ContractOrderEntrust order : memberOrders) {
    					if (order.getId().longValue() == modifiedOrder.getId().longValue()) {
    						order.setProfitPrice(profitPrice);
    						order.setLossPrice(lossPrice);
    						order.setCurrentPrice(currentPrice);
    						modifiedOrder.setProfitPrice(profitPrice);
    						modifiedOrder.setLossPrice(lossPrice);
    						modifiedOrder.setCurrentPrice(currentPrice);
    						contractOrderEntrustService.save(modifiedOrder);
    						return 0;
    					}
    				}
    			}
    		}
    	} else if (modifiedOrder.getEntrustType() == ContractOrderEntrustType.OPEN) {
    		if(modifiedOrder.getType() == ContractOrderType.SPOT_LIMIT && modifiedOrder.getEntrustPrice().compareTo(BigDecimal.ZERO)==0) {
    			return 9;
    		}
    		if(modifiedOrder.getDirection() == ContractOrderDirection.SELL) {
            	if(profitPrice.compareTo(BigDecimal.ZERO)>0 && profitPrice.compareTo(modifiedOrder.getEntrustPrice())>=0)
            		return 5;
            	if(lossPrice.compareTo(BigDecimal.ZERO)>0 && lossPrice.compareTo(modifiedOrder.getEntrustPrice())<=0)
            		return 6;
            } else {
            	if(profitPrice.compareTo(BigDecimal.ZERO)>0 && profitPrice.compareTo(modifiedOrder.getEntrustPrice())<=0)
            		return 7;
            	if(lossPrice.compareTo(BigDecimal.ZERO)>0 && lossPrice.compareTo(modifiedOrder.getEntrustPrice())>=0)
            		return 8;
            }
    		if(modifiedOrder.getType() == ContractOrderType.SPOT_LIMIT) {
    			synchronized(openOrderSpotList) {
        			Iterator<ContractOrderEntrust> orderIterator = openOrderSpotList.iterator();
                    while ((orderIterator.hasNext())) {
                    	ContractOrderEntrust order = orderIterator.next();
                    	if (order.getId().longValue() == modifiedOrder.getId().longValue()) {
                    		order.setProfitPrice(profitPrice);
                    		order.setLossPrice(lossPrice);
                    		//order.setCurrentPrice(currentPrice);
                    		
                    		modifiedOrder.setProfitPrice(profitPrice);
                    		modifiedOrder.setLossPrice(lossPrice);
                    		//modifiedorder.setCurrentPrice(currentPrice);
                    		contractOrderEntrustService.save(modifiedOrder);
                        	return 0;
                    	}
                    }
        		}
    		} else if(modifiedOrder.getType() == ContractOrderType.LIMIT_PRICE) {
    			synchronized(openOrderList) {
        			Iterator<ContractOrderEntrust> orderIterator = openOrderList.iterator();
                    while ((orderIterator.hasNext())) {
                    	ContractOrderEntrust order = orderIterator.next();
                    	if (order.getId().longValue() == modifiedOrder.getId().longValue()) {
                    		order.setProfitPrice(profitPrice);
                    		order.setLossPrice(lossPrice);
                    		//order.setCurrentPrice(currentPrice);
                    		
                    		modifiedOrder.setProfitPrice(profitPrice);
                    		modifiedOrder.setLossPrice(lossPrice);
                    		//modifiedorder.setCurrentPrice(currentPrice);
                    		contractOrderEntrustService.save(modifiedOrder);
                        	return 0;
                    	}
                    }
        		}
    		}
    	}
    	return 10;
    }

    // 撤销订单（委托单）
    public BigDecimal cancelContractOrderEntrust(ContractOrderEntrust orderEntrust, boolean isBlast) {
        //if(!redisLock.lockOrder(orderEntrust.getId()))
    	//	return BigDecimal.ZERO;
    	
    	// 查找订单
        LinkedList<ContractOrderEntrust> list = null;
        if(orderEntrust.getEntrustType() == ContractOrderEntrustType.OPEN) {
            if(orderEntrust.getType() == ContractOrderType.SPOT_LIMIT) {
                list = this.openOrderSpotList;
                logger.info("取消开仓订单 - 计划委托类型");
            }else{
                logger.info("取消开仓订单 - 非计划委托类型");
                list = this.openOrderList;
            }
        }else{
            if(orderEntrust.getType() == ContractOrderType.SPOT_LIMIT) {
                list = this.closeOrderSpotList;
                logger.info("取消平仓订单 - 计划委托类型");
            }else{
                list = this.closeOrderList;
                logger.info("取消平仓订单 - 非计划委托类型");
            }
        }
        BigDecimal releasedPosition = BigDecimal.ZERO;
        synchronized (list) {
            logger.info("撤销订单列表大小：{}", list.size());
            Iterator<ContractOrderEntrust> orderIterator = list.iterator();
            while ((orderIterator.hasNext())) {
                ContractOrderEntrust order = orderIterator.next();
                logger.info("撤销订单ID：{}, 对比 开仓订单ID: {}", orderEntrust.getId(), order.getId());
                if (order.getId().longValue() == orderEntrust.getId().longValue()) {
                    logger.info("撤销订单，在引擎中发现订单，予以撤销");
                    // 更新数据库
                    if(orderEntrust.getEntrustType() == ContractOrderEntrustType.OPEN) {
                        // 开仓单，撤单需要解冻USDT
                    	releasedPosition = releasedPosition.add(orderEntrust.getVolume());
                    	if(orderEntrust.getType() == ContractOrderType.LIMIT_PRICE || orderEntrust.getType() == ContractOrderType.MARKET_PRICE) {
                            // 限价或市价单，需要解冻保证金 | 如果是爆仓单，则无需解冻保证金
                    		if(orderEntrust.getFollowId() != null && followWalletService != null) {
                    		    // 跟单订单：保证金从 follow_wallet 扣的，归还到 follow_wallet
                    		    followWalletService.thawMargin(orderEntrust.getMemberId(), contractCoin, orderEntrust.getPrincipalAmount().add(orderEntrust.getOpenFee()));
                    		} else {
                    		    userPurseService.thawMargin(orderEntrust.getMemberId(), contractCoin, orderEntrust.getPrincipalAmount().add(orderEntrust.getOpenFee()));
                    		}
                            if(!isBlast) {
                                
                            }
                        }else{
                            // 计划委托单，什么都不用做，因为计划委托单没有冻结任何资产
                        }
                    }else{
                        if(orderEntrust.getType() == ContractOrderType.LIMIT_PRICE || orderEntrust.getType() == ContractOrderType.MARKET_PRICE) {
                            // 平仓单，撤单需要解冻仓位Position
                        	//if(orderEntrust.getVolume().compareTo(BigDecimal.ZERO)>0) {
                        	memberContractPositionService.thawPosition(order.getPositionId(), orderEntrust.getVolume());
                        	releasedPosition = releasedPosition.add(orderEntrust.getVolume());
                        	//}
                        }else{
                            // 计划委托单，什么都不用做，因为计划委托单没有冻结任何资产
                        }
                    }
                    contractOrderEntrustService.updateStatusAndDealTime(orderEntrust.getId(), ContractOrderEntrustStatus.ENTRUST_CANCEL, DateUtil.getTimeMillis());
                    orderIterator.remove();
                    this.removeFromMap(order);
                    updateTradingAccount(orderEntrust);
                    
                    break;
                }
            }
        }
        //redisLock.unlockOrder(orderEntrust.getId());
        return releasedPosition;
    }

    /**
     * 初始化Thumb
     */
    public void initializeThumb() {
        this.thumb = new CoinThumb();
        this.thumb.setChg(BigDecimal.ZERO);                 // 变化百分比（例：4%）
        this.thumb.setChange(BigDecimal.ZERO);              // 变化金额
        this.thumb.setOpen(BigDecimal.ZERO);                // 开盘价
        this.thumb.setClose(BigDecimal.ZERO);               // 收盘价
        this.thumb.setHigh(BigDecimal.ZERO);                // 最高价
        this.thumb.setLow(BigDecimal.ZERO);                 // 最低价
        this.thumb.setBaseUsdRate(BigDecimal.valueOf(6.42)); // 基础USDT汇率
        this.thumb.setLastDayClose(BigDecimal.ZERO);        // 前日收盘价
        this.thumb.setSymbol(this.symbol);                  // 交易对符号
        this.thumb.setUsdRate(BigDecimal.valueOf(6.42));     // USDT汇率
        this.thumb.setZone(0);                              // 交易区
        this.thumb.setVolume(BigDecimal.ZERO);              // 成交量
        this.thumb.setTurnover(BigDecimal.ZERO);            // 成交额
    }

    public void handleCoinThumb() {
        for (MarketHandler storage : handlers) {
            storage.handleTrade(symbol, thumb);
        }
    }

    public void handleKLineStorage(KLine kLine) {
        for (MarketHandler storage : handlers) {
            storage.handleKLine(symbol, kLine);
        }
    }
    public void handlePositionChange(Long memberId) {
        for (MarketHandler storage : handlers) {
            storage.handlePositionChange(memberId);
        }
    }
    public BigDecimal getAdjustedNowPrice(ContractOrderDirection direction) {
    	BigDecimal adjustedPrice = this.nowPrice;
        if (direction == ContractOrderDirection.BUY) { // 买入平空，滑点计算，更低价格
            if (contractCoin.getSpreadType() == 1) { // 滑点类型：百分比
            	adjustedPrice = this.nowPrice.add(this.nowPrice.multiply(contractCoin.getSpread())); // 已当前价成交（或滑点价成交）
            } else { // 滑点类型：固定额
            	adjustedPrice = this.nowPrice.add(contractCoin.getSpread());
            }
        } else { // 卖出，滑点计算，做空，更低价格成交
            if (contractCoin.getSpreadType() == 1) { // 滑点类型：百分比
            	adjustedPrice = this.nowPrice.subtract(this.nowPrice.multiply(contractCoin.getSpread())); // 已当前价成交（或滑点价成交）
            } else { // 滑点类型：固定额
            	adjustedPrice = this.nowPrice.subtract(contractCoin.getSpread());
            }
        }
        return adjustedPrice;
    }
    /**
     * 未订单生成交易价格
     * @param order
     * @param limitPrice
     */
    public void genTradedPriceForOrder(ContractOrderEntrust order, boolean limitPrice) {
    	BigDecimal tradedPrice = BigDecimal.ZERO;
    	BigDecimal openPrice = getAdjustedNowPrice(order.getDirection());
    	if(order.getType() == ContractOrderType.MARKET_PRICE) {
    		tradedPrice = openPrice;
    	} else if(order.getType() == ContractOrderType.LIMIT_PRICE) {
    		if(limitPrice) {
    			tradedPrice = order.getEntrustPrice();
    		} else {
	    		if (order.getDirection() == ContractOrderDirection.BUY) {
	        		if(order.getEntrustPrice().compareTo(openPrice) > 0) {
	        			tradedPrice = openPrice;
	        			order.setIsLimitPrice(1);
	        		} else
	        			tradedPrice = order.getEntrustPrice();
	        	} else {
	        		if(order.getEntrustPrice().compareTo(openPrice) < 0) {
	        			tradedPrice = openPrice;
	        			order.setIsLimitPrice(1);
	        		} else
	        			tradedPrice = order.getEntrustPrice();
	        	}
    		}
    	}
    	order.setTradedPrice(tradedPrice);
    }
    // 获取交易对符号
    public String getSymbol() { return this.symbol; }
    // 获取币种符号
    public String getCoinSymbol() { return this.coinSymbol; }
    // 获取基币符号
    public String getBaseSymbol() { return this.baseSymbol; }
    // 获取交易对最新报价
    public BigDecimal getNowPrice() { return this.nowPrice; }
    // 获取交易对最新行情
    public CoinThumb getThumb() { return this.thumb; }
    // 获取最新成交明细
    public List<ContractTrade> getLastedTradeList() { return this.lastedTradeList; }
    // 获取盘口数据
    public TradePlate getTradePlate(ContractOrderDirection direction){
        if(direction == ContractOrderDirection.BUY){
            return buyTradePlate;
        }
        else{
            return sellTradePlate;
        }
    }
    // 设置合约币种服务
    public void setContractCoinService(ContractCoinService contractCoinService) { this.contractCoinService = contractCoinService; }
    // 设置合约订单委托服务
    public void setContractOrderEntrustService(ContractOrderEntrustService contractOrderEntrustService){ this.contractOrderEntrustService = contractOrderEntrustService; }
    // 添加处理者
    public void addHandler(MarketHandler storage) {
        handlers.add(storage);
    }
    public void setExchangePushJob(ExchangePushJob job) { this.exchangePushJob = job; }

    public void setMemberTransactionService(MemberTransactionService memberTransactionService) {
        this.memberTransactionService = memberTransactionService;
    }
    
    public void setMemberService(MemberService memberService) {
        this.memberService = memberService;
    }

    public void setMemberContractWalletService(MemberContractWalletService memberContractWalletService) {
        this.memberContractWalletService = memberContractWalletService;
    }
    
    public void setMemberContractPositionService(MemberContractPositionService memberContractPositionService) {
        this.memberContractPositionService = memberContractPositionService;
    }
    
    public void setUserPurseService(UserPurseService userPurseService) {
    	this.userPurseService = userPurseService;
    }

    public void setFollowWalletService(FollowWalletService followWalletService) {
        this.followWalletService = followWalletService;
    }
    
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    /**
     * 更新合约交易对信息
     * @param coin
     */
    public void updateContractCoin(ContractCoin coin) {
        synchronized (contractCoin) {
            contractCoin = coin;
        }
    }


    /**
     * 定点爆仓
     * @param newPrice
     */
    public void refreshBlastPrice(BigDecimal newPrice) {
        logger.info("========>>>>>>定点爆仓，爆仓执行价：{}", newPrice);
        // 尚未启动
        if(!this.isStarted) return;

        //this.process(newPrice);
    }

    /**
     * 获取引擎中所有用户持仓信息
     * @return
     */
    public List<MemberContractWallet> getMemberContractWalletList() {
        return this.memberContractWalletList;
    }

    /**
     * 处理手续费
     */
    public void handleFee(Long memberId, BigDecimal fee){
        logger.info("处理手续费，用户：{}, 手续费：{}", memberId, fee);
    }
    
    private void addTransaction(Long memberId, BigDecimal amount, TransactionType type) {
    	MemberTransaction memberTransaction = new MemberTransaction();
        memberTransaction.setFee(BigDecimal.ZERO);
        memberTransaction.setAmount(amount);
        memberTransaction.setMemberId(memberId);
        memberTransaction.setSymbol(contractCoin.getSymbol().split("/")[1]);
        memberTransaction.setType(type);
        memberTransaction.setCreateTime(DateUtil.getCurrentDate());
        memberTransaction.setRealFee("0");
        memberTransaction.setDiscountFee("0");
        memberTransaction = memberTransactionService.save(memberTransaction);
    }

    /**
     * 处理盈亏
     */
    public void handlePl(Long memberId, BigDecimal pL){

        MemberTransaction memberTransaction = new MemberTransaction();
        memberTransaction.setFee(BigDecimal.ZERO);
        memberTransaction.setAmount(pL);
        memberTransaction.setMemberId(memberId);
        memberTransaction.setSymbol(contractCoin.getSymbol().split("/")[1]);
        memberTransaction.setType(pL.compareTo(BigDecimal.ZERO) > 0 ? TransactionType.CONTRACT_PROFIT : TransactionType.CONTRACT_LOSS);
        memberTransaction.setCreateTime(DateUtil.getCurrentDate());
        memberTransaction.setRealFee("0");
        memberTransaction.setDiscountFee("0");
        memberTransaction = memberTransactionService.save(memberTransaction);

        logger.info("处理盈亏，用户：{}, 实际盈亏：{}", memberId, pL);
    }
    
    public void setTradingAccountMonitor(TradingAccountMonitor tradingAccountMonitor) {
    	this.tradingAccountMonitor = tradingAccountMonitor;
    }

    public void setKafkaTemplate(KafkaTemplate<String, String> kafkaTemplate) {
    	this.kafkaTemplate = kafkaTemplate;
    }

    public void setRedisManager(RedisManager redisManager) {
        this.redisManager = redisManager;
    }

    /**
     * 发送逐仓爆仓邮件，24小时内同一用户只发一次
     *
     * @param wallet    爆仓钱包
     * @param direction 方向：BUY=多单爆仓，SELL=空单爆仓
     */
    private void sendPositionBlastEmailByWallet(MemberContractWallet wallet, String direction) {
        try {
            // 24小时内同一用户只发一次逐仓爆仓通知
            if (redisManager != null && !redisManager.tryMarkBlastPositionEmail(wallet.getMemberId())) {
                logger.info("position blast email skipped (already sent within 24h), memberId={}", wallet.getMemberId());
                return;
            }
            net.sf.json.JSONObject jsonObject = new net.sf.json.JSONObject();
            net.sf.json.JSONArray positionJsonArray = new net.sf.json.JSONArray();
            net.sf.json.JSONObject positionJsonObject = new net.sf.json.JSONObject();
            // BUY=看涨(0) SELL=看跌(1)，与 ContractOrderDirection.ordinal() 对齐
            positionJsonObject.put("direction", "BUY".equals(direction) ? 0 : 1);
            positionJsonObject.put("contractName", this.coinSymbol + "-" + this.baseSymbol);
            positionJsonObject.put("volume", "BUY".equals(direction)
                    ? wallet.getUsdtBuyPosition().add(wallet.getUsdtFrozenBuyPosition())
                    : wallet.getUsdtSellPosition().add(wallet.getUsdtFrozenSellPosition()));
            positionJsonObject.put("leverage", "BUY".equals(direction)
                    ? wallet.getUsdtBuyLeverage()
                    : wallet.getUsdtSellLeverage());
            positionJsonArray.add(positionJsonObject);
            jsonObject.put("positions", positionJsonArray);
            memberService.notifyByEmail(wallet.getMemberId(), NotifyType.POSITION_BLAST, jsonObject);
        } catch (Exception e) {
            logger.error("send position blast email error, memberId={}", wallet.getMemberId(), e);
        }
    }

    public void setExperienceGiftRecordService(ExperienceGiftRecordService experienceGiftRecordService) {
        this.experienceGiftRecordService = experienceGiftRecordService;
    }

    public void updateTradingAccount(ContractOrderEntrust order) {
    	//tradingAccountMonitor.updateAccount(memberId);
		kafkaTemplate.send("trading-account-change", order.getMemberId()+"");
    	if(order.getFollowId()!=null)
    		kafkaTemplate.send("follow-account-change", order.getMemberId()+"");
    }
    
    public void addToMap(ContractOrderEntrust order) {
    	if (!orderListMap.containsKey(order.getMemberId())) {
    		orderListMap.put(order.getMemberId(), new ArrayList<ContractOrderEntrust>());
    	}
    	List<ContractOrderEntrust> list = orderListMap.get(order.getMemberId());
    	for (ContractOrderEntrust existing : list) {
    		if (existing.getId().longValue() == order.getId().longValue()) {
    			logger.warn("addToMap 重复订单，跳过: orderId={}, memberId={}", order.getId(), order.getMemberId());
    			return;
    		}
    	}
    	list.add(order);
    }
    
    public void removeFromMap(ContractOrderEntrust orderEntrust) {
    	if (!orderListMap.containsKey(orderEntrust.getMemberId())) {
    		logger.info("用户map撤销订单ID：{}, 未找到用户ID: {}", orderEntrust.getId(), orderEntrust.getMemberId());
    		return;
    	}
    	List<ContractOrderEntrust> list = orderListMap.get(orderEntrust.getMemberId());
    	Iterator<ContractOrderEntrust> orderIterator = list.iterator();
    	while ((orderIterator.hasNext())) {
            ContractOrderEntrust order = orderIterator.next();
            logger.info("用户map撤销订单ID：{}, 对比 开仓订单ID: {}", orderEntrust.getId(), order.getId());
            if (order.getId().longValue() == orderEntrust.getId().longValue()) {
            	orderIterator.remove();
            	logger.info("用户map撤销成功");
            }
    	}
    }
    
    public static List<ContractOrderEntrust> getListByMemberId(Long memberId) {
    	if (!orderListMap.containsKey(memberId)) {
    		return new ArrayList<ContractOrderEntrust>();
    	}
    	return orderListMap.get(memberId);
    }

    /**
     * 更新钱包
     * @param walletId
     */
    public void memberWalletChange(Long walletId) {
    	entityManager.clear();
        synchronized (memberContractWalletList) {
            boolean hasWallet = false;
            Iterator<MemberContractWallet> walletIterator = memberContractWalletList.iterator();
            while(walletIterator.hasNext()) {
                MemberContractWallet wallet = walletIterator.next();
                if(wallet.getId().longValue() == walletId.longValue()) {
                    hasWallet = true;
                    logger.info("更新钱包，用户：{}, 内容：{}", wallet.getMemberId(), JSON.toJSONString(wallet));
                    // 更新钱包
                    MemberContractWallet queryResult = memberContractWalletService.findOne(walletId);
                    logger.info("更新钱包后，用户：{}, 内容：{}", wallet.getMemberId(), JSON.toJSONString(queryResult));
                    memberContractWalletList.set(memberContractWalletList.indexOf(wallet), queryResult);
                    
                    //推送仓位发生变化
                    //handlePositionChange(wallet.getMemberId());
                    break;
                }
            }
            // 找不到，则添加
            if(!hasWallet) {
                MemberContractWallet wallet = memberContractWalletService.findOne(walletId);
                if(wallet != null) {
                    logger.info("新增用户钱包，用户：{}, 内容：{}", wallet.getMemberId(), JSON.toJSONString(wallet));
                    memberContractWalletList.add(wallet);
                }
            }
        }
    }
}
