package com.spot.service;

import com.alibaba.fastjson.JSON;
import com.spot.dto.mq.TradeRecord;
import com.spot.dto.mq.TradeResult;
import com.spot.entity.ConfigCoinSymbol;
import com.spot.entity.ConfigSymbol;
import com.spot.entity.ExOrder;
import com.spot.enums.OrderSide;
import com.spot.enums.OrderStatus;
import com.spot.enums.OrderType;
import com.spot.utils.Constant;
import com.spot.utils.FeeCalculator;
import com.spot.utils.PriceCache;
import com.spot.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 新匹配引擎 - 基于最新价格的撮合逻辑
 * 撮合结果通过 Kafka 发送到 SPOT_TRADE_{symbol} Topic
 *
 * @author jean
 * @date 2026-05-07
 */
@Component
@Slf4j
public class NewMatchingEngine {

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    @Autowired
    private ConfigSymbolService configSymbolService;

    @Autowired
    private ConfigCoinSymbolService configCoinSymbolService;

    @Autowired
    private ConfigSymbolSlippageService configSymbolSlippageService;

    @Value("${kafka.topic.trade:SPOT_TRADE_}")
    private String tradeTopic;

    /**
     * 新匹配引擎缓存 Map（按交易对分组）
     * Key: symbol_side（例如: BTCUSDT_BUY, BTCUSDT_SELL）
     * Value: 订单列表（买单价格降序，卖单价格升序）
     */
    private static final ConcurrentHashMap<String, List<ExOrder>> NEW_ENGINE_CACHE = new ConcurrentHashMap<>();

    /**
     * 处理新进入的 init 状态订单（状态0）
     *
     * @param newOrder 新订单
     * @param symbol   交易对
     * @return 撮合结果
     */
    public TradeResult processInitOrder(ExOrder newOrder, String symbol) {
        if (newOrder == null) {
            log.warn("订单为空，无法处理");
            return new TradeResult();
        }
        if (!OrderStatus.INIT.getCode().equals(newOrder.getStatus())) {
            log.warn("只能处理状态为0的init订单，当前状态: {} - OrderId: {}",
                    newOrder.getStatus(), newOrder.getId());
            return new TradeResult();
        }
        try {
            BigDecimal latestPrice = PriceCache.getPrice(symbol);
            if (latestPrice == null) {
                log.warn("交易对 [{}] 没有最新价格信息，订单挂单等待", symbol);
                return processOrderWithoutPrice(newOrder, symbol);
            }
            OrderType orderType = OrderType.fromCode(newOrder.getType());
            TradeResult result;
            if (OrderType.MARKET.equals(orderType)) {
                result = processMarketOrder(newOrder, symbol, latestPrice);
            } else {
                result = processLimitOrder(newOrder, symbol, latestPrice);
            }
            if (result.isMatched()) {
                log.info("新引擎匹配成功 - OrderId: {}, 匹配价格: {}", newOrder.getId(), latestPrice);
            }
            sendTradeResultToKafka(symbol, result);
            return result;
        } catch (Exception e) {
            log.error("新匹配引擎处理订单时发生错误 - OrderId: {}", newOrder.getId(), e);
            return new TradeResult();
        }
    }

