package com.junmp.jyzb.websocket;


import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.junmp.jyzb.api.bean.query.WsCabinetReq;
import com.junmp.jyzb.entity.Cabinet;
import com.junmp.jyzb.entity.CabinetBox;
import com.junmp.jyzb.service.CabinetBoxService;
import com.junmp.jyzb.service.CabinetService;
import com.junmp.jyzb.utils.DateTimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;


@Component
@ServerEndpoint(value = "/cabinet/ws")
@Slf4j
public class CabinetWebSocketServer {

    private final String CABINET_WEB_KEY = "cabinet_web";

    @Resource
    public CabinetService cabinetService;

    @Resource
    public CabinetBoxService cabinetBoxService;

    /**
     * 每个客户端对应的Session
     */
    private static Map<String, CabinetWebSocketServer> cbWebSessionMap = new ConcurrentHashMap<>();

    private Session cbWebSession;

    /**
     * 建立连接
     *
     * @param session
     */
    @OnOpen
    public void connect(Session session) {
        try {
            this.cbWebSession = session;
            String keyVal = StrUtil.format("{}_{}", CABINET_WEB_KEY, session.getId());
            cbWebSessionMap.putIfAbsent(keyVal, this);
        } catch (Exception ex) {
            log.error("[设备接入异常]|异常信息：{}", ex.getMessage());
        }
    }

    @OnMessage
    public void onMessage(Session session, String message) {
        try {
            log.info("[接收客户端请求]|请求参数：{}", message);
            WsCabinetReq boxData = JSON.parseObject(message, WsCabinetReq.class);
            Cabinet cabinet = cabinetService.getOne(new LambdaQueryWrapper<Cabinet>()
                    .eq(Cabinet::getDevSn, boxData.getSerialNum()));
            List<WsCabinetReq.Box> boxStateList = boxData.getBoxList();
            List<CabinetBox> boxlist = cabinetBoxService.list(new LambdaQueryWrapper<CabinetBox>()
                    .eq(CabinetBox::getCabinetId, cabinet.getId()));

            // 将 boxlist 转换为 Map，以 boxNum 为键
            Map<Integer, CabinetBox> boxMap = boxlist.stream()
                    .collect(Collectors.toMap(CabinetBox::getBoxNo, box -> box));
            List<CabinetBox> updateBoxlist = new ArrayList<>();
            // 比较并修改
            for (WsCabinetReq.Box boxState : boxStateList) {
                Integer boxNum = Integer.valueOf(boxState.getBoxNum());
                CabinetBox cabinetBox = boxMap.get(boxNum);

                if (cabinetBox != null) {
                    // 根据 boxState 中的 state 字段修改 cabinetBox 中的状态
                    cabinetBox.setState(boxState.getState());
                    cabinetBox.setErrorMsg(boxState.getErrorMsg());
                    updateBoxlist.add(cabinetBox);
                    // 可以选择更新其他字段
                    // cabinetBox.setOtherField(...);
                }
            }
            String keyVal = StrUtil.format("{}_{}", CABINET_WEB_KEY, session.getId());
            cabinet.setOnlineState(1);
            cabinet.setUpdateTime(DateTimeUtil.getCurrentDateTime());
            cabinet.setChannelId(keyVal);
            cabinetService.updateById(cabinet);
            cabinetBoxService.updateBatchById(updateBoxlist);

            WsMsgProduce.sendMessage(session, "true");
        } catch (Exception ex) {
            WsMsgProduce.sendMessage(session, "false");
        }
    }


    @OnClose
    public void onClose() {
        try {
            String keyVal = StrUtil.format("{}_{}", CABINET_WEB_KEY, cbWebSession.getId());
            CabinetWebSocketServer oldSession = cbWebSessionMap.get(keyVal);
            if (null != oldSession) {
                Cabinet cabinet = cabinetService.getOne(new LambdaQueryWrapper<Cabinet>()
                        .eq(Cabinet::getChannelId, keyVal));
                cabinet.setOnlineState(0);
                cabinet.setChannelId("");
                cabinet.setUpdateTime(DateTimeUtil.getCurrentDateTime());
                cabinetService.updateById(cabinet);
            }
        } catch (Exception ex) {
            log.error("[Ws断开异常]|异常信息：{}", ex.getMessage());
        }
    }
}
