package cn.iocoder.yudao.module.system.service.websocket;

import cn.hutool.json.JSONObject;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.websocket.WebsocketBaseVO;
import cn.iocoder.yudao.module.system.dal.dataobject.equipment.DistributeRecordDO;
import cn.iocoder.yudao.module.system.service.equipment.DistributeRecordService;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.xingyuv.http.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.REQUEST_FAILURE;

/**
 * websocket Service 实现类
 */
@Service
@Slf4j
public class WebsocketServiceImpl implements WebsocketService{

    @Resource
    private DistributeRecordService recordService;

    @Resource
    private WebSocketSenderApi webSocketSenderApi;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public void sendSn(String deviceNo, Object data, Integer type) {

        String requestId = IdWorker.get32UUID();

        WebsocketBaseVO baseVO = new WebsocketBaseVO()
                .setFrom("")
                .setTo(deviceNo)
                .setExtra(requestId + "_" + getLoginUserId())
                .setData(data);

        JSONObject dataJson = new JSONObject(data);

        // 设置 设备下发记录
        DistributeRecordDO recordDO = new DistributeRecordDO();
        recordDO.setRequestId(requestId);
        recordDO.setDeviceNo(deviceNo);
        recordDO.setUserId(dataJson.get("user_id") == null ? getLoginUserId() : Long.valueOf(dataJson.get("user_id").toString()));
        recordDO.setType(type);
        recordDO.setResult("通讯失败");

        // 更新下发记录信息
        recordService.createDistributeRecord(Collections.singletonList(recordDO));

        // 设备租户ID
        TenantContextHolder.setTenantId(1L);

        if (StringUtil.isEmpty(stringRedisTemplate.opsForValue().get(deviceNo))) {
            stringRedisTemplate.opsForValue().set(deviceNo, "true");
        }
        // 发送命令给设备
        webSocketSenderApi.sendSN(deviceNo, "attendance-message-send", JsonUtils.toJsonString(baseVO));

        Long startTime = System.currentTimeMillis();
        while (true) {
            String result = stringRedisTemplate.opsForValue().get(deviceNo);
            if (StringUtil.isEmpty(result)) {
                return;
            }

            if ("false".equals(result)) {
                String msg = stringRedisTemplate.opsForValue().get(deviceNo + "msg").split("_")[1];

                // 清楚 redis缓存
                stringRedisTemplate.delete(deviceNo);
                stringRedisTemplate.delete(deviceNo + "msg");

                throw new RuntimeException(msg);
            }

            try {
                Thread.sleep(1000L);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            Long currentTime = System.currentTimeMillis();
            if (currentTime - startTime > 30000) {

                throw exception(REQUEST_FAILURE);
            }
        }
    }
}