    /**
     * 处理市价单 - 直接按最新价格成交
     *
     * @param marketOrder 市价订单
     * @param symbol      交易对
     * @param latestPrice 最新价格
     * @return 撮合结果
     */
    private TradeResult processMarketOrder(ExOrder marketOrder, String symbol, BigDecimal latestPrice) {
        TradeResult result = new TradeResult();
        result.setTakerOrder(marketOrder);
        result.setMatchTime(TimeUtils.now());

        BigDecimal tradeVolume;
        BigDecimal tradeAmount;
        BigDecimal refundVolume = BigDecimal.ZERO;

        if (OrderSide.BUY.getCode().equals(marketOrder.getSide())) {
            // 市价买单：volume 是金额，需要计算能买到的数量
            BigDecimal availableMoney = marketOrder.getVolume();

            // 1. 先用原始价格估算成交额，查询滑点并上调价格
            BigDecimal slippagePrice = applySlippage(symbol, latestPrice, availableMoney, true);

            BigDecimal totalVolume = availableMoney.divide(slippagePrice, 10, RoundingMode.DOWN);
            totalVolume = formatVolume(totalVolume, symbol);
            BigDecimal minTradeVolume = getMinTradeVolumeForSymbol(symbol);
            if (totalVolume.compareTo(minTradeVolume) < 0) {
                refundVolume = availableMoney;
                tradeVolume = BigDecimal.ZERO;
                tradeAmount = BigDecimal.ZERO;
                marketOrder.setStatus(OrderStatus.CANCELED.getCode());
            } else {
                BigDecimal tradeableUnits = totalVolume.divide(minTradeVolume, 0, RoundingMode.DOWN);
                tradeVolume = formatVolume(tradeableUnits.multiply(minTradeVolume), symbol);
                tradeAmount = tradeVolume.multiply(slippagePrice);
                BigDecimal remainingMoney = availableMoney.subtract(tradeAmount);
                if (remainingMoney.compareTo(minTradeVolume.multiply(slippagePrice)) < 0) {
                    refundVolume = remainingMoney;
                }
            }

            if (tradeVolume.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal fee = FeeCalculator.calculateOrderFee(marketOrder, slippagePrice, tradeVolume,
                        marketOrder.getFeeRateTaker(), true, configSymbolService, configCoinSymbolService);
                marketOrder.setFee(fee);
                marketOrder.setDealVolume(formatVolume(tradeVolume, symbol));
                marketOrder.setDealMoney(formatPrice(tradeAmount, symbol));
                marketOrder.setAvgPrice(slippagePrice);
                marketOrder.setStatus(OrderStatus.FILLED.getCode());
                result.setFullyFilled(refundVolume.compareTo(BigDecimal.ZERO) == 0);

                TradeRecord tradeRecord = buildTradeRecord(symbol, slippagePrice, tradeVolume, tradeAmount,
                        marketOrder, fee);
                result.setTradeRecord(tradeRecord);
                result.setMatched(true);
            } else {
                marketOrder.setStatus(OrderStatus.CANCELED.getCode());
            }
        } else {
            // 市价卖单：volume 是数量，计算成交金额
            BigDecimal totalVolume = marketOrder.getVolume();
            BigDecimal minTradeVolume = getMinTradeVolumeForSymbol(symbol);

            if (totalVolume.compareTo(minTradeVolume) < 0) {
                refundVolume = totalVolume;
                marketOrder.setStatus(OrderStatus.CANCELED.getCode());
            } else {
                BigDecimal tradeableUnits = totalVolume.divide(minTradeVolume, 0, RoundingMode.DOWN);
                tradeVolume = formatVolume(tradeableUnits.multiply(minTradeVolume), symbol);

                // 2. 先用原始价格估算成交额，查询滑点并下调价格
                BigDecimal estimatedAmount = tradeVolume.multiply(latestPrice);
                BigDecimal slippagePrice = applySlippage(symbol, latestPrice, estimatedAmount, false);

                tradeAmount = tradeVolume.multiply(slippagePrice);
                BigDecimal remainingVolume = totalVolume.subtract(tradeVolume);
                if (remainingVolume.compareTo(BigDecimal.ZERO) > 0) {
                    refundVolume = remainingVolume;
                }

                if (tradeVolume.compareTo(BigDecimal.ZERO) > 0) {
                    BigDecimal fee = FeeCalculator.calculateOrderFee(marketOrder, slippagePrice, tradeVolume,
                            marketOrder.getFeeRateTaker(), false, configSymbolService, configCoinSymbolService);
                    marketOrder.setFee(fee);
                    marketOrder.setDealVolume(formatVolume(tradeVolume, symbol));
                    marketOrder.setDealMoney(formatPrice(tradeAmount, symbol));
                    marketOrder.setAvgPrice(slippagePrice);
                    marketOrder.setStatus(OrderStatus.FILLED.getCode());
                    result.setFullyFilled(refundVolume.compareTo(BigDecimal.ZERO) == 0);

                    TradeRecord tradeRecord = buildTradeRecord(symbol, slippagePrice, tradeVolume, tradeAmount,
                            marketOrder, fee);
                    result.setTradeRecord(tradeRecord);
                    result.setMatched(true);
                } else {
                    marketOrder.setStatus(OrderStatus.CANCELED.getCode());
                }
            }
        }

        if (refundVolume.compareTo(BigDecimal.ZERO) > 0) {
            marketOrder.setRefundVolume(refundVolume);
        }
        marketOrder.setMtime(TimeUtils.now());
        return result;
    }

