package com.spot.utils;

import com.spot.entity.ConfigCoinSymbol;
import com.spot.entity.ConfigSymbol;
import com.spot.entity.ExOrder;
import com.spot.enums.OrderSide;
import com.spot.service.ConfigCoinSymbolService;
import com.spot.service.ConfigSymbolService;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 手续费计算工具类
 *
 * @author jean
 * @date 2026-05-07
 */
@Slf4j
public class FeeCalculator {

    /** 默认精度（当无法获取配置时使用，与 Constant.DEFAULT_PRECISION 保持一致） */
    private static final int DEFAULT_PRECISION = Constant.DEFAULT_PRECISION;

    /**
     * 计算订单的手续费
     *
     * @param order                  订单
     * @param tradePrice             成交价格
     * @param tradeVolume            成交数量
     * @param feeRate                费率
     * @param isTaker                是否为 taker
     * @param configSymbolService    交易对配置服务
     * @param configCoinSymbolService 币种配置服务
     * @return 手续费
     */
    public static BigDecimal calculateOrderFee(ExOrder order, BigDecimal tradePrice,
                                               BigDecimal tradeVolume, Double feeRate, boolean isTaker,
                                               ConfigSymbolService configSymbolService,
                                               ConfigCoinSymbolService configCoinSymbolService) {
        if (order == null) {
            log.warn("订单为空，无法计算手续费");
            return BigDecimal.ZERO;
        }
        return calculateTradeFee(order.getSymbol(), tradePrice, tradeVolume, feeRate, isTaker,
                order.getSide(), configSymbolService, configCoinSymbolService);
    }

    /**
     * 计算交易手续费
     *
     * @param symbol                  交易对
     * @param tradePrice              成交价格
     * @param tradeVolume             成交数量
     * @param feeRate                 费率
     * @param isTaker                 是否为 taker
     * @param orderSide               订单方向
     * @param configSymbolService     交易对配置服务
     * @param configCoinSymbolService 币种配置服务
     * @return 手续费
     */
    public static BigDecimal calculateTradeFee(String symbol, BigDecimal tradePrice,
                                               BigDecimal tradeVolume, Double feeRate, boolean isTaker,
                                               String orderSide,
                                               ConfigSymbolService configSymbolService,
                                               ConfigCoinSymbolService configCoinSymbolService) {
        if (tradePrice == null || tradeVolume == null || feeRate == null) {
            log.warn("计算手续费参数无效 - Symbol: {}, Price: {}, Volume: {}, FeeRate: {}",
                    symbol, tradePrice, tradeVolume, feeRate);
            return BigDecimal.ZERO;
        }

        // 获取交易对配置
        ConfigSymbol symbolConfig = configSymbolService.getConfigSymbol(symbol);
        if (symbolConfig == null) {
            log.warn("未找到交易对配置，使用默认精度计算手续费 - Symbol: {}", symbol);
            return calculateFeeWithDefaultPrecision(tradePrice, tradeVolume, feeRate);
        }

        // 从交易对配置中获取计价币种
        String quoteCurrency = symbolConfig.getQuote();
        if (quoteCurrency == null || quoteCurrency.trim().isEmpty()) {
            log.warn("交易对配置中计价币种为空，使用默认精度计算手续费 - Symbol: {}", symbol);
            return calculateFeeWithDefaultPrecision(tradePrice, tradeVolume, feeRate);
        }

        // 获取计价币种配置
        ConfigCoinSymbol coinSymbolConfig = configCoinSymbolService.getConfigCoinSymbol(quoteCurrency);
        if (coinSymbolConfig == null) {
            log.warn("未找到币种配置，使用默认精度计算手续费 - Symbol: {}, QuoteCurrency: {}", symbol, quoteCurrency);
            return calculateFeeWithDefaultPrecision(tradePrice, tradeVolume, feeRate);
        }

        // 根据订单方向计算手续费基数
        BigDecimal feeBase;
        if (OrderSide.BUY.getCode().equals(orderSide)) {
            // 买单：手续费基于成交数量（基础货币数量）
            feeBase = tradeVolume;
        } else {
            // 卖单：手续费基于成交金额（价格 × 数量）
            feeBase = tradePrice.multiply(tradeVolume);
        }

        BigDecimal baseFee = feeBase.multiply(BigDecimal.valueOf(feeRate));

        // 使用币种的合约精度作为手续费精度，向上取整
        int precision = coinSymbolConfig.getContractPrecision() != null
                ? coinSymbolConfig.getContractPrecision() : DEFAULT_PRECISION;
        return baseFee.setScale(precision, RoundingMode.UP);
    }

    /** 使用默认精度计算手续费 */
    private static BigDecimal calculateFeeWithDefaultPrecision(BigDecimal tradePrice,
                                                               BigDecimal tradeVolume,
                                                               Double feeRate) {
        BigDecimal tradeAmount = tradePrice.multiply(tradeVolume);
        BigDecimal baseFee = tradeAmount.multiply(BigDecimal.valueOf(feeRate));
        return baseFee.setScale(DEFAULT_PRECISION, RoundingMode.UP);
    }

    /**
     * 验证订单是否符合交易对配置要求
     *
     * @param order               订单
     * @param configSymbolService 交易对配置服务
     * @return 是否合法
     */
    public static boolean validateOrder(ExOrder order, ConfigSymbolService configSymbolService) {
        if (order == null || order.getSymbol() == null) {
            log.warn("订单或交易对为空，验证失败");
            return false;
        }
        ConfigSymbol symbolConfig = configSymbolService.getConfigSymbol(order.getSymbol());
        if (symbolConfig == null) {
            log.warn("未找到交易对配置 - Symbol: {}", order.getSymbol());
            return false;
        }
        return true;
    }
}
