package com.market.manager;

import com.market.model.SpotClientSession;
import com.market.utils.SpotConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 现货 WebSocket 客户端会话管理器
 *
 * @author system
 * @date 2026-05-07
 */
@Component
public class SpotClientSessionManager {

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

    /** clientId → SpotClientSession（主索引） */
    private final Map<String, SpotClientSession> sessions = new ConcurrentHashMap<>();

    /** wsSessionId → SpotClientSession（二级索引，O(1) 反查） */
    private final Map<String, SpotClientSession> wsSessions = new ConcurrentHashMap<>();

    /** 客户端 ID 自增计数器 */
    private final AtomicLong clientCounter = new AtomicLong(0);

    /**
     * 添加会话，同时维护 wsSessionId 二级索引
     *
     * @param session 客户端会话
     */
    public void addSession(SpotClientSession session) {
        sessions.put(session.getId(), session);
        if (session.getSession() != null) {
            wsSessions.put(session.getSession().getId(), session);
        }
        log.info("现货客户端连接: id={}, 当前连接数={}", session.getId(), sessions.size());
    }

    /**
     * 移除会话，同时清理 wsSessionId 二级索引
     *
     * @param sessionId 客户端ID
     */
    public void removeSession(String sessionId) {
        SpotClientSession session = sessions.remove(sessionId);
        if (session != null) {
            if (session.getSession() != null) {
                wsSessions.remove(session.getSession().getId());
            }
            log.info("现货客户端断开: id={}, 当前连接数={}", sessionId, sessions.size());
        }
    }

    /**
     * 通过客户端ID获取会话
     *
     * @param sessionId 客户端ID
     * @return 会话对象，不存在返回 null
     */
    public SpotClientSession getSession(String sessionId) {
        return sessions.get(sessionId);
    }

    /**
     * 通过 Spring WebSocketSession ID 获取会话（O(1) 反查）
     *
     * @param wsSessionId Spring WebSocketSession.getId()
     * @return 会话对象，不存在返回 null
     */
    public SpotClientSession getByWsSessionId(String wsSessionId) {
        return wsSessions.get(wsSessionId);
    }

    /**
     * 获取所有会话
     *
     * @return 会话 Map（只读视图）
     */
    public Map<String, SpotClientSession> getAllSessions() {
        return sessions;
    }

    /**
     * 获取当前连接数
     *
     * @return 连接数
     */
    public int getSessionCount() {
        return sessions.size();
    }

    /**
     * 根据用户ID获取该用户所有在线会话
     *
     * @param uid 用户ID（字符串）
     * @return 会话列表，无会话时返回空列表
     */
    public List<SpotClientSession> getSessionsByUid(String uid) {
        List<SpotClientSession> result = new ArrayList<>();
        if (uid == null) {
            return result;
        }
        for (SpotClientSession session : sessions.values()) {
            if (uid.equals(session.getUid())) {
                result.add(session);
            }
        }
        return result;
    }

    /**
     * 生成唯一客户端ID
     *
     * @return 客户端ID字符串
     */
    public String generateClientId() {
        return SpotConstant.CLIENT_ID_PREFIX + System.currentTimeMillis() + "_" + clientCounter.incrementAndGet();
    }
}