    /**
     * 根据成交额查询滑点配置，计算滑点后的成交价格
     * 买单价格上浮，卖单价格下浮
     *
     * @param symbol      交易对
     * @param basePrice   基准价格（最新价）
     * @param tradeAmount 预估成交额（用于匹配滑点区间）
     * @param isBuy       是否买单
     * @return 调整后的成交价格
     */
    private BigDecimal applySlippage(String symbol, BigDecimal basePrice, BigDecimal tradeAmount, boolean isBuy) {
        try {
            BigDecimal slippage = configSymbolSlippageService.getSlippage(symbol, tradeAmount);
            if (slippage == null || slippage.compareTo(BigDecimal.ZERO) == 0) {
                return basePrice;
            }
            if (isBuy) {
                // 买单：价格上浮，用户以更高价格买入
                BigDecimal slippagePrice = basePrice.multiply(BigDecimal.ONE.add(slippage));
                log.info("市价买单滑点 - Symbol: {}, 原价: {}, 滑点: {}, 调整后价格: {}",
                        symbol, basePrice, slippage, slippagePrice);
                return slippagePrice;
            } else {
                // 卖单：价格下浮，用户以更低价格卖出
                BigDecimal slippagePrice = basePrice.multiply(BigDecimal.ONE.subtract(slippage));
                log.info("市价卖单滑点 - Symbol: {}, 原价: {}, 滑点: {}, 调整后价格: {}",
                        symbol, basePrice, slippage, slippagePrice);
                return slippagePrice;
            }
        } catch (Exception e) {
            // 滑点查询异常，降级处理：不应用滑点，直接使用原始价格继续流程
            log.warn("滑点查询异常，跳过滑点处理，使用原始价格继续 - Symbol: {}, basePrice: {}, 原因: {}",
                    symbol, basePrice, e.getMessage());
            return basePrice;
        }
    }

    /**
     * 处理限价单 - 对比最新价格决定是否成交
     *
     * @param limitOrder  限价订单
     * @param symbol      交易对
     * @param latestPrice 最新价格
     * @return 撮合结果
     */
    private TradeResult processLimitOrder(ExOrder limitOrder, String symbol, BigDecimal latestPrice) {
        if (canLimitOrderExecute(limitOrder, latestPrice)) {
            return executeLimitOrderTrade(limitOrder, symbol, latestPrice);
        } else {
            return addLimitOrderToCache(limitOrder, symbol);
        }
    }

    /**
     * 判断限价单是否可以成交
     * 买单：订单价格 >= 当前价格；卖单：订单价格 <= 当前价格
     */
    private boolean canLimitOrderExecute(ExOrder limitOrder, BigDecimal latestPrice) {
        if (latestPrice == null || limitOrder.getPrice() == null) {
            return false;
        }
        String side = limitOrder.getSide();
        BigDecimal orderPrice = limitOrder.getPrice();
        if (OrderSide.BUY.getCode().equals(side)) {
            return orderPrice.compareTo(latestPrice) >= 0;
        } else if (OrderSide.SELL.getCode().equals(side)) {
            return orderPrice.compareTo(latestPrice) <= 0;
        }
        return false;
    }

    /** 将限价单加入缓存等待匹配 */
    private TradeResult addLimitOrderToCache(ExOrder limitOrder, String symbol) {
        String side = limitOrder.getSide();
        String cacheKey = symbol.toUpperCase() + Constant.CACHE_KEY_SEPARATOR + side;
        NEW_ENGINE_CACHE.compute(cacheKey, (key, orders) -> {
            if (orders == null) {
                orders = new ArrayList<>();
            }
            if (OrderSide.BUY.getCode().equals(side)) {
                insertBuyOrder(orders, limitOrder);
            } else if (OrderSide.SELL.getCode().equals(side)) {
                insertSellOrder(orders, limitOrder);
            }
            return orders;
        });
        limitOrder.setStatus(OrderStatus.NEW.getCode());
        limitOrder.setMtime(TimeUtils.now());
        TradeResult result = new TradeResult();
        result.setTakerOrder(limitOrder);
        return result;
    }

    /** 买单插入（价格降序，同价时间升序） */
    private void insertBuyOrder(List<ExOrder> orders, ExOrder newOrder) {
        int insertIndex = orders.size();
        for (int i = 0; i < orders.size(); i++) {
            ExOrder existing = orders.get(i);
            if (newOrder.getPrice().compareTo(existing.getPrice()) > 0 ||
                    (newOrder.getPrice().compareTo(existing.getPrice()) == 0 &&
                            newOrder.getCtime() != null && existing.getCtime() != null &&
                            newOrder.getCtime().compareTo(existing.getCtime()) <= 0)) {
                insertIndex = i;
                break;
            }
        }
        orders.add(insertIndex, newOrder);
    }

