package com.ruoyi.framework.websocket;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.HeartbeatMessage;
import com.ruoyi.system.domain.HeartbeatResponse;
import com.ruoyi.system.domain.UserLocation;
import com.ruoyi.system.service.ISysUserOnlineTimeService;
import com.ruoyi.system.service.impl.SysUserOnlineTimeServiceImpl;
import org.apache.ibatis.annotations.Param;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.List;
import java.util.concurrent.Semaphore;
import com.ruoyi.system.domain.HeartbeatMessage;


@Component
// 把当前类标识成一个WebSocket的服务端
@ServerEndpoint("/websocket/online/{token}")
public class UserOnlineTimeWebSocketServer {
    private static final Logger LOGGER = LoggerFactory.getLogger(UserOnlineTimeWebSocketServer.class);
    private static final int MAX_ONLINE_COUNT = 100000;
    private static final Semaphore SEMAPHORE = new Semaphore(MAX_ONLINE_COUNT);

//    private static volatile LocationService locationService;
    private static volatile ObjectMapper objectMapper;

    private static volatile SysUserOnlineTimeServiceImpl userOnlineTimeService;

    private static volatile TokenService tokenService;

    public static void setUserOnlineTimeService(SysUserOnlineTimeServiceImpl service) {
        UserOnlineTimeWebSocketServer.userOnlineTimeService = service;
    }
    public static void setTokenService(TokenService service) {
        UserOnlineTimeWebSocketServer.tokenService = service;
    }

    public static void setObjectMapper(ObjectMapper mapper) {
        UserOnlineTimeWebSocketServer.objectMapper = mapper;
    }

    //socket 打开时的处理
    @OnOpen
    public void onOpen(@PathParam("token") String token, Session session) {
        try {
            if (!SemaphoreUtils.tryAcquire(SEMAPHORE)) {
                WebSocketUsers.sendMessageToUserByText(session, "当前在线人数超过限制：" + MAX_ONLINE_COUNT);
                session.close();
                return;
            }

            Long userId = tokenService.getUserIdByToken(token);

            // 保存用户连接
            WebSocketUsers.put(userId.toString(), session);
            LOGGER.info("用户[{}]建立连接", userId);

            System.out.println("用户"+userId+"登录");

            // 注册用户每天登录信息
            userOnlineTimeService.recordUserLogin(userId);
            // 发送当前在线人数
//            String message = String.format("连接成功，当前在线人数：%d", WebSocketUsers.getOnlineCount());
            WebSocketUsers.sendMessageToUserByText(session, "连接成功");
            System.out.println(String.format("连接成功，当前在线人数：%d", WebSocketUsers.getOnlineCount()));
        } catch (Exception e) {
            LOGGER.error("连接建立失败", e);
            SemaphoreUtils.release(SEMAPHORE);
        }
    }

//    private void checkDependencies() {
//        if (locationService == null || objectMapper == null) {
//            throw new IllegalStateException("必要的依赖未注入，请检查LocationService和ObjectMapper是否已经设置");
//        }
//    }

    // 处理用户发送的消息
    @OnMessage
    public void onMessage(String message, Session session) {
        try {

            String userId = WebSocketUsers.getUserId(session);
            if (userId == null) {
                WebSocketUsers.sendMessageToUserByText(session, "未找到用户信息，请重新连接");
                return;
            }

            LOGGER.info("收到用户[{}]的消息: {}", userId, message);

            HeartbeatMessage heartbeatMessage = objectMapper.readValue(message, HeartbeatMessage.class);

            Long userIdLong = Long.parseLong(userId);
            Long duration = heartbeatMessage.getDuration();

            if (userIdLong == null || duration == null) {

                System.out.println("接收到无效的心跳消息");
                LOGGER.error("接收到无效的心跳消息");
                WebSocketUsers.sendMessageToUserByText(session, "接收到无效的心跳消息");
            }
            else{
                LOGGER.info("用户[{}]发送了心跳消息，时间戳为：{}", userIdLong, duration);
                //更新用户在线时间, duration参数用不到.
                int back = userOnlineTimeService.updateUserHeartbeat(userIdLong, duration);
                if(back>0){
                    WebSocketUsers.sendMessageToUserByText(session, "更新在线时长成功");
                }
                else{
                    WebSocketUsers.sendMessageToUserByText(session, "更新在线时长失败");
                }

            }


        } catch (Exception e) {
            LOGGER.error("处理消息失败", e);
            WebSocketUsers.sendMessageToUserByText(session, "消息处理失败: " + e.getMessage());
        }
    }

    @OnClose
    public void onClose(Session session) {

        String userId = WebSocketUsers.getUserId(session);
        Long userIdLong = Long.parseLong(userId);

        if(userIdLong != null){
            userOnlineTimeService.recordUserLogout(userIdLong);
        }

        WebSocketUsers.remove(session);
        SemaphoreUtils.release(SEMAPHORE);
        LOGGER.info("关闭连接 - {}", session.getId());
    }

    @OnError
    public void onError(Session session, Throwable error) {
        LOGGER.error("WebSocket错误", error);
        WebSocketUsers.remove(session);
        SemaphoreUtils.release(SEMAPHORE);
    }
}
