package com.junmp.jyzb.websocket;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.junmp.jyzb.cache.OnlineRedisCache;
import com.junmp.jyzb.entity.Cabinet;
import com.junmp.jyzb.entity.Temp.OnlineState;
import com.junmp.jyzb.service.CabinetService;
import com.junmp.v2.ws.api.enums.ClientMsgType;
import com.junmp.v2.ws.api.enums.ServerMsgType;
import com.junmp.v2.ws.api.enums.SysMsgTypeEnum;
import com.junmp.v2.ws.api.message.WsCallbackApi;
import com.junmp.v2.ws.api.session.bean.WsSession;
import com.junmp.v2.ws.bean.WsMsgDto;
import com.junmp.v2.ws.channel.WsSessionContainer;
import com.junmp.v2.ws.message.WsMessageHandle;
import com.junmp.v2.ws.session.WsSessionHandle;
import io.jsonwebtoken.JwtException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.time.Instant;


@Component
@ServerEndpoint("/warehouse/{data}")
public class WarehouseWebSocketServer {
    private static final Logger log = LoggerFactory.getLogger(com.junmp.v2.ws.server.ScreenWebSocketServer.class);
    @Resource
    public CabinetService cabinetService;
    @Resource
    private OnlineRedisCache onlineRedisCache;

    public WarehouseWebSocketServer() {
    }

    @OnOpen
    public void onOpen(Session session, @PathParam("data") String data) {
        String userId = null;

        try {
            // 获取当前时间的时间戳
            Instant now = Instant.now();

            // 转换为long类型
            long timestamp = now.toEpochMilli();

                Cabinet cabinet=cabinetService.getOne(new LambdaQueryWrapper<Cabinet>()
                        .eq(Cabinet::getCabinetNum, data));
                cabinet.setOnlineState(1);
                cabinet.setUpdateTime(DateTime.now());
//                cabinetService.updateById(cabinet);
//                //将数据放入redis
//                onlineRedisCache.addSessionValue(session.getId(),type,typeId,timestamp);


        } catch (JwtException var15) {
            log.error("建立连接异常>>" + var15.getMessage());

            try {
                session.close();
                log.warn("因连接失败，会话自动关闭");
            } catch (IOException var14) {
                var14.printStackTrace();
                log.error("会话关闭异常>>" + var14.getMessage());
            }
        }

        WsSessionContainer wsContainer = new WsSessionContainer(session);
        WsSession<WsSessionContainer> socketSession = new WsSession();
        WsMsgDto replyMsg = new WsMsgDto();
        boolean var13 = false;

        try {
            var13 = true;
            replyMsg.setServerMsgType(ServerMsgType.REPLY_MSG_TYPE.getCode());
//            replyMsg.setToUserId(userId);
            replyMsg.setData(session.getId());
            socketSession.setSessionId(session.getId());
            socketSession.setUserId(userId);
            socketSession.setWsApi(wsContainer);
            socketSession.setToken(data);
//            socketSession.setData();
            socketSession.setConnectionTime(System.currentTimeMillis());
            WsSessionHandle.addWsSession(socketSession);
            var13 = false;
        } finally {
            if (var13) {
                wsContainer.writeAndFlush(replyMsg);
                WsCallbackApi wsCallbackApi = WsMessageHandle.getWsCallback(SysMsgTypeEnum.LISTENER_ON_OPEN.getCode());
                if (ObjectUtil.isNotEmpty(wsCallbackApi)) {
                    wsCallbackApi.callback(SysMsgTypeEnum.LISTENER_ON_OPEN.getCode(), (Object)null, socketSession);
                }

                log.info("已建立连接");
            }
        }

        wsContainer.writeAndFlush(replyMsg);
        WsCallbackApi wsCallbackApi = WsMessageHandle.getWsCallback(SysMsgTypeEnum.LISTENER_ON_OPEN.getCode());
        if (ObjectUtil.isNotEmpty(wsCallbackApi)) {
            wsCallbackApi.callback(SysMsgTypeEnum.LISTENER_ON_OPEN.getCode(), (Object)null, socketSession);
        }

        log.info("已建立连接");
    }