    /** 卖单插入（价格升序，同价时间升序） */
    private void insertSellOrder(List<ExOrder> orders, ExOrder newOrder) {
        int insertIndex = orders.size();
        for (int i = 0; i < orders.size(); i++) {
            ExOrder existing = orders.get(i);
            if (newOrder.getPrice().compareTo(existing.getPrice()) < 0 ||
                    (newOrder.getPrice().compareTo(existing.getPrice()) == 0 &&
                            newOrder.getCtime() != null && existing.getCtime() != null &&
                            newOrder.getCtime().compareTo(existing.getCtime()) <= 0)) {
                insertIndex = i;
                break;
            }
        }
        orders.add(insertIndex, newOrder);
    }

    /**
     * 执行限价单交易 - 按当前价格成交
     *
     * @param limitOrder  限价订单
     * @param symbol      交易对
     * @param latestPrice 最新价格
     * @return 撮合结果
     */
    private TradeResult executeLimitOrderTrade(ExOrder limitOrder, String symbol, BigDecimal latestPrice) {
        TradeResult result = new TradeResult();
        result.setTakerOrder(limitOrder);
        result.setMatchTime(TimeUtils.now());

        BigDecimal totalVolume = limitOrder.getVolume();
        if (isSmallRemainder(symbol, totalVolume, latestPrice)) {
            limitOrder.setStatus(OrderStatus.CANCELED.getCode());
            limitOrder.setMtime(TimeUtils.now());
            return result;
        }

        ConfigSymbol symbolConfig = configSymbolService.getConfigSymbol(symbol);
        BigDecimal tradeVolume;
        BigDecimal tradeAmount;
        BigDecimal refundVolume = BigDecimal.ZERO;

        if (OrderSide.BUY.getCode().equals(limitOrder.getSide())) {
            // 限价买单：按当前价格计算能买到的数量
            BigDecimal totalPrice = limitOrder.getPrice().multiply(limitOrder.getVolume());
            int volumePre = symbolConfig != null && symbolConfig.getVolumePre() != null
                    ? symbolConfig.getVolumePre() : Constant.DEFAULT_PRECISION;
            tradeVolume = formatVolume(totalPrice.divide(latestPrice, volumePre, RoundingMode.DOWN), symbol);
            if (tradeVolume.compareTo(totalVolume) > 0) {
                tradeVolume = formatVolume(totalVolume, symbol);
            }
            tradeAmount = tradeVolume.multiply(latestPrice);
            refundVolume = totalPrice.subtract(tradeAmount);
        } else {
            // 限价卖单：直接按下单数量成交
            tradeVolume = formatVolume(limitOrder.getVolume(), symbol);
            tradeAmount = tradeVolume.multiply(latestPrice);
        }

        BigDecimal fee = FeeCalculator.calculateOrderFee(limitOrder, latestPrice, tradeVolume,
                limitOrder.getFeeRateTaker(), OrderSide.BUY.getCode().equals(limitOrder.getSide()),
                configSymbolService, configCoinSymbolService);

        limitOrder.setFee(fee);
        limitOrder.setDealVolume(formatVolume(tradeVolume, symbol));
        limitOrder.setDealMoney(formatPrice(tradeAmount, symbol));
        limitOrder.setAvgPrice(latestPrice);
        limitOrder.setStatus(OrderStatus.FILLED.getCode());
        limitOrder.setMtime(TimeUtils.now());

        if (refundVolume.compareTo(BigDecimal.ZERO) > 0) {
            limitOrder.setRefundVolume(refundVolume);
            result.setFullyFilled(false);
        } else {
            result.setFullyFilled(true);
        }

        TradeRecord tradeRecord = buildTradeRecord(symbol, latestPrice, tradeVolume, tradeAmount,
                limitOrder, fee);
        result.setTradeRecord(tradeRecord);
        result.setMatched(true);
        return result;
    }

    /**
     * 没有价格信息时的处理：
     * 市价单：无法成交，直接取消并退还全部冻结金额，发送取消结果到 Kafka
     * 限价单：挂单等待，加入缓存
     */
    private TradeResult processOrderWithoutPrice(ExOrder order, String symbol) {
        if (order.getType() != null && order.getType().equals(OrderType.MARKET.getCode())) {
            // 市价单无最新价格，立即取消并退款
            order.setRefundVolume(order.getVolume());
            order.setStatus(OrderStatus.CANCELED.getCode());
            order.setMtime(TimeUtils.now());
            TradeResult result = new TradeResult();
            result.setTakerOrder(order);
            result.setFullyFilled(false);
            // 发送取消结果，让 TradeResultConsumer 更新 DB 并退还冻结余额
            sendTradeResultToKafka(symbol, result);
            return result;
        }
        order.setStatus(OrderStatus.NEW.getCode());
        order.setMtime(LocalDateTime.now());
        addOrderToNewEngineCache(order, symbol);
        return new TradeResult();
    }

