package com.market.consumer;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.market.model.ManualPriceMessage;
import com.market.service.SpotDataProcessService;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;

/**
 * 现货手动注入价格 Kafka 消费者
 * <p>
 * 监听外部发布的手动价格消息，将指定 symbol 所有已缓存周期的
 * K 线收盘价更新到内存、数据库和 Redis。
 * <p>
 * 消息格式：{"symbol":"btcusdt","price":"95000.00"}
 *
 * @author system
 * @date 2026-05-10
 */
@Component
public class SpotManualPriceConsumer {

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

    /** 现货行情数据处理服务，负责内存 + 数据库 + Redis 更新 */
    private final SpotDataProcessService spotDataProcessService;
    private final ObjectMapper           objectMapper;

    public SpotManualPriceConsumer(SpotDataProcessService spotDataProcessService) {
        this.spotDataProcessService = spotDataProcessService;
        this.objectMapper           = new ObjectMapper();
    }

    /**
     * 消费现货手动价格消息
     *
     * @param record Kafka 消息记录
     * @param ack    手动提交偏移量
     */
    @KafkaListener(
            topics      = "${spot.kafka.topic.manual-price:SPOT_MANUAL_PRICE}",
            groupId     = "${spot.kafka.consumer.group-id:spot-market-group}",
            concurrency = "1"
    )
    public void onManualPrice(ConsumerRecord<String, String> record, Acknowledgment ack) {
        try {
            // 1. 解析消息
            ManualPriceMessage msg = objectMapper.readValue(record.value(), ManualPriceMessage.class);
            if (msg.getSymbol() == null || msg.getPrice() == null) {
                log.warn("现货手动价格消息字段缺失: {}", record.value());
                return;
            }

            String symbol = msg.getSymbol().toLowerCase();
            BigDecimal price = new BigDecimal(msg.getPrice());

            log.info("收到现货手动注入价格: symbol={}, price={}", symbol, price);

            // 2. 更新所有周期内存 + DB + Redis
            spotDataProcessService.applyManualPrice(symbol, price);

        } catch (Exception e) {
            log.error("处理现货手动价格消息失败: topic={}, offset={}, value={}",
                    record.topic(), record.offset(), record.value(), e);
        } finally {
            ack.acknowledge();
        }
    }
}
