package com.market.service;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.market.entity.ConfigSymbol;
import com.market.mapper.SpotConfigSymbolMapper;
import com.market.utils.SpotConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 现货币种深度精度配置服务
 * <p>
 * 缓存所有开启币种的三档深度精度（depth0Pre / depth1Pre / depth2Pre），
 * 每 60 分钟自动刷新一次。
 *
 * @author system
 * @date 2026-05-07
 */
@DS("kucoin")
@Service
public class SpotSymbolPrecisionService {

    private static final Logger log = LoggerFactory.getLogger(SpotSymbolPrecisionService.class);

    private final SpotConfigSymbolMapper configSymbolMapper;

    /**
     * 精度配置缓存
     * key: symbol（小写），value: [depth0Pre, depth1Pre, depth2Pre]
     */
    private final Map<String, int[]> symbolPrecisionMap = new ConcurrentHashMap<>();

    public SpotSymbolPrecisionService(SpotConfigSymbolMapper configSymbolMapper) {
        this.configSymbolMapper = configSymbolMapper;
    }

    /**
     * 启动时加载精度配置
     */
    @PostConstruct
    public void init() {
        loadPrecisionConfig();
    }

    /**
     * 每 60 分钟刷新精度配置
     */
    @Scheduled(fixedRate = SpotConstant.PRECISION_REFRESH_INTERVAL_MS)
    public void refreshPrecisionConfig() {
        log.info("定时刷新现货币种精度配置...");
        loadPrecisionConfig();
    }

    /**
     * 获取指定币种和 step 档位的精度
     *
     * @param symbol 币种（大小写均可）
     * @param step   档位（0 / 1 / 2）
     * @return 精度值，不存在时返回 null
     */
    public Integer getPrecision(String symbol, int step) {
        int[] precisions = symbolPrecisionMap.get(symbol.toLowerCase());
        if (precisions == null || step < 0 || step >= precisions.length) {
            return null;
        }
        return precisions[step];
    }

    /**
     * 检查币种是否有精度配置
     *
     * @param symbol 币种
     * @return true=有配置
     */
    public boolean hasPrecision(String symbol) {
        return symbolPrecisionMap.containsKey(symbol.toLowerCase());
    }

    /**
     * 获取所有已配置的币种
     *
     * @return 币种集合
     */
    public Set<String> getAllSymbols() {
        return symbolPrecisionMap.keySet();
    }

    /**
     * 手动触发刷新
     */
    public void refresh() {
        loadPrecisionConfig();
    }

    // ------------------------------------------------------------------ private

    /** 从数据库加载精度配置 */
    private void loadPrecisionConfig() {
        try {
            LambdaQueryWrapper<ConfigSymbol> qw = new LambdaQueryWrapper<>();
            qw.select(ConfigSymbol::getSymbol,
                      ConfigSymbol::getDepth0Pre,
                      ConfigSymbol::getDepth1Pre,
                      ConfigSymbol::getDepth2Pre);
            qw.eq(ConfigSymbol::getIsOpen, 1);
            qw.eq(ConfigSymbol::getPublish, 1);
            List<ConfigSymbol> configList = configSymbolMapper.selectList(qw);

            if (configList == null || configList.isEmpty()) {
                log.warn("未查询到现货币种精度配置");
                return;
            }

            symbolPrecisionMap.clear();
            for (ConfigSymbol cs : configList) {
                String symbolName = cs.getSymbol().toLowerCase();
                int depth0 = cs.getDepth0Pre() != null ? cs.getDepth0Pre().intValue() : SpotConstant.DEFAULT_PRECISION_DEPTH0;
                int depth1 = cs.getDepth1Pre() != null ? cs.getDepth1Pre().intValue() : SpotConstant.DEFAULT_PRECISION_DEPTH1;
                int depth2 = cs.getDepth2Pre() != null ? cs.getDepth2Pre().intValue() : SpotConstant.DEFAULT_PRECISION_DEPTH2;
                symbolPrecisionMap.put(symbolName, new int[]{depth0, depth1, depth2});
            }
            log.info("现货币种精度配置加载完成，共 {} 个币种", symbolPrecisionMap.size());
        } catch (Exception e) {
            log.error("加载现货币种精度配置失败", e);
        }
    }
}