    /**
     * 构建并发送撤单结果到 Kafka，供 TradeResultConsumer 更新 DB 和退款
     *
     * @param order 已设置 CANCELED 状态的订单
     */
    public void sendCancelResult(ExOrder order) {
        if (order == null || order.getSymbol() == null) {
            return;
        }
        TradeResult cancelResult = new TradeResult();
        cancelResult.setTakerOrder(order);
        cancelResult.setMatched(false);
        cancelResult.setFullyFilled(false);
        sendTradeResultToKafka(order.getSymbol(), cancelResult);
    }

    /**
     * 添加订单到新引擎缓存（公共方法）
     *
     * @param order 订单对象
     * @return 是否成功添加
     */
    public boolean addOrderToCache(ExOrder order) {
        if (order == null) {
            return false;
        }
        String symbol = order.getSymbol();
        if (symbol == null || symbol.trim().isEmpty()) {
            return false;
        }
        addOrderToNewEngineCache(order, symbol);
        return true;
    }

    /** 添加订单到新引擎缓存（内部方法） */
    private void addOrderToNewEngineCache(ExOrder order, String symbol) {
        String side = order.getSide();
        String cacheKey = symbol.toUpperCase() + Constant.CACHE_KEY_SEPARATOR + side;
        NEW_ENGINE_CACHE.compute(cacheKey, (key, orders) -> {
            if (orders == null) {
                orders = new java.util.concurrent.CopyOnWriteArrayList<>();
            }
            insertOrderInSortedPosition(orders, order, side);
            return orders;
        });
    }

    /** 将订单插入到排序位置 */
    private void insertOrderInSortedPosition(List<ExOrder> orders, ExOrder newOrder, String side) {
        if (orders.isEmpty()) {
            orders.add(newOrder);
            return;
        }
        orders.add(findInsertPosition(orders, newOrder, side), newOrder);
    }

    /** 找到插入位置 */
    private int findInsertPosition(List<ExOrder> orders, ExOrder newOrder, String side) {
        if (newOrder.getPrice() == null) {
            for (int i = 0; i < orders.size(); i++) {
                ExOrder existing = orders.get(i);
                if (existing.getPrice() != null) {
                    return i;
                }
                if (newOrder.getCtime() != null && existing.getCtime() != null &&
                        newOrder.getCtime().isBefore(existing.getCtime())) {
                    return i;
                }
            }
            return orders.size();
        }
        for (int i = 0; i < orders.size(); i++) {
            ExOrder existing = orders.get(i);
            if (existing.getPrice() == null) {
                continue;
            }
            if (OrderSide.BUY.getCode().equals(side)) {
                int cmp = newOrder.getPrice().compareTo(existing.getPrice());
                if (cmp > 0) {
                    return i;
                }
                if (cmp == 0 && newOrder.getCtime() != null && existing.getCtime() != null &&
                        newOrder.getCtime().isBefore(existing.getCtime())) {
                    return i;
                }
            } else {
                int cmp = newOrder.getPrice().compareTo(existing.getPrice());
                if (cmp < 0) {
                    return i;
                }
                if (cmp == 0 && newOrder.getCtime() != null && existing.getCtime() != null &&
                        newOrder.getCtime().isBefore(existing.getCtime())) {
                    return i;
                }
            }
        }
        return orders.size();
    }

    /**
     * 从新引擎缓存中移除订单
     *
     * @param order 要移除的订单
     * @return 是否成功移除
     */
    public boolean removeOrderFromCache(ExOrder order) {
        if (order == null || order.getId() == null || order.getSymbol() == null || order.getSide() == null) {
            return false;
        }
        try {
            String key = order.getSymbol().toUpperCase() + Constant.CACHE_KEY_SEPARATOR + order.getSide();
            List<ExOrder> orders = NEW_ENGINE_CACHE.get(key);
            if (orders == null || orders.isEmpty()) {
                return false;
            }
            boolean removed = orders.removeIf(o -> o != null && o.getId() != null &&
                    java.util.Objects.equals(o.getId(), order.getId()));
            if (removed) {
                log.info("订单已从缓存移除 - OrderId: {}, Symbol: {}, Side: {}", order.getId(), order.getSymbol(), order.getSide());
            } else {
                log.warn("订单不在缓存中，无需移除 - OrderId: {}, Symbol: {}, Side: {}", order.getId(), order.getSymbol(), order.getSide());
            }
            return removed;
        } catch (Exception e) {
            log.error("从新引擎缓存中移除订单时发生错误 - OrderId: {}", order.getId(), e);
            return false;
        }
    }

    /**
     * 价格更新时触发的匹配逻辑
     *
     * @param symbol   交易对
     * @param newPrice 新价格
     */
    public void processOnPriceUpdate(String symbol, BigDecimal newPrice) {
        processOrdersOnPriceUpdate(symbol, OrderSide.BUY.getCode(), newPrice);
        processOrdersOnPriceUpdate(symbol, OrderSide.SELL.getCode(), newPrice);
    }

    /** 价格更新时处理特定方向的挂单 */
    private void processOrdersOnPriceUpdate(String symbol, String side, BigDecimal newPrice) {
        String cacheKey = symbol.toUpperCase() + Constant.CACHE_KEY_SEPARATOR + side;
        List<ExOrder> orders = NEW_ENGINE_CACHE.get(cacheKey);
        if (orders == null || orders.isEmpty()) {
            return;
        }
        java.util.Set<Long> ordersToRemove = new java.util.HashSet<>();
        for (ExOrder order : orders) {
            if (canLimitOrderExecuteOnPriceUpdate(order, newPrice, side)) {
                TradeResult result = executePriceUpdateTrade(order, symbol, newPrice);
                ordersToRemove.add(order.getId());
                sendTradeResultToKafka(symbol, result);
            } else {
                break;
            }
        }
        if (!ordersToRemove.isEmpty()) {
            orders.removeIf(order -> ordersToRemove.contains(order.getId()));
        }
    }

    /** 判断价格更新时限价单是否可以成交 */
    private boolean canLimitOrderExecuteOnPriceUpdate(ExOrder order, BigDecimal newPrice, String side) {
        if (newPrice == null || order.getPrice() == null) {
            return false;
        }
        if (OrderSide.BUY.getCode().equals(side)) {
            return order.getPrice().compareTo(newPrice) >= 0;
        } else if (OrderSide.SELL.getCode().equals(side)) {
            return order.getPrice().compareTo(newPrice) <= 0;
        }
        return false;
    }

    /**
     * 执行价格变动吃单交易 - 用户为 maker，系统为 taker
     *
     * @param userOrder 用户挂单
     * @param symbol    交易对
     * @param newPrice  新价格
     * @return 撮合结果
     */
    private TradeResult executePriceUpdateTrade(ExOrder userOrder, String symbol, BigDecimal newPrice) {
        TradeResult result = new TradeResult();
        result.setMakerOrder(userOrder);
        result.setMatchTime(TimeUtils.now());

        BigDecimal tradePrice = userOrder.getPrice();
        BigDecimal totalVolume = userOrder.getVolume();

        if (isSmallRemainder(symbol, totalVolume, tradePrice)) {
            userOrder.setStatus(OrderStatus.CANCELED.getCode());
            userOrder.setMtime(TimeUtils.now());
            return result;
        }

        BigDecimal tradeVolume = formatVolume(totalVolume, symbol);
        BigDecimal tradeAmount = tradeVolume.multiply(tradePrice);
        BigDecimal refundVolume = BigDecimal.ZERO;

        if (OrderSide.BUY.getCode().equals(userOrder.getSide())) {
            BigDecimal orderAmount = totalVolume.multiply(userOrder.getPrice());
            refundVolume = orderAmount.subtract(tradeAmount);
        }

        BigDecimal userFee = FeeCalculator.calculateOrderFee(userOrder, tradePrice, tradeVolume,
                userOrder.getFeeRateMaker(), OrderSide.BUY.getCode().equals(userOrder.getSide()),
                configSymbolService, configCoinSymbolService);

        userOrder.setFee(userFee);
        userOrder.setDealVolume(formatVolume(tradeVolume, symbol));
        userOrder.setDealMoney(formatPrice(tradeAmount, symbol));
        userOrder.setAvgPrice(tradePrice);
        userOrder.setStatus(OrderStatus.FILLED.getCode());
        userOrder.setMtime(TimeUtils.now());

        if (refundVolume.compareTo(BigDecimal.ZERO) > 0) {
            userOrder.setRefundVolume(refundVolume);
            result.setFullyFilled(false);
        } else {
            result.setFullyFilled(true);
        }

        // 价格变动吃单：系统为 taker，用户为 maker
        TradeRecord tradeRecord = new TradeRecord();
        tradeRecord.setSymbol(symbol);
        tradeRecord.setTradePrice(formatPrice(tradePrice, symbol));
        tradeRecord.setTradeVolume(formatVolume(tradeVolume, symbol));
        tradeRecord.setTradeAmount(formatPrice(tradeAmount, symbol));
        tradeRecord.setTradeTime(TimeUtils.now());
        tradeRecord.setTakerOrderId(Constant.SYSTEM_ORDER_ID);
        tradeRecord.setTakerUserId(Constant.SYSTEM_USER_ID);
        tradeRecord.setTakerSide(OrderSide.BUY.getCode().equals(userOrder.getSide())
                ? OrderSide.SELL.getCode() : OrderSide.BUY.getCode());
        tradeRecord.setTakerFee(BigDecimal.ZERO);
        tradeRecord.setMakerOrderId(userOrder.getId());
        tradeRecord.setMakerUserId(userOrder.getUserId());
        tradeRecord.setMakerSide(userOrder.getSide());
        tradeRecord.setMakerFee(userFee);

        result.setTradeRecord(tradeRecord);
        result.setMatched(true);
        return result;
    }

