package com.njcn.gather.detection.util.socket.websocket;

import com.alibaba.fastjson.JSON;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Generic WebSocket session manager.
 * Stage 4-A removes detection payload conventions and detection parameter
 * caches from this class so it remains a pure WebSocket session registry.
 *
 * @author wr
 * @author hongawen
 * @date 2026/04/07
 */
@Slf4j
public class WebServiceManager {

    private static final Map<String, Channel> USER_SESSIONS = new ConcurrentHashMap<>();

    private WebServiceManager() {
    }

    public static void addUser(String userId, Channel channel) {
        USER_SESSIONS.put(userId, channel);
    }

    public static Channel removeByUserId(String userId) {
        return USER_SESSIONS.remove(userId);
    }

    @Deprecated
    public static void removeChannel(String channelId) {
        Iterator<Map.Entry<String, Channel>> iterator = USER_SESSIONS.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Channel> entry = iterator.next();
            if (entry.getValue().id().toString().equals(channelId)) {
                iterator.remove();
                break;
            }
        }
    }

    public static void sendMsg(String userId, String msg) {
        Channel channel = USER_SESSIONS.get(userId);
        if (Objects.nonNull(channel) && channel.isActive()) {
            channel.writeAndFlush(new TextWebSocketFrame(msg));
            return;
        }
        log.error("WebSocket push failed because session is offline, time={}, userId={}",
                LocalDateTime.now(), userId);
        WebSocketHandler.cleanupSocketResources(userId);
    }

    public static void sendJson(String userId, Object payload) {
        Channel channel = USER_SESSIONS.get(userId);
        if (Objects.nonNull(channel) && channel.isActive()) {
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(payload)));
            return;
        }
        log.error("WebSocket json push failed because session is offline, time={}, userId={}",
                LocalDateTime.now(), userId);
        WebSocketHandler.cleanupSocketResources(userId);
    }

    public static int getOnlineUserCount() {
        return USER_SESSIONS.size();
    }

    public static boolean isUserOnline(String userId) {
        Channel channel = USER_SESSIONS.get(userId);
        return Objects.nonNull(channel) && channel.isActive();
    }

    public static Set<String> getOnlineUserIds() {
        return new HashSet<>(USER_SESSIONS.keySet());
    }
}
