package com.market.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.market.model.SpotBaseMessage;
import com.market.model.SpotClientSession;
import com.market.utils.SpotConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 现货 WebSocket 消息处理服务（旧协议：event=sub/unsub/req）
 *
 * @author system
 * @date 2026-05-07
 */
@Service
public class SpotMessageHandlerService {

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

    private final StringRedisTemplate redisTemplate;
    private final ObjectMapper objectMapper;
    private final SpotDataQueryService dataQueryService;
    private final SpotMarketPushService pushService;

    public SpotMessageHandlerService(StringRedisTemplate redisTemplate,
                                     SpotDataQueryService dataQueryService,
                                     SpotMarketPushService pushService) {
        this.redisTemplate = redisTemplate;
        this.dataQueryService = dataQueryService;
        this.pushService = pushService;
        this.objectMapper = new ObjectMapper();
    }

    /**
     * 处理前端消息（旧协议）
     *
     * @param clientSession 客户端会话
     * @param message       解析后的基础消息
     */
    public void handleMessage(SpotClientSession clientSession, SpotBaseMessage message) {
        try {
            String action = message.getEvent();

            // 1. 心跳 pong
            if (action == null && message.getPong() != null) {
                clientSession.setLastPongTime(LocalDateTime.now());
                return;
            }

            // 2. 订阅
            if (SpotConstant.EVENT_SUB.equals(action) || SpotConstant.EVENT_SUB_BATCH.equals(action)) {
                handleSubscribe(clientSession, message);
                return;
            }

            // 3. 取消订阅
            if (SpotConstant.EVENT_UNSUB.equals(action) || SpotConstant.EVENT_UNSUB_BATCH.equals(action)) {
                handleUnsubscribe(clientSession, message);
                return;
            }

            // 4. 数据请求
            if (SpotConstant.EVENT_REQ.equals(action)) {
                handleRequest(clientSession, message);
            }

        } catch (Exception e) {
            log.error("处理现货 WebSocket 消息失败: clientId={}", clientSession.getId(), e);
        }
    }

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

    /** 处理订阅（支持逗号分隔批量），同步注册到推送服务并立即推送缓存 */
    private void handleSubscribe(SpotClientSession clientSession, SpotBaseMessage message) {
        String channel = message.getChannel();
        if (channel == null) {
            return;
        }
        List<String> channels = Arrays.asList(channel.split(","));
        for (String ch : channels) {
            ch = ch.trim().toLowerCase();
            SpotClientSession.SubscribeData subscribeData = new SpotClientSession.SubscribeData();
            subscribeData.setAction(SpotConstant.SUBSCRIBE_ACTION);
            subscribeData.setParams(buildSubscribeParams(message, ch));
            subscribeData.setFlutter(clientSession.isFlutter());
            clientSession.getSubscriptions().put(ch, subscribeData);
            // 同步注册到推送服务
            pushService.subscribe(clientSession.getId(), ch);
            // 立即推送最新缓存
            Object latest = pushService.getLatest(ch);
            if (latest != null) {
                pushService.pushToSession(clientSession, ch, latest);
            }
        }
    }

    /** 处理取消订阅（支持逗号分隔批量），同步从推送服务移除 */
    private void handleUnsubscribe(SpotClientSession clientSession, SpotBaseMessage message) {
        String channel = message.getChannel();
        if (channel == null) {
            return;
        }
        for (String ch : Arrays.asList(channel.split(","))) {
            ch = ch.trim().toLowerCase();
            clientSession.getSubscriptions().remove(ch);
            pushService.unsubscribe(clientSession.getId(), ch);
        }
    }

    /** 处理数据请求 */
    private void handleRequest(SpotClientSession clientSession, SpotBaseMessage message) {
        String channel = message.getChannel();
        if (channel == null) {
            return;
        }
        List<String> channels = Arrays.asList(channel.split(","));
        for (String ch : channels) {
            ch = ch.trim().toLowerCase();
            Map<String, Object> responseData = dataQueryService.queryData(ch, message, clientSession.isFlutter());
            if (responseData != null) {
                try {
                    clientSession.getReqQueue().offer(objectMapper.writeValueAsString(responseData));
                } catch (Exception e) {
                    log.error("序列化请求响应失败: clientId={}, channel={}", clientSession.getId(), ch, e);
                }
            }
        }
    }

    /** 构建订阅参数 */
    private Map<String, Object> buildSubscribeParams(SpotBaseMessage message, String channel) {
        Map<String, Object> params = new HashMap<>();
        if (message.getParams() == null) {
            return params;
        }
        message.getParams().forEach((key, value) -> {
            if (SpotConstant.PARAM_FIELD_CHANNEL.equals(key)) {
                params.put(key, channel);
            } else if (SpotConstant.PARAM_FIELD_CB_ID.equals(key)) {
                String cbId = value != null ? value.toString() : SpotConstant.DEFAULT_CB_ID;
                if (!SpotConstant.DEFAULT_CB_ID.equals(cbId)) {
                    params.put(key, value);
                } else {
                    String[] parts = channel.split("_");
                    if (parts.length > 1) {
                        params.put(key, parts[1]);
                    }
                }
            } else {
                params.put(key, value);
            }
        });
        return params;
    }
}