    /**
     * 发送交易结果到 Kafka
     *
     * @param symbol      交易对
     * @param tradeResult 撮合结果
     */
    private void sendTradeResultToKafka(String symbol, TradeResult tradeResult) {
        if (symbol == null || tradeResult == null) {
            return;
        }
        try {
            String messageId = generateMessageId(tradeResult);
            tradeResult.setMessageId(messageId);
            String topic = tradeTopic + symbol.toUpperCase();
            String json = JSON.toJSONString(tradeResult);
            kafkaTemplate.send(topic, messageId, json);
            log.info("撮合结果已发送 Kafka - Symbol: {}, Topic: {}, MessageId: {}, Matched: {}",
                    symbol, topic, messageId, tradeResult.isMatched());
        } catch (Exception e) {
            log.error("发送撮合结果到 Kafka 失败 - Symbol: {}", symbol, e);
        }
    }

    /** 构建交易记录（用户为 taker，系统为 maker） */
    private TradeRecord buildTradeRecord(String symbol, BigDecimal tradePrice, BigDecimal tradeVolume,
                                         BigDecimal tradeAmount, ExOrder takerOrder, BigDecimal fee) {
        TradeRecord tradeRecord = new TradeRecord();
        tradeRecord.setSymbol(symbol);
        tradeRecord.setTradePrice(formatPrice(tradePrice, symbol));
        tradeRecord.setTradeVolume(formatVolume(tradeVolume, symbol));
        tradeRecord.setTradeAmount(formatPrice(tradeAmount, symbol));
        tradeRecord.setTradeTime(TimeUtils.now());
        tradeRecord.setTakerOrderId(takerOrder.getId());
        tradeRecord.setTakerUserId(takerOrder.getUserId());
        tradeRecord.setTakerSide(takerOrder.getSide());
        tradeRecord.setTakerFee(fee);
        tradeRecord.setMakerOrderId(Constant.SYSTEM_ORDER_ID);
        tradeRecord.setMakerUserId(Constant.SYSTEM_USER_ID);
        tradeRecord.setMakerSide(OrderSide.BUY.getCode().equals(takerOrder.getSide())
                ? OrderSide.SELL.getCode() : OrderSide.BUY.getCode());
        tradeRecord.setMakerFee(BigDecimal.ZERO);
        return tradeRecord;
    }

    /** 生成唯一消息 ID：orderId_timestamp_uuid8 */
    private String generateMessageId(TradeResult tradeResult) {
        String orderId = (tradeResult.getTakerOrder() != null && tradeResult.getTakerOrder().getId() != null)
                ? String.valueOf(tradeResult.getTakerOrder().getId()) : "UNKNOWN";
        return orderId + "_" + System.currentTimeMillis() + "_"
                + UUID.randomUUID().toString().replace("-", "").substring(0, 8);
    }