    @OnMessage
    public void onMessage(String message, Session channel) {
        WsMsgDto wsMsgDto = (WsMsgDto) JSON.parseObject(message, WsMsgDto.class);
        WsSession<WsSessionContainer> wsSession = WsSessionHandle.getSessionBySessionId(channel.getId());
        if (ObjectUtil.isNotEmpty(wsSession) && ClientMsgType.USER_HEART.getCode().equals(wsMsgDto.getClientMsgType())) {
            log.info(StrUtil.format("来自与客户端[{}]的心跳消息。", new Object[]{wsMsgDto.getFromUserId()}));
            if (ObjectUtil.isNotEmpty(wsSession)) {
                wsSession.setLastActiveTime(System.currentTimeMillis());
            }

        } else if (!ObjectUtil.isEmpty(wsMsgDto.getFromUserId())) {
            if (ObjectUtil.isNotEmpty(wsSession)) {
                wsSession.setLastActiveTime(System.currentTimeMillis());
                WsCallbackApi callbackApi;
                if (ClientMsgType.OPEN_AI_TYPE.getCode().equals(wsMsgDto.getClientMsgType())) {
                    log.info(StrUtil.format("来自与客户端[{}]调用OpenAi的消息。", new Object[]{wsMsgDto.getFromUserId()}));
                    callbackApi = (WsCallbackApi) SpringUtil.getBean(WsCallbackApi.class);
                    if (ObjectUtil.isNull(callbackApi)) {
                        log.warn("回调WsCallbackApi未注册.");
                    } else {
                        callbackApi.callback(wsMsgDto.getClientMsgType(), wsMsgDto.getData(), wsSession);
                    }
                } else {
                    callbackApi = WsMessageHandle.getWsCallback(wsMsgDto.getClientMsgType());
                    if (ObjectUtil.isNotEmpty(callbackApi)) {
                        callbackApi.callback(wsMsgDto.getClientMsgType(), wsMsgDto, wsSession);
                    } else {
                        log.warn("未知的消息类型");
                        channel.getAsyncRemote().sendText("{\"serverMsgType\":\"未知的消息类型\"}");
                    }
                }
            }

        }
    }

    @OnClose
    public void onClose(Session session) {
        try {
            WsSession<WsSessionContainer> wsSession = WsSessionHandle.getSessionBySessionId(session.getId());
            WsCallbackApi wsCallbackApi = WsMessageHandle.getWsCallback(SysMsgTypeEnum.LISTENER_ON_CLOSE.getCode());
            if (ObjectUtil.isNotEmpty(wsSession) && ObjectUtil.isNotEmpty(wsCallbackApi)) {
                OnlineState os=onlineRedisCache.getDataValue(wsSession.getSessionId());
                String type= os.getType();
                String typeId=os.getTypeId();
                if (type.equals("cabinet"))//警柜断开连接
                {
                    Cabinet cabinet=cabinetService.getOne(new LambdaQueryWrapper<Cabinet>()
                            .eq(Cabinet::getCabinetNum, typeId));
                    cabinet.setOnlineState(0);
                    cabinet.setUpdateTime(DateTime.now());
                    cabinetService.updateById(cabinet);
                    onlineRedisCache.remove(wsSession.getSessionId());
                } else if (type.equals("warehouse")) {//仓库主机已连接

                }
                wsCallbackApi.callback(SysMsgTypeEnum.LISTENER_ON_CLOSE.getCode(), (Object)null, wsSession);
            }

        } finally {
            WsSessionHandle.delById(session.getId());
            log.warn("会话已关闭");
        }

    }

    @OnError
    public void onError(Session session, Throwable error) {
        WsSession<WsSessionContainer> wsSession = WsSessionHandle.getSessionBySessionId(session.getId());
        WsCallbackApi wsCallbackApi = WsMessageHandle.getWsCallback(SysMsgTypeEnum.LISTENER_ON_ERROR.getCode());
        if (ObjectUtil.isNotEmpty(wsCallbackApi)) {
            wsCallbackApi.callback(SysMsgTypeEnum.LISTENER_ON_ERROR.getCode(), (Object)null, wsSession);
        }

    }
}