package com.market.service.impl;

import com.alibaba.fastjson.JSON;
import com.market.utils.KlineUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 资金费率 Redis 更新服务
 *
 * <p>Redis key：{@code FUNDING_RATE:}，TTL 7 天
 * <p>Redis value：JSON，格式 {@code {"1":0.000010,"2":0.000010,...}}
 */
@Slf4j
@Service
public class FundingRateServiceImpl {

    private static final String REDIS_KEY = "FUNDING_RATE:";

    /** JDK 序列化模板，与其他项目 key 格式（\xac\xed 前缀）保持一致 */
    @Autowired
    @Qualifier("jdkRedisTemplate")
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private KlineUtils klineUtils;

    private ValueOperations<String, Object> valOps;

    @PostConstruct
    public void init() {
        valOps = redisTemplate.opsForValue();
    }

    // ------------------------------------------------------------------ public

    /**
     * 尝试更新资金费率（1 分钟限流）。
     *
     * @param symbol 小写交易对，如 btcusdt
     * @param rate   资金费率字符串，如 "0.000100"
     */
    public void tryUpdate(String symbol, String rate) {
        Long contractId = klineUtils.SYMBOL_ID_MAP.get(symbol);
        if (contractId == null) return;

        long now = System.currentTimeMillis();
        Long last = klineUtils.LAST_FUNDING_RATE_TIME.getIfPresent(symbol);
        if (last != null && now - last < KlineUtils.FUNDING_RATE_INTERVAL_MS) return;
        klineUtils.LAST_FUNDING_RATE_TIME.put(symbol, now);

        try {
            Map<Integer, BigDecimal> rateMap = getFundingRateMap();
            if (rateMap == null) rateMap = new HashMap<>();
            rateMap.put(contractId.intValue(), new BigDecimal(rate));
            saveFundingRateMap(rateMap);
        } catch (Exception e) {
            log.error("资金费率写 Redis 失败: symbol={}", symbol, e);
        }
    }

    // ------------------------------------------------------------------ redis

    public void saveFundingRateMap(Map<Integer, BigDecimal> biasMap) {
        valOps.set(REDIS_KEY, JSON.toJSONString(biasMap), 7, TimeUnit.DAYS);
    }

    public Map<Integer, BigDecimal> getFundingRateMap() {
        try {
            Object biasMap = valOps.get(REDIS_KEY);
            if (biasMap != null) {
                String json = biasMap.toString();
                return (Map<Integer, BigDecimal>) JSON.parseObject(json, Map.class);
            }
            return null;
        } catch (Exception e) {
            return null;
        }
    }
}