    /** 判断是否为小额剩余（不满足最小交易单位） */
    private boolean isSmallRemainder(String symbol, BigDecimal remainingVolume, BigDecimal currentPrice) {
        try {
            ConfigSymbol symbolConfig = configSymbolService.getConfigSymbol(symbol);
            if (symbolConfig == null) {
                return false;
            }
            BigDecimal minTradeVolume = getMinTradeVolume(symbolConfig);
            BigDecimal minTradeAmount = getMinTradeAmount(symbolConfig);
            if (remainingVolume.compareTo(minTradeVolume.multiply(Constant.SMALL_REMAINDER_MULTIPLIER)) < 0) {
                return true;
            }
            BigDecimal remainingAmount = remainingVolume.multiply(currentPrice);
            return remainingAmount.compareTo(minTradeAmount.multiply(Constant.SMALL_REMAINDER_MULTIPLIER)) < 0;
        } catch (Exception e) {
            log.error("检查小额剩余时发生错误 - Symbol: {}", symbol, e);
            return false;
        }
    }

    /** 通过交易对获取最小交易数量 */
    private BigDecimal getMinTradeVolumeForSymbol(String symbol) {
        ConfigSymbol symbolConfig = configSymbolService.getConfigSymbol(symbol);
        if (symbolConfig != null) {
            return getMinTradeVolume(symbolConfig);
        }
        return Constant.DEFAULT_MIN_TRADE_VOLUME;
    }

    /** 获取最小交易数量 */
    private BigDecimal getMinTradeVolume(ConfigSymbol symbolConfig) {
        if (symbolConfig.getVolumePre() != null) {
            return BigDecimal.ONE.divide(BigDecimal.TEN.pow(symbolConfig.getVolumePre()),
                    symbolConfig.getVolumePre(), RoundingMode.HALF_UP);
        }
        return Constant.DEFAULT_MIN_TRADE_VOLUME;
    }

    /** 获取最小交易金额 */
    private BigDecimal getMinTradeAmount(ConfigSymbol symbolConfig) {
        if (symbolConfig.getPricePre() != null) {
            return BigDecimal.ONE.divide(BigDecimal.TEN.pow(symbolConfig.getPricePre()),
                    symbolConfig.getPricePre(), RoundingMode.HALF_UP);
        }
        return Constant.DEFAULT_MIN_TRADE_VOLUME;
    }

    /** 格式化价格到指定精度（使用计价货币的合约精度） */
    private BigDecimal formatPrice(BigDecimal price, String symbol) {
        if (price == null) {
            return BigDecimal.ZERO;
        }
        try {
            ConfigSymbol symbolConfig = configSymbolService.getConfigSymbol(symbol);
            if (symbolConfig != null && symbolConfig.getQuote() != null) {
                ConfigCoinSymbol coinConfig = configCoinSymbolService.getConfigCoinSymbol(symbolConfig.getQuote());
                if (coinConfig != null && coinConfig.getContractPrecision() != null) {
                    return price.setScale(coinConfig.getContractPrecision(), RoundingMode.DOWN);
                }
            }
        } catch (Exception e) {
            log.warn("格式化价格失败，使用默认精度 - Symbol: {}", symbol, e);
        }
        return price.setScale(Constant.DEFAULT_PRECISION, RoundingMode.DOWN);
    }

    /** 格式化数量到指定精度（使用基础货币的合约精度） */
    private BigDecimal formatVolume(BigDecimal volume, String symbol) {
        if (volume == null) {
            return BigDecimal.ZERO;
        }
        try {
            ConfigSymbol symbolConfig = configSymbolService.getConfigSymbol(symbol);
            if (symbolConfig != null && symbolConfig.getBase() != null) {
                ConfigCoinSymbol coinConfig = configCoinSymbolService.getConfigCoinSymbol(symbolConfig.getBase());
                if (coinConfig != null && coinConfig.getContractPrecision() != null) {
                    return volume.setScale(coinConfig.getContractPrecision(), RoundingMode.DOWN);
                }
            }
        } catch (Exception e) {
            log.warn("格式化数量失败，使用默认精度 - Symbol: {}", symbol, e);
        }
        return volume.setScale(Constant.DEFAULT_PRECISION, RoundingMode.DOWN);
    }

    /**
     * 获取新引擎缓存（供启动加载器使用）
     *
     * @return 缓存 Map
     */
    public static ConcurrentHashMap<String, List<ExOrder>> getNewEngineCache() {
        return NEW_ENGINE_CACHE;
    }

    /**
     * 获取指定交易对和方向的缓存订单
     *
     * @param symbol 交易对
     * @param side   方向
     * @return 订单列表
     */
    public static List<ExOrder> getCacheOrders(String symbol, String side) {
        return NEW_ENGINE_CACHE.get(symbol.toUpperCase() + Constant.CACHE_KEY_SEPARATOR + side);
    }
}
