package org.dromara.system.websocket;

import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.websocket.holder.WebSocketSessionHolder;
import org.dromara.common.websocket.utils.WebSocketUtils;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 站内信 WebSocket 服务
 */
@Slf4j
@Component
@ServerEndpoint("/websocket/message")
public class MessageWebSocketServer {

    /**
     * 用户ID和会话的映射关系
     */
    private static final Map<Long, Session> SESSION_MAP = new ConcurrentHashMap<>();

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
        log.info("[WebSocket] 新的连接建立，sessionId: {}", session.getId());
        try {
            // 获取当前登录用户
            LoginUser loginUser = (LoginUser) session.getUserProperties().get("loginUser");
            if (loginUser != null) {
                SESSION_MAP.put(loginUser.getUserId(), session);
                log.info("[WebSocket] 用户 {} 连接成功", loginUser.getUserId());
            } else {
                log.warn("[WebSocket] 未获取到用户信息，关闭连接");
                session.close();
            }
        } catch (Exception e) {
            log.error("[WebSocket] 连接建立失败", e);
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        log.info("[WebSocket] 连接关闭，sessionId: {}", session.getId());
        // 从映射中移除会话
        SESSION_MAP.values().removeIf(s -> s.getId().equals(session.getId()));
    }

    /**
     * 收到客户端消息后调用的方法
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("[WebSocket] 收到消息: {}", message);
        // 这里可以处理客户端发送的消息
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("[WebSocket] 发生错误", error);
        // 从映射中移除会话
        SESSION_MAP.values().removeIf(s -> s.getId().equals(session.getId()));
    }

    /**
     * 发送消息给指定用户
     *
     * @param userId  用户ID
     * @param message 消息内容
     */
    public void sendMessage(Long userId, String message) {
        Session session = SESSION_MAP.get(userId);
        if (session != null && session.isOpen()) {
            try {
                session.getBasicRemote().sendText(message);
                log.info("[WebSocket] 消息发送成功，接收者: {}", userId);
            } catch (IOException e) {
                log.error("[WebSocket] 消息发送失败", e);
            }
        } else {
            log.warn("[WebSocket] 用户 {} 不在线或会话已关闭", userId);
        }
    }

    /**
     * 广播消息给所有在线用户
     *
     * @param message 消息内容
     */
    public void broadcastMessage(String message) {
        SESSION_MAP.forEach((userId, session) -> {
            if (session.isOpen()) {
                try {
                    session.getBasicRemote().sendText(message);
                    log.info("[WebSocket] 广播消息发送成功，接收者: {}", userId);
                } catch (IOException e) {
                    log.error("[WebSocket] 广播消息发送失败，接收者: {}", userId, e);
                }
            }
        });
    }
}
