package com.usky.iot.service.impl;


import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mysql.cj.x.protobuf.MysqlxDatatypes;
import com.usky.backend.client.DataQueryClient;
import com.usky.backend.client.DeviceDataClient;
import com.usky.backend.domain.*;
import com.usky.backend.domain.response.DataRealTimeResponseVO;
import com.usky.common.core.bean.ApiResult;
import com.usky.common.core.bean.CommonPage;
import com.usky.common.core.exception.BusinessException;
import com.usky.common.core.util.BeanMapperUtils;
import com.usky.common.core.util.UUIDUtils;
import com.usky.common.mybatis.core.AbstractCrudService;
import com.usky.demo.RemoteTsdbProxyService;
import com.usky.demo.domain.LastInnerQueryVO;
import com.usky.demo.domain.LastInnerResultVO;
import com.usky.iot.domain.*;
import com.usky.common.security.utils.SecurityUtils;
import com.usky.iot.mapper.DmpDeviceInfoMapper;
import com.usky.iot.mapper.DmpProductAttributeMapper;
import com.usky.iot.mapper.DmpProductInfoMapper;
import com.usky.iot.service.*;
import com.usky.iot.service.config.DeviceOperate;
import com.usky.iot.service.enums.TopicInfo;
import com.usky.iot.service.vo.*;
import com.usky.transfer.RemoteTransferService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.DecimalFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 设备信息表 服务实现类
 * </p>
 *
 * @author ya
 * @since 2022-10-08
 */
@Slf4j
@Service
public class DmpDeviceInfoServiceImpl extends AbstractCrudService<DmpDeviceInfoMapper, DmpDeviceInfo> implements DmpDeviceInfoService {
    @Autowired
    private DmpDeviceStatusService dmpDeviceStatusService;

    @Autowired
    private DmpProductAttributeService dmpProductAttributeService;

    @Autowired
    private BaseFacilityDeviceService baseFacilityDeviceService;

    @Autowired
    private DeviceDataClient deviceDataClient;

    @Autowired
    private DataQueryClient dataQueryClient;

    @Autowired
    private RemoteTransferService remoteTransferService;

    @Autowired
    private RemoteTsdbProxyService remoteTsdbProxyService;

    @Autowired
    private DmpProductAttributeMapper dmpProductAttributeMapper;

    @Autowired
    private BaseSpaceGatewayService baseSpaceGatewayService;

    @Autowired
    private DeviceOperate deviceOperate;

    @Autowired
    private DmpProductInfoMapper dmpProductInfoMapper;

    @Autowired
    private DmpDeviceTypeService dmpDeviceTypeService;

    private static final String ALARM_HTTP_URL = "/service-alarm/baseAlarm/alarmInfo";


    @Override
    public Map<String, Object> control(String productCode, String deviceUuid, String commandCode, String commandValue, String domain, Long userId, String userName, Integer categoryType, String gatewayUuid) {
        Integer tenantId;
        long commandUserId;
        String commandUserName;
        if (StringUtils.isNotBlank(domain)) {
            tenantId = baseMapper.sysTenantId(domain);
            commandUserId = userId;
            commandUserName = userName;
        } else {
            tenantId = SecurityUtils.getTenantId();
            commandUserId = SecurityUtils.getUserId();
            commandUserName = SecurityUtils.getUsername();
        }
//
//        //人员设备权限校验，校验通过，可以下发命令控制设备
//        Integer fid = baseMapper.getMeetingFaceData(commandUserId);
//        if(fid == null){
//            throw new BusinessException("人脸卡号信息未注册");
//        }
//        Integer[] deviceFid = baseMapper.getMeetingFaceDeviceList(fid);
//        if(deviceFid.length == 0){
//            throw new BusinessException("人员未绑定设备，请检查");
//        }
//
//        LambdaQueryWrapper<DmpDeviceInfo> queryWrapper = Wrappers.lambdaQuery();
//        queryWrapper.select(DmpDeviceInfo::getId)
//                .eq(DmpDeviceInfo::getDeviceId,deviceUuid)
//                .eq(DmpDeviceInfo::getDeleteFlag,0);
//        DmpDeviceInfo one = this.getOne(queryWrapper);
//        if(one != null){
//            boolean exist = Arrays.asList(deviceFid).contains(one.getId());
//            if(!exist){
//                throw new BusinessException("暂无权限");
//            }
//        }else{
//            throw new BusinessException("设备未注册，请先注册");
//        }


        Map<String, Object> map = new HashMap<>();
        map.put("method", "control");
        map.put("deviceUuid", deviceUuid);
        Map<String, Object> map1 = new HashMap<>();
        map1.put("commandCode", commandCode);
        map1.put("commandValue", commandValue);
        map.put("params", map1);

        if (categoryType == 3) {
            return remoteTransferService.deviceControl(productCode, gatewayUuid, JSON.toJSONString(map), tenantId, commandUserId, commandUserName);
        } else {
            return remoteTransferService.deviceControl(productCode, deviceUuid, JSON.toJSONString(map), tenantId, commandUserId, commandUserName);
        }

    }

    @Override
    public CommonPage<DmpTopicResponseVO> topic(DmpTopicRequestVO requestVO) {

        String productCode = requestVO.getProductCode();
        String deviceId = requestVO.getDeviceId();
        String deviceUuid = requestVO.getDeviceUuid();
        String deviceName = requestVO.getDeviceName();
        String simCode = requestVO.getSimCode();
        String installAddress = requestVO.getInstallAddress();
        Integer productId = requestVO.getProductId();
        Integer pageNum = requestVO.getPageNum();
        Integer pageSize = requestVO.getPageSize();
        Integer categoryType = requestVO.getCategoryType();


        pageNum = (pageNum != null) ? pageNum : 1;
        pageSize = (pageSize != null) ? pageSize : 10;

        List<DmpTopicResponseVO> responseVOList = new ArrayList<>();
        String topicType = requestVO.getTopicType();

        if (topicType == null) {
            if (StringUtils.isBlank(productCode)) {
                throw new BusinessException("产品编码“productCode”不能为空！");
            } else if (StringUtils.isBlank(deviceId)) {
                throw new BusinessException("设备编号“deviceId”不能为空！");
            } else if (StringUtils.isBlank(deviceUuid)) {
                throw new BusinessException("设备uuid“deviceUuid“不能为空！");
            }

            if (categoryType == 1) {
                DmpTopicResponseVO add = new DmpTopicResponseVO();
                add.setTopic("/usky/devices/" + deviceUuid + "/add");
                add.setPublisher("普通设备");
                add.setSubscriber("物联网平台");
                add.setRemarks("添加普通设备");
                responseVOList.add(add);

                DmpTopicResponseVO info = new DmpTopicResponseVO();
                info.setTopic("/usky/devices/" + deviceUuid + "/info");
                info.setPublisher("普通设备");
                info.setSubscriber("物联网平台");
                info.setRemarks("普通设备上报数据");
                responseVOList.add(info);

                DmpTopicResponseVO control = new DmpTopicResponseVO();
                control.setTopic("/usky/devices/" + deviceUuid + "/control");
                control.setPublisher("物联网平台");
                control.setSubscriber("普通设备");
                control.setRemarks("物联网平台给普通设备下发命令");
                responseVOList.add(control);

                DmpTopicResponseVO controlResponse = new DmpTopicResponseVO();
                controlResponse.setTopic("/usky/devices/" + deviceUuid + "/controlResponse");
                controlResponse.setPublisher("普通设备");
                controlResponse.setSubscriber("物联网平台");
                controlResponse.setRemarks("普通设备返回给物联网平台的命令响应");
                responseVOList.add(controlResponse);
            } else {
                String gatewayUuid = requestVO.getGatewayUuid();
                if (categoryType == 2) {
                    gatewayUuid = requestVO.getDeviceUuid();
                }

                DmpTopicResponseVO add = new DmpTopicResponseVO();
                add.setTopic("/usky/devices/" + gatewayUuid + "/add");
                add.setPublisher("网关设备");
                add.setSubscriber("物联网平台");
                add.setRemarks("网关设备添加子设备");
                responseVOList.add(add);

                DmpTopicResponseVO info = new DmpTopicResponseVO();
                info.setTopic("/usky/devices/" + gatewayUuid + "/info");
                info.setPublisher("网关设备");
                info.setSubscriber("物联网平台");
                info.setRemarks("网关设备上报数据");
                responseVOList.add(info);

                DmpTopicResponseVO control = new DmpTopicResponseVO();
                control.setTopic("/usky/devices/" + gatewayUuid + "/control");
                control.setPublisher("物联网平台");
                control.setSubscriber("网关设备");
                control.setRemarks("物联网平台给网关设备下发命令");
                responseVOList.add(control);

                DmpTopicResponseVO controlResponse = new DmpTopicResponseVO();
                controlResponse.setTopic("/usky/devices/" + gatewayUuid + "/controlResponse");
                controlResponse.setPublisher("网关设备");
                controlResponse.setSubscriber("物联网平台");
                controlResponse.setRemarks("网关设备返回给物联网平台的命令响应");
                responseVOList.add(controlResponse);
            }

//            DmpTopicResponseVO add = new DmpTopicResponseVO();
//            add.setTopic("/usky/devices/" + deviceUuid + "/" + TopicInfo.ADD_REMARKS.getLetter());
//            add.setPublisher(TopicInfo.GATEWAY_DEVICE.getValue());
//            add.setSubscriber(TopicInfo.IOT_PLATFORM.getValue());
//            add.setRemarks(TopicInfo.ADD_REMARKS.getValue());
//            responseVOList.add(add);
//
//            DmpTopicResponseVO info = new DmpTopicResponseVO();
//            info.setTopic("/usky/devices/" + deviceUuid + "/" + TopicInfo.INFO_REMARKS.getLetter());
//            info.setPublisher(TopicInfo.GATEWAY_DEVICE.getValue());
//            info.setSubscriber(TopicInfo.IOT_PLATFORM.getValue());
//            info.setRemarks(TopicInfo.INFO_REMARKS.getValue());
//            responseVOList.add(info);
//
//            DmpTopicResponseVO control = new DmpTopicResponseVO();
//            control.setTopic("/usky/devices/" + deviceUuid + "/" + TopicInfo.CONTROL_REMARKS.getLetter());
//            control.setSubscriber(TopicInfo.GATEWAY_DEVICE.getValue());
//            control.setPublisher(TopicInfo.IOT_PLATFORM.getValue());
//            control.setRemarks(TopicInfo.CONTROL_REMARKS.getValue());
//            responseVOList.add(control);
//
//            DmpTopicResponseVO controlResponse = new DmpTopicResponseVO();
//            controlResponse.setTopic("/usky/devices/" + deviceUuid + "/" + TopicInfo.CONTROL_RESPONSE_REMARKS.getLetter());
//            controlResponse.setPublisher(TopicInfo.GATEWAY_DEVICE.getValue());
//            controlResponse.setSubscriber(TopicInfo.IOT_PLATFORM.getValue());
//            controlResponse.setRemarks(TopicInfo.CONTROL_RESPONSE_REMARKS.getValue());
//            responseVOList.add(controlResponse);

        } else {
            if (categoryType == 1) {
                switch (topicType) {
                    case "add":
                    /*if (StringUtils.isBlank(productCode)) {
                        throw new BusinessException("产品编码“productCode”不能为空！");
                    } else if (StringUtils.isBlank(deviceId)) {
                        throw new BusinessException("设备编号“deviceId”不能为空！");
                    } else if (StringUtils.isBlank(deviceName)) {
                        throw new BusinessException("设备名“deviceName“不能为空！");
                    }

                    DmpTopicResponseVO add = new DmpTopicResponseVO();
                    add.setTopic("/" + productCode + "/" + deviceId + "/" + TopicInfo.ADD_REMARKS.getLetter());
                    add.setPublisher(TopicInfo.GATEWAY_DEVICE.getValue());
                    add.setSubscriber(TopicInfo.IOT_PLATFORM.getValue());
                    add.setRemarks(TopicInfo.ADD_REMARKS.getValue());

                    // 组装topicPayload
                    JSONObject topicPayloadJson = new JSONObject();
                    topicPayloadJson.put("productCode", productCode);
                    topicPayloadJson.put("deviceId", deviceId);
                    topicPayloadJson.put("deviceName", deviceName);
                    if (!StringUtils.isBlank(simCode)) {
                        topicPayloadJson.put("simCode", simCode);
                    }
                    if (!StringUtils.isBlank(installAddress)) {
                        topicPayloadJson.put("installAddress", installAddress);
                    }
                    String topicPayload = topicPayloadJson.toString();
                    add.setTopicPayload(topicPayload);
                    responseVOList.add(add);*/
                        break;
                    case "info":
                        if (StringUtils.isBlank(productCode)) {
                            throw new BusinessException("产品编码“productCode”不能为空！");
                        } else if (productId == null) {
                            throw new BusinessException("产品ID“productId“不能为空！");
                        } else if (StringUtils.isBlank(deviceId)) {
                            throw new BusinessException("设备编号“deviceId”不能为空！");
                        }

                        DmpTopicResponseVO info = new DmpTopicResponseVO();
                        info.setTopic("/usky/devices/" + deviceUuid + "/info");
                        info.setPublisher("普通设备");
                        info.setSubscriber("物联网平台");
                        info.setRemarks("普通设备上报数据");

                        // 组装topicPayload
                        JSONObject infoPayloadJson = new JSONObject();
                        infoPayloadJson.put("productCode", productCode);
                        infoPayloadJson.put("deviceUuid", deviceUuid);
                        Long timestamp = System.currentTimeMillis();
                        infoPayloadJson.put("timestamp", timestamp);

                        JSONObject metricsJson = new JSONObject();
                        List<DmpProductAttribute> productAttributeList = getProductAttributeList(productId);
                        for (DmpProductAttribute productAttribute : productAttributeList) {
                            metricsJson.put(productAttribute.getAttributeCode(), productAttribute.getMaximum());
                        }
                        infoPayloadJson.put("metrics", metricsJson);

                        JSONObject tagsJson = new JSONObject();
                        tagsJson.put("device_id", deviceId);
                        infoPayloadJson.put("tags", tagsJson);
                        String infoPayload = infoPayloadJson.toString();
                        info.setTopicPayload(infoPayload);
                        info.setProductAttributeList(productAttributeList);
                        responseVOList.add(info);
                        break;
                    case "control":
                    /*if (StringUtils.isBlank(deviceUuid)) {
                        throw new BusinessException("设备uuid“deviceUuid“不能为空！");
                    }else if (StringUtils.isBlank(productCode)){
                        throw new BusinessException("产品编码“productCode”不能为空！");
                    }

                    DmpTopicResponseVO control = new DmpTopicResponseVO();
                    control.setTopic("/" + deviceUuid + "/" + TopicInfo.CONTROL_REMARKS.getLetter());
                    control.setPublisher(TopicInfo.IOT_PLATFORM.getValue());
                    control.setSubscriber(TopicInfo.GATEWAY_DEVICE.getValue());
                    control.setRemarks(TopicInfo.CONTROL_REMARKS.getValue());

                    // 组装topicPayload
                    JSONObject controlPayloadJson = new JSONObject();

                    responseVOList.add(control);*/
                        break;
                    case "controlResponse":
                        break;
                    default:
                        throw new BusinessException("topicType参数错误！");
                }
            } else {
                String gatewayUuid = requestVO.getGatewayUuid();
                if (categoryType == 2) {
                    gatewayUuid = requestVO.getDeviceUuid();
                }
                switch (topicType) {
                    case "add":
                    /*if (StringUtils.isBlank(productCode)) {
                        throw new BusinessException("产品编码“productCode”不能为空！");
                    } else if (StringUtils.isBlank(deviceId)) {
                        throw new BusinessException("设备编号“deviceId”不能为空！");
                    } else if (StringUtils.isBlank(deviceName)) {
                        throw new BusinessException("设备名“deviceName“不能为空！");
                    }

                    DmpTopicResponseVO add = new DmpTopicResponseVO();
                    add.setTopic("/" + productCode + "/" + deviceId + "/" + TopicInfo.ADD_REMARKS.getLetter());
                    add.setPublisher(TopicInfo.GATEWAY_DEVICE.getValue());
                    add.setSubscriber(TopicInfo.IOT_PLATFORM.getValue());
                    add.setRemarks(TopicInfo.ADD_REMARKS.getValue());

                    // 组装topicPayload
                    JSONObject topicPayloadJson = new JSONObject();
                    topicPayloadJson.put("productCode", productCode);
                    topicPayloadJson.put("deviceId", deviceId);
                    topicPayloadJson.put("deviceName", deviceName);
                    if (!StringUtils.isBlank(simCode)) {
                        topicPayloadJson.put("simCode", simCode);
                    }
                    if (!StringUtils.isBlank(installAddress)) {
                        topicPayloadJson.put("installAddress", installAddress);
                    }
                    String topicPayload = topicPayloadJson.toString();
                    add.setTopicPayload(topicPayload);
                    responseVOList.add(add);*/
                        break;
                    case "info":
                        if (StringUtils.isBlank(productCode)) {
                            throw new BusinessException("产品编码“productCode”不能为空！");
                        } else if (productId == null) {
                            throw new BusinessException("产品ID“productId“不能为空！");
                        } else if (StringUtils.isBlank(deviceId)) {
                            throw new BusinessException("设备编号“deviceId”不能为空！");
                        }

                        DmpTopicResponseVO info = new DmpTopicResponseVO();
                        info.setTopic("/usky/devices/" + gatewayUuid + "/info");
                        info.setPublisher("网关设备");
                        info.setSubscriber("物联网平台");
                        info.setRemarks("网关设备上报数据");

                        // 组装topicPayload
                        JSONObject infoPayloadJson = new JSONObject();
                        infoPayloadJson.put("productCode", productCode);
                        infoPayloadJson.put("deviceUuid", deviceUuid);
                        Long timestamp = System.currentTimeMillis();
                        infoPayloadJson.put("timestamp", timestamp);

                        JSONObject metricsJson = new JSONObject();
                        List<DmpProductAttribute> productAttributeList = getProductAttributeList(productId);
                        for (DmpProductAttribute productAttribute : productAttributeList) {
                            metricsJson.put(productAttribute.getAttributeCode(), productAttribute.getMaximum());
                        }
                        infoPayloadJson.put("metrics", metricsJson);

                        JSONObject tagsJson = new JSONObject();
                        tagsJson.put("device_id", deviceId);
                        infoPayloadJson.put("tags", tagsJson);
                        String infoPayload = infoPayloadJson.toString();
                        info.setTopicPayload(infoPayload);
                        info.setProductAttributeList(productAttributeList);
                        responseVOList.add(info);
                        break;
                    case "control":
                    /*if (StringUtils.isBlank(deviceUuid)) {
                        throw new BusinessException("设备uuid“deviceUuid“不能为空！");
                    }else if (StringUtils.isBlank(productCode)){
                        throw new BusinessException("产品编码“productCode”不能为空！");
                    }

                    DmpTopicResponseVO control = new DmpTopicResponseVO();
                    control.setTopic("/" + deviceUuid + "/" + TopicInfo.CONTROL_REMARKS.getLetter());
                    control.setPublisher(TopicInfo.IOT_PLATFORM.getValue());
                    control.setSubscriber(TopicInfo.GATEWAY_DEVICE.getValue());
                    control.setRemarks(TopicInfo.CONTROL_REMARKS.getValue());

                    // 组装topicPayload
                    JSONObject controlPayloadJson = new JSONObject();

                    responseVOList.add(control);*/
                        break;
                    case "controlResponse":
                        break;
                    default:
                        throw new BusinessException("topicType参数错误！");
                }
            }
        }

        int fromIndex = (pageNum - 1) * pageSize;
        int toIndex = Math.min(fromIndex + pageSize, responseVOList.size());
        List<DmpTopicResponseVO> paginatedList = responseVOList.subList(fromIndex, toIndex);

        IPage<DmpTopicResponseVO> page = new Page<>(pageNum, pageSize);
        page.setRecords(paginatedList);
        page.setTotal(responseVOList.size());
        return ToCommonPage(page);
    }

    /**
     * 获取产品属性列表
     *
     * @param productId
     * @return
     */
    private List<DmpProductAttribute> getProductAttributeList(Integer productId) {
        LambdaQueryWrapper<DmpProductAttribute> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DmpProductAttribute::getProductId, productId)
                .eq(DmpProductAttribute::getDeleteFlag, 0);
        return dmpProductAttributeMapper.selectList(queryWrapper);
    }

    /**
     * 获取设备告警信息
     *
     * @param deviceId
     * @param productCode
     * @return
     */
    @Override
    public DmpHttpAlarmResponseVO alarmResponse(String deviceId, String productCode) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime now = LocalDateTime.now();
        String alarmTime = now.format(formatter);

        DmpHttpAlarmResponseVO responseVO = new DmpHttpAlarmResponseVO();
        JSONObject alarmPayloadJson = new JSONObject();
        alarmPayloadJson.put("productCode", productCode);
        alarmPayloadJson.put("deviceId", deviceId);
        alarmPayloadJson.put("alarmTime", alarmTime);
        alarmPayloadJson.put("alarmType", "311");
        alarmPayloadJson.put("alarmObject", "烟雾报警");
        alarmPayloadJson.put("alarmData", "0");
        alarmPayloadJson.put("alarmAttribute", "烟雾报警");
        alarmPayloadJson.put("alarmContent", "烟感");
        alarmPayloadJson.put("alarmGrade", 1);
        alarmPayloadJson.put("alarmAddress", "上海市青浦区华徐公路628号C幢");
        String alarmPayload = alarmPayloadJson.toString();
        responseVO.setAlarmPayload(alarmPayload);
        responseVO.setAlarmHttpUrl(ALARM_HTTP_URL);
        return responseVO;
    }

    @Override
    public void add(DmpDeviceInfo dmpDeviceInfo) {
        if (checkNameUnique(dmpDeviceInfo)) {
            throw new BusinessException("新增设备信息'" + dmpDeviceInfo.getDeviceId() + "'失败，设备信息已存在");
        }
        List<DmpProductInfo> list = baseMapper.getProductInfo(dmpDeviceInfo.getProductCode());
        if (CollectionUtils.isNotEmpty(list)) {
            dmpDeviceInfo.setDeviceType(list.get(0).getDeviceType());
            dmpDeviceInfo.setProductId(list.get(0).getId());
            dmpDeviceInfo.setCreatedBy(SecurityUtils.getUsername());
            dmpDeviceInfo.setCreatedTime(LocalDateTime.now());
            dmpDeviceInfo.setTenantId(SecurityUtils.getTenantId());

            if(dmpDeviceInfo.getServiceStatus() == null) {
                dmpDeviceInfo.setServiceStatus(1);
            }

            if (StringUtils.isBlank(dmpDeviceInfo.getDeviceUuid())) {
                dmpDeviceInfo.setDeviceUuid(UUIDUtils.uuid().substring(0, 16));
            }
            this.save(dmpDeviceInfo);

            remoteTransferService.deleteDeviceCache(dmpDeviceInfo.getProductCode());

            DmpDeviceStatus dmpDeviceStatus = new DmpDeviceStatus();
            dmpDeviceStatus.setDeviceId(dmpDeviceInfo.getDeviceId());
            dmpDeviceStatus.setProductId(dmpDeviceInfo.getProductId());
            dmpDeviceStatus.setDeviceStatus(2);
            dmpDeviceStatus.setLastOfflineTime(LocalDateTime.now());
            dmpDeviceStatus.setProductCode(dmpDeviceInfo.getProductCode());
            dmpDeviceStatus.setDeviceUuid(dmpDeviceInfo.getDeviceUuid());
            dmpDeviceStatusService.save(dmpDeviceStatus);
        } else {
            throw new BusinessException("新增设备信息'" + dmpDeviceInfo.getDeviceId() + "'失败，无对应产品信息");
        }
    }

    @Override
    public void update(DmpDeviceInfo dmpDeviceInfo) {
        dmpDeviceInfo.setUpdatedBy(SecurityUtils.getUsername());
        dmpDeviceInfo.setUpdatedTime(LocalDateTime.now());
        if (checkNameUnique(dmpDeviceInfo)) {
            throw new BusinessException("修改设备信息'" + dmpDeviceInfo.getDeviceId() + "'失败，设备信息已存在");
        }
        this.updateById(dmpDeviceInfo);

    }

    @Override
    public boolean checkNameUnique(DmpDeviceInfo dmpDeviceInfo) {
        Integer id = null == dmpDeviceInfo.getId() ? -1 : dmpDeviceInfo.getId();
        LambdaQueryWrapper<DmpDeviceInfo> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper
                .eq(DmpDeviceInfo::getDeviceId, dmpDeviceInfo.getDeviceId())
                .eq(DmpDeviceInfo::getProductCode, dmpDeviceInfo.getProductCode())
                .eq(DmpDeviceInfo::getDeleteFlag, 0)
                .eq(DmpDeviceInfo::getTenantId, SecurityUtils.getTenantId());
        DmpDeviceInfo one = this.getOne(queryWrapper);
        return null != one && !Objects.equals(one.getId(), id);
    }

    @Override
    public boolean checkNameUnique1(DmpDeviceInfo dmpDeviceInfo, Integer tenantId) {
        Integer id = null == dmpDeviceInfo.getId() ? -1 : dmpDeviceInfo.getId();
        LambdaQueryWrapper<DmpDeviceInfo> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper
                .eq(DmpDeviceInfo::getDeviceId, dmpDeviceInfo.getDeviceId())
                .eq(DmpDeviceInfo::getProductCode, dmpDeviceInfo.getProductCode())
                .eq(DmpDeviceInfo::getDeleteFlag, 0)
                .eq(DmpDeviceInfo::getTenantId, tenantId);
        DmpDeviceInfo one = this.getOne(queryWrapper);
        return null != one && !Objects.equals(one.getId(), id);
    }

    @Override
    public void deviceStatus() {
        log.info("设备状态 start");
        deviceOperate.updateDeviceStatus();
        log.info("设备状态 end");
    }

    @Override
    public void updateDeviceStatus(LastInnerQueryVO queryVO) {
        ApiResult<List<LastInnerResultVO>> lastApi = remoteTsdbProxyService.queryLastDeviceData(queryVO);
        List<LastInnerResultVO> list = lastApi != null ? lastApi.getData() : null;
        if (CollectionUtils.isNotEmpty(list)) {
            for (int i = 0; i < list.size(); i++) {
                if (Objects.nonNull(list.get(i).getMetrics())) {
                    String deviceuuid = list.get(i).getDeviceuuid();
                    LocalDateTime lTime = Instant.ofEpochMilli(Long.valueOf(list.get(i).getMetrics().get("realtime").toString())).atZone(ZoneOffset.ofHours(8)).toLocalDateTime();
                    String date = lTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                    String currentDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                    LambdaUpdateWrapper<DmpDeviceStatus> updateWrapper = Wrappers.lambdaUpdate();
                    if (date.equals(currentDate)) {
                        updateWrapper.set(DmpDeviceStatus::getDeviceStatus, 1)  // 设备在线
                                .set(DmpDeviceStatus::getLastOnlineTime, lTime)
                                .eq(DmpDeviceStatus::getDeviceUuid, deviceuuid);

                    } else {
                        updateWrapper.set(DmpDeviceStatus::getDeviceStatus, 2)  // 设备离线
                                .set(DmpDeviceStatus::getLastOnlineTime, lTime)
                                .eq(DmpDeviceStatus::getDeviceUuid, deviceuuid);

                    }
                    dmpDeviceStatusService.update(updateWrapper);
                }

            }

        }
    }

    @Override
    public CommonPage<DmpDeviceInfo> page(DmpDeviceInfoRequest diRequest) {
        List<DmpDeviceInfo> list = new ArrayList<>();
        Integer total = 0;
        Integer pageCurrent = diRequest.getCurrent();
        Integer pageSize = diRequest.getSize();
        IPage<DmpDeviceInfo> page = new Page<>(pageCurrent, pageSize);

        List<String> gatewayUuidList = new ArrayList<>();
        if (diRequest.getSpaceId() != null) {
            LambdaQueryWrapper<BaseSpaceGateway> spaceGatewayLambdaQueryWrapper = Wrappers.lambdaQuery();
            spaceGatewayLambdaQueryWrapper.eq(BaseSpaceGateway::getSpaceId, diRequest.getSpaceId());
            gatewayUuidList = baseSpaceGatewayService.list(spaceGatewayLambdaQueryWrapper).stream().map(BaseSpaceGateway::getGatewayUuid).collect(Collectors.toList());
        }
        if(StringUtils.isNotBlank(diRequest.getGatewayUuid())){
            gatewayUuidList.add(diRequest.getGatewayUuid());
        }

        if (diRequest.getDeviceStatus() != null) {
            if (StringUtils.isNotBlank(diRequest.getDeviceId()) || StringUtils.isNotBlank(diRequest.getDeviceUuid()) || StringUtils.isNotBlank(diRequest.getDeviceName()) || diRequest.getProductId() != null || CollectionUtils.isNotEmpty(diRequest.getProductIdList()) || StringUtils.isNotBlank(diRequest.getProductCode()) || diRequest.getServiceStatus() != null || diRequest.getCategoryType() != null) {
                LambdaQueryWrapper<DmpDeviceInfo> queryWrapper = Wrappers.lambdaQuery();
                queryWrapper.eq(StringUtils.isNotBlank(diRequest.getDeviceId()), DmpDeviceInfo::getDeviceId, diRequest.getDeviceId())
                        .eq(StringUtils.isNotBlank(diRequest.getDeviceUuid()), DmpDeviceInfo::getDeviceUuid, diRequest.getDeviceUuid())
                        .like(StringUtils.isNotBlank(diRequest.getDeviceName()), DmpDeviceInfo::getDeviceName, diRequest.getDeviceName())
                        .eq(diRequest.getProductId() != null, DmpDeviceInfo::getProductId, diRequest.getProductId())
                        .in(CollectionUtils.isNotEmpty(diRequest.getProductIdList()), DmpDeviceInfo::getProductId, diRequest.getProductIdList())
                        .like(StringUtils.isNotBlank(diRequest.getProductCode()), DmpDeviceInfo::getProductCode, diRequest.getProductCode())
                        .eq(diRequest.getServiceStatus() != null, DmpDeviceInfo::getServiceStatus, diRequest.getServiceStatus())
                        .eq(diRequest.getCategoryType() != null, DmpDeviceInfo::getCategoryType, diRequest.getCategoryType())
                        .in(CollectionUtils.isNotEmpty(gatewayUuidList), DmpDeviceInfo::getGatewayUuid, gatewayUuidList)
                        .eq(DmpDeviceInfo::getDeleteFlag, 0)
                        .eq(DmpDeviceInfo::getTenantId, SecurityUtils.getTenantId())
                        .orderByDesc(DmpDeviceInfo::getId);
                List<DmpDeviceInfo> list1 = this.list(queryWrapper);

                if (CollectionUtils.isNotEmpty(list1)) {
                    List<String> devList = new ArrayList<>();
                    List<Integer> productIdList = new ArrayList<>();
                    for (int i = 0; i < list1.size(); i++) {
                        if (!devList.contains(list1.get(i).getDeviceId())) {
                            devList.add(list1.get(i).getDeviceId());
                        }
                        if (!productIdList.contains(list1.get(i).getProductId())) {
                            productIdList.add(list1.get(i).getProductId());
                        }
                    }

                    if (devList.size() > 0) {
                        LambdaQueryWrapper<DmpDeviceStatus> queryWrapper1 = Wrappers.lambdaQuery();
                        queryWrapper1.in(DmpDeviceStatus::getDeviceId, devList)
                                .in(DmpDeviceStatus::getProductId, productIdList)
                                .eq(DmpDeviceStatus::getDeviceStatus, diRequest.getDeviceStatus());
                        List<DmpDeviceStatus> statusList = dmpDeviceStatusService.list(queryWrapper1);
                        if (statusList.size() > 0) {
                            for (int i = 0; i < list1.size(); i++) {
                                for (int j = 0; j < statusList.size(); j++) {
                                    if (list1.get(i).getProductId().equals(statusList.get(j).getProductId()) && list1.get(i).getDeviceId().equals(statusList.get(j).getDeviceId())) {
                                        list1.get(i).setDeviceStatus(statusList.get(j).getDeviceStatus());
                                        list1.get(i).setLastOnlineTime(statusList.get(j).getLastOnlineTime());
                                        list1.get(i).setLastOfflineTime(statusList.get(j).getLastOfflineTime());
                                        list.add(list1.get(i));
                                        break;
                                    }
                                }
                            }
                        }
                    }

                }

                if (list.size() > 0) {
                    total = list.size();
                    page.setTotal(total);
                }

                Integer current = 0;
                if (pageCurrent != null && pageSize > 0) {
                    current = (pageCurrent - 1) * pageSize;
                }

                page.setRecords(list.stream().skip(current).limit(pageSize).collect(Collectors.toList()));
            } else {
                LambdaQueryWrapper<DmpDeviceStatus> queryWrapper = Wrappers.lambdaQuery();
                queryWrapper.eq(DmpDeviceStatus::getDeviceStatus, diRequest.getDeviceStatus());
                List<DmpDeviceStatus> statusList = dmpDeviceStatusService.list(queryWrapper);
                if (statusList.size() > 0) {
                    List<String> devList = new ArrayList<>();
                    List<Integer> productIdList = new ArrayList<>();
                    for (int i = 0; i < statusList.size(); i++) {
                        if (!devList.contains(statusList.get(i).getDeviceId())) {
                            devList.add(statusList.get(i).getDeviceId());
                        }
                        if (!productIdList.contains(statusList.get(i).getProductId())) {
                            productIdList.add(statusList.get(i).getProductId());
                        }
                    }

                    if (devList.size() > 0) {
                        LambdaQueryWrapper<DmpDeviceInfo> queryWrapper1 = Wrappers.lambdaQuery();
                        queryWrapper1.in(DmpDeviceInfo::getDeviceId, devList)
                                .in(DmpDeviceInfo::getProductId, productIdList)
                                .eq(DmpDeviceInfo::getDeleteFlag, 0)
                                .eq(DmpDeviceInfo::getTenantId, SecurityUtils.getTenantId())
                                .orderByDesc(DmpDeviceInfo::getId);
                        List<DmpDeviceInfo> list1 = this.list(queryWrapper1);
                        if (list1.size() > 0) {
                            for (int i = 0; i < list1.size(); i++) {
                                for (int j = 0; j < statusList.size(); j++) {
                                    if (list1.get(i).getProductId().equals(statusList.get(j).getProductId()) && list1.get(i).getDeviceId().equals(statusList.get(j).getDeviceId())) {
                                        list1.get(i).setDeviceStatus(statusList.get(j).getDeviceStatus());
                                        list1.get(i).setLastOnlineTime(statusList.get(j).getLastOnlineTime());
                                        list1.get(i).setLastOfflineTime(statusList.get(j).getLastOfflineTime());
                                        list.add(list1.get(i));
                                        break;
                                    }
                                }
                            }
                            if (list.size() > 0) {
                                total = list.size();
                                page.setTotal(total);
                            }

                            Integer current = 0;
                            if (pageCurrent != null && pageSize > 0) {
                                current = (pageCurrent - 1) * pageSize;
                            }

                            page.setRecords(list.stream().skip(current).limit(pageSize).collect(Collectors.toList()));
                        }
                    }
                }
            }
        } else {
            LambdaQueryWrapper<DmpDeviceInfo> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(StringUtils.isNotBlank(diRequest.getDeviceId()), DmpDeviceInfo::getDeviceId, diRequest.getDeviceId())
                    .eq(StringUtils.isNotBlank(diRequest.getDeviceUuid()), DmpDeviceInfo::getDeviceUuid, diRequest.getDeviceUuid())
                    .like(StringUtils.isNotBlank(diRequest.getDeviceName()), DmpDeviceInfo::getDeviceName, diRequest.getDeviceName())
                    .eq(diRequest.getProductId() != null, DmpDeviceInfo::getProductId, diRequest.getProductId())
                    .in(CollectionUtils.isNotEmpty(diRequest.getProductIdList()), DmpDeviceInfo::getProductId, diRequest.getProductIdList())
                    .like(StringUtils.isNotBlank(diRequest.getProductCode()), DmpDeviceInfo::getProductCode, diRequest.getProductCode())
                    .eq(diRequest.getServiceStatus() != null, DmpDeviceInfo::getServiceStatus, diRequest.getServiceStatus())
                    .eq(diRequest.getCategoryType() != null, DmpDeviceInfo::getCategoryType, diRequest.getCategoryType())
                    .in(CollectionUtils.isNotEmpty(gatewayUuidList), DmpDeviceInfo::getGatewayUuid, gatewayUuidList)
                    .eq(DmpDeviceInfo::getDeleteFlag, 0)
                    .eq(DmpDeviceInfo::getTenantId, SecurityUtils.getTenantId());

            List<DmpDeviceInfo> allRecords = this.list(queryWrapper);

            if (!allRecords.isEmpty()) {
                List<String> devList = allRecords.stream().map(DmpDeviceInfo::getDeviceId).distinct().collect(Collectors.toList());
                List<Integer> productIdList = allRecords.stream().map(DmpDeviceInfo::getProductId).distinct().collect(Collectors.toList());

                LambdaQueryWrapper<DmpDeviceStatus> queryWrapper1 = Wrappers.lambdaQuery();
                queryWrapper1.in(DmpDeviceStatus::getDeviceId, devList)
                        .in(DmpDeviceStatus::getProductId, productIdList);

                List<DmpDeviceStatus> statusList = dmpDeviceStatusService.list(queryWrapper1);

                // 创建一个Map，用于快速查找设备状态
                Map<String, DmpDeviceStatus> statusMap = new HashMap<>();
                for (DmpDeviceStatus status : statusList) {
                    statusMap.put(status.getDeviceId(), status);
                }

                // 重新排序设备信息，优先显示在线设备
                allRecords.sort((d1, d2) -> {
                    DmpDeviceStatus status1 = statusMap.get(d1.getDeviceId());
                    DmpDeviceStatus status2 = statusMap.get(d2.getDeviceId());
                    Integer deviceStatus1 = status1 != null ? status1.getDeviceStatus() : 2; // 默认离线
                    Integer deviceStatus2 = status2 != null ? status2.getDeviceStatus() : 2; // 默认离线
                    // 在线设备优先（1 < 2），如果状态相同，则按id降序
                    return deviceStatus1.compareTo(deviceStatus2) != 0 ? deviceStatus1.compareTo(deviceStatus2) : d2.getId().compareTo(d1.getId());
                });

                // 填充设备状态信息
                for (DmpDeviceInfo deviceInfo : allRecords) {
                    DmpDeviceStatus status = statusMap.get(deviceInfo.getDeviceId());
                    if (status != null) {
                        deviceInfo.setDeviceStatus(status.getDeviceStatus()); // 填充设备状态
                    } else {
                        deviceInfo.setDeviceStatus(2); // 默认离线
                    }
                }
            }

            // 分页处理
            int start = (pageCurrent - 1) * pageSize;
            int end = Math.min(start + pageSize, allRecords.size());

            // 确保 start 不超过 allRecords 的大小
            if (start >= allRecords.size()) {
                start = 0; // 如果 start 超出范围，重置为 0
                end = Math.min(pageSize, allRecords.size()); // 重新计算 end
            }

            List<DmpDeviceInfo> pageRecords = allRecords.subList(start, end);
            total = allRecords.size();

            page.setRecords(pageRecords);
            page.setTotal(total);
        }


        return new CommonPage<>(page.getRecords(), page.getTotal(), pageSize, pageCurrent);
    }

    @Override
    public CommonPage<DmpDeviceInfo> pageWhite(DmpDeviceInfoRequest diRequest) {
        List<DmpDeviceInfo> list = new ArrayList<>();
        Integer total = 0;
        Integer pageCurrent = diRequest.getCurrent();
        Integer pageSize = diRequest.getSize();
        IPage<DmpDeviceInfo> page = new Page<>(pageCurrent, pageSize);
        Integer tenantId = 0;
        String domain = diRequest.getDomain();
        if (StringUtils.isNotBlank(domain)) {
            tenantId = baseMapper.sysTenantId(domain);
        }

        List<String> gatewayUuidList = new ArrayList<>();
        if (diRequest.getSpaceId() != null) {
            LambdaQueryWrapper<BaseSpaceGateway> spaceGatewayLambdaQueryWrapper = Wrappers.lambdaQuery();
            spaceGatewayLambdaQueryWrapper.eq(BaseSpaceGateway::getSpaceId, diRequest.getSpaceId());
            gatewayUuidList = baseSpaceGatewayService.list(spaceGatewayLambdaQueryWrapper).stream().map(BaseSpaceGateway::getGatewayUuid).collect(Collectors.toList());
        }
        if(StringUtils.isNotBlank(diRequest.getGatewayUuid())){
            gatewayUuidList.add(diRequest.getGatewayUuid());
        }

        if (diRequest.getDeviceStatus() != null) {
            if (StringUtils.isNotBlank(diRequest.getDeviceId()) || StringUtils.isNotBlank(diRequest.getDeviceName()) || diRequest.getProductId() != null || CollectionUtils.isNotEmpty(diRequest.getProductIdList()) || StringUtils.isNotBlank(diRequest.getProductCode()) || diRequest.getServiceStatus() != null || diRequest.getCategoryType() != null) {
                LambdaQueryWrapper<DmpDeviceInfo> queryWrapper = Wrappers.lambdaQuery();
                queryWrapper.eq(StringUtils.isNotBlank(diRequest.getDeviceId()), DmpDeviceInfo::getDeviceId, diRequest.getDeviceId())
                        .like(StringUtils.isNotBlank(diRequest.getDeviceName()), DmpDeviceInfo::getDeviceName, diRequest.getDeviceName())
                        .eq(diRequest.getProductId() != null, DmpDeviceInfo::getProductId, diRequest.getProductId())
                        .in(CollectionUtils.isNotEmpty(diRequest.getProductIdList()), DmpDeviceInfo::getProductId, diRequest.getProductIdList())
                        .like(StringUtils.isNotBlank(diRequest.getProductCode()), DmpDeviceInfo::getProductCode, diRequest.getProductCode())
                        .eq(diRequest.getServiceStatus() != null, DmpDeviceInfo::getServiceStatus, diRequest.getServiceStatus())
                        .eq(diRequest.getCategoryType() != null, DmpDeviceInfo::getCategoryType, diRequest.getCategoryType())
                        .in(CollectionUtils.isNotEmpty(gatewayUuidList), DmpDeviceInfo::getGatewayUuid, gatewayUuidList)
                        .eq(DmpDeviceInfo::getDeleteFlag, 0)
                        .eq(DmpDeviceInfo::getTenantId, tenantId)
                        .orderByDesc(DmpDeviceInfo::getId);
                List<DmpDeviceInfo> list1 = this.list(queryWrapper);

                if (CollectionUtils.isNotEmpty(list1)) {
                    List<String> devList = new ArrayList<>();
                    List<Integer> productIdList = new ArrayList<>();
                    for (int i = 0; i < list1.size(); i++) {
                        if (!devList.contains(list1.get(i).getDeviceId())) {
                            devList.add(list1.get(i).getDeviceId());
                        }
                        if (!productIdList.contains(list1.get(i).getProductId())) {
                            productIdList.add(list1.get(i).getProductId());
                        }
                    }

                    if (devList.size() > 0) {
                        LambdaQueryWrapper<DmpDeviceStatus> queryWrapper1 = Wrappers.lambdaQuery();
                        queryWrapper1.in(DmpDeviceStatus::getDeviceId, devList)
                                .in(DmpDeviceStatus::getProductId, productIdList)
                                .eq(DmpDeviceStatus::getDeviceStatus, diRequest.getDeviceStatus());
                        List<DmpDeviceStatus> statusList = dmpDeviceStatusService.list(queryWrapper1);
                        if (statusList.size() > 0) {
                            for (int i = 0; i < list1.size(); i++) {
                                for (int j = 0; j < statusList.size(); j++) {
                                    if (list1.get(i).getProductId().equals(statusList.get(j).getProductId()) && list1.get(i).getDeviceId().equals(statusList.get(j).getDeviceId())) {
                                        list1.get(i).setDeviceStatus(statusList.get(j).getDeviceStatus());
                                        list1.get(i).setLastOnlineTime(statusList.get(j).getLastOnlineTime());
                                        list1.get(i).setLastOfflineTime(statusList.get(j).getLastOfflineTime());
                                        list.add(list1.get(i));
                                        break;
                                    }
                                }
                            }
                        }
                    }

                }

                if (list.size() > 0) {
                    total = list.size();
                    page.setTotal(total);
                }

                Integer current = 0;
                if (pageCurrent != null && pageSize > 0) {
                    current = (pageCurrent - 1) * pageSize;
                }

                page.setRecords(list.stream().skip(current).limit(pageSize).collect(Collectors.toList()));
            } else {
                LambdaQueryWrapper<DmpDeviceStatus> queryWrapper = Wrappers.lambdaQuery();
                queryWrapper.eq(DmpDeviceStatus::getDeviceStatus, diRequest.getDeviceStatus());
                List<DmpDeviceStatus> statusList = dmpDeviceStatusService.list(queryWrapper);
                if (statusList.size() > 0) {
                    List<String> devList = new ArrayList<>();
                    List<Integer> productIdList = new ArrayList<>();
                    for (int i = 0; i < statusList.size(); i++) {
                        if (!devList.contains(statusList.get(i).getDeviceId())) {
                            devList.add(statusList.get(i).getDeviceId());
                        }
                        if (!productIdList.contains(statusList.get(i).getProductId())) {
                            productIdList.add(statusList.get(i).getProductId());
                        }
                    }

                    if (devList.size() > 0) {
                        LambdaQueryWrapper<DmpDeviceInfo> queryWrapper1 = Wrappers.lambdaQuery();
                        queryWrapper1.in(DmpDeviceInfo::getDeviceId, devList)
                                .in(DmpDeviceInfo::getProductId, productIdList)
                                .eq(DmpDeviceInfo::getDeleteFlag, 0)
                                .eq(DmpDeviceInfo::getTenantId, tenantId)
                                .orderByDesc(DmpDeviceInfo::getId);
                        List<DmpDeviceInfo> list1 = this.list(queryWrapper1);
                        if (list1.size() > 0) {
                            for (int i = 0; i < list1.size(); i++) {
                                for (int j = 0; j < statusList.size(); j++) {
                                    if (list1.get(i).getProductId().equals(statusList.get(j).getProductId()) && list1.get(i).getDeviceId().equals(statusList.get(j).getDeviceId())) {
                                        list1.get(i).setDeviceStatus(statusList.get(j).getDeviceStatus());
                                        list1.get(i).setLastOnlineTime(statusList.get(j).getLastOnlineTime());
                                        list1.get(i).setLastOfflineTime(statusList.get(j).getLastOfflineTime());
                                        list.add(list1.get(i));
                                        break;
                                    }
                                }
                            }
                            if (list.size() > 0) {
                                total = list.size();
                                page.setTotal(total);
                            }

                            Integer current = 0;
                            if (pageCurrent != null && pageSize > 0) {
                                current = (pageCurrent - 1) * pageSize;
                            }

                            page.setRecords(list.stream().skip(current).limit(pageSize).collect(Collectors.toList()));
                        }
                    }
                }
            }
        } else {
            LambdaQueryWrapper<DmpDeviceInfo> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(StringUtils.isNotBlank(diRequest.getDeviceId()), DmpDeviceInfo::getDeviceId, diRequest.getDeviceId())
                    .like(StringUtils.isNotBlank(diRequest.getDeviceName()), DmpDeviceInfo::getDeviceName, diRequest.getDeviceName())
                    .eq(diRequest.getProductId() != null, DmpDeviceInfo::getProductId, diRequest.getProductId())
                    .in(CollectionUtils.isNotEmpty(diRequest.getProductIdList()), DmpDeviceInfo::getProductId, diRequest.getProductIdList())
                    .like(StringUtils.isNotBlank(diRequest.getProductCode()), DmpDeviceInfo::getProductCode, diRequest.getProductCode())
                    .eq(diRequest.getServiceStatus() != null, DmpDeviceInfo::getServiceStatus, diRequest.getServiceStatus())
                    .eq(diRequest.getCategoryType() != null, DmpDeviceInfo::getCategoryType, diRequest.getCategoryType())
                    .in(CollectionUtils.isNotEmpty(gatewayUuidList), DmpDeviceInfo::getGatewayUuid, gatewayUuidList)
                    .eq(DmpDeviceInfo::getDeleteFlag, 0)
                    .eq(DmpDeviceInfo::getTenantId, tenantId)
                    .orderByDesc(DmpDeviceInfo::getId);
            page = this.page(page, queryWrapper);
            if (page.getTotal() > 0) {
                List<String> devList = new ArrayList<>();
                List<Integer> productIdList = new ArrayList<>();
                for (int i = 0; i < page.getRecords().size(); i++) {
                    if (!devList.contains(page.getRecords().get(i).getDeviceId())) {
                        devList.add(page.getRecords().get(i).getDeviceId());
                    }
                    if (!productIdList.contains(page.getRecords().get(i).getProductId())) {
                        productIdList.add(page.getRecords().get(i).getProductId());
                    }
                }

                if (devList.size() > 0) {
                    LambdaQueryWrapper<DmpDeviceStatus> queryWrapper1 = Wrappers.lambdaQuery();
                    queryWrapper1.in(DmpDeviceStatus::getDeviceId, devList)
                            .in(DmpDeviceStatus::getProductId, productIdList);
                    List<DmpDeviceStatus> statusList = dmpDeviceStatusService.list(queryWrapper1);
                    if (statusList.size() > 0) {
                        for (int i = 0; i < page.getRecords().size(); i++) {
                            for (int j = 0; j < statusList.size(); j++) {
                                if (page.getRecords().get(i).getProductId().equals(statusList.get(j).getProductId()) && page.getRecords().get(i).getDeviceId().equals(statusList.get(j).getDeviceId())) {
                                    page.getRecords().get(i).setDeviceStatus(statusList.get(j).getDeviceStatus());
                                    page.getRecords().get(i).setLastOnlineTime(statusList.get(j).getLastOnlineTime());
                                    page.getRecords().get(i).setLastOfflineTime(statusList.get(j).getLastOfflineTime());
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }


        return new CommonPage<>(page.getRecords(), page.getTotal(), pageSize, pageCurrent);
    }

    @Override
    public List<DmpDeviceInfo> gatewayDeviceList() {
        LambdaQueryWrapper<DmpDeviceInfo> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(DmpDeviceInfo::getCategoryType, 2)
                .eq(DmpDeviceInfo::getDeleteFlag, 0)
                .eq(DmpDeviceInfo::getTenantId, SecurityUtils.getTenantId())
                .orderByDesc(DmpDeviceInfo::getId);
        List<DmpDeviceInfo> list1 = this.list(queryWrapper);

        return list1;
    }

    @Override
    public boolean remove(Integer id) {
        DmpDeviceInfo dmpDeviceInfo = this.getById(id);
        Optional.ofNullable(dmpDeviceInfo).orElseThrow(() -> new BusinessException("设备不存在"));

        // 已关联设施的不能删除
        LambdaQueryWrapper<BaseFacilityDevice> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(BaseFacilityDevice::getDeviceId, dmpDeviceInfo.getDeviceId());
        int count = baseFacilityDeviceService.count(queryWrapper);
        if (count > 0) {
            throw new BusinessException("已关联设施的不能删除");
        }

        dmpDeviceInfo.setDeleteFlag(1);

        remoteTransferService.deleteDeviceCache(dmpDeviceInfo.getProductCode());

        return this.updateById(dmpDeviceInfo);
    }

    @Override
    public List<Map<String, Object>> deviceCollect(List<Integer> productIds) {
        QueryWrapper<DmpDeviceInfo> query = Wrappers.query();
        query.select("product_id as productId", "count(*) as count", "count(service_status != 1 or null) as serviceCount")
                .in(CollectionUtil.isNotEmpty(productIds), "product_id", productIds)
                .eq("delete_flag", 0)
                .eq("tenant_id", SecurityUtils.getTenantId())
                .groupBy("product_id");
        return this.listMaps(query);
    }

    @Override
    public int deviceCountByProductId(Integer productId) {
        LambdaQueryWrapper<DmpDeviceInfo> lambdaQuery = Wrappers.lambdaQuery();
        lambdaQuery.eq(DmpDeviceInfo::getProductId, productId)
                .eq(DmpDeviceInfo::getDeleteFlag, 0);
        return this.count(lambdaQuery);
    }

    @Override
    public void addByFile(MultipartFile multipartFiles) {
        ImportParams params = new ImportParams();
        params.setHeadRows(1);
        params.setTitleRows(1);
        String err = "文件导入失败";
        try {
            List<DeviceImportVo> deviceImportVos = ExcelImportUtil.importExcel(multipartFiles.getInputStream(),
                    DeviceImportVo.class, params);
            if (CollectionUtils.isNotEmpty(deviceImportVos)) {
                int rot = 0;
                for (DeviceImportVo deviceImportVo : deviceImportVos) {
                    DmpDeviceInfo dmpDeviceInfo = BeanMapperUtils.map(deviceImportVo, DmpDeviceInfo.class);
                    if (StringUtils.isBlank(dmpDeviceInfo.getDeviceId()) || StringUtils.isBlank(dmpDeviceInfo.getProductCode()) || StringUtils.isBlank(dmpDeviceInfo.getDeviceName()) || StringUtils.isBlank(dmpDeviceInfo.getInstallAddress())) {
                        int h = rot + 3;
                        err = "文件导入失败，第" + h + "行数据导入失败,必填字段不能为空";
                        throw new BusinessException(err);
                    }
                    try {
                        this.add(dmpDeviceInfo);
                    } catch (Exception e) {
                        int h = rot + 3;
                        err = "文件导入失败，第" + h + "行数据导入失败";
                        throw new BusinessException(err);
                    }
                    rot++;
                }
            } else {
                err = "文件不能为空";
                throw new BusinessException(err);
            }
        } catch (Exception e) {
            throw new BusinessException(err);
        }
    }

    @Override
    public void importDeviceInfo(List<DmpDeviceInfo> devList) {
        List<DmpDeviceStatus> dmpDeviceStatusList = new ArrayList<>();
        if (CollectionUtils.isEmpty(devList)) {
            throw new BusinessException("数据不能为空");
        }
        for (int i = 0; i < devList.size(); i++) {
            List<DmpProductInfo> list = baseMapper.getProductInfo(devList.get(i).getProductCode());
            if (CollectionUtils.isNotEmpty(list)) {

                if (checkNameUnique1(devList.get(i), list.get(0).getTenantId())) {
                    throw new BusinessException("新增设备信息'" + devList.get(i).getDeviceId() + "'失败，设备信息已存在");
                }

                devList.get(i).setDeviceType(list.get(0).getDeviceType());
                devList.get(i).setProductId(list.get(0).getId());
                devList.get(i).setCreatedBy(SecurityUtils.getUsername());
                devList.get(i).setCreatedTime(LocalDateTime.now());
                devList.get(i).setTenantId(list.get(0).getTenantId());
                devList.get(i).setServiceStatus(1);
                devList.get(i).setDeviceUuid(UUIDUtils.uuid());

                DmpDeviceStatus dmpDeviceStatus = new DmpDeviceStatus();
                dmpDeviceStatus.setDeviceId(devList.get(i).getDeviceId());
                dmpDeviceStatus.setProductId(devList.get(i).getProductId());
                dmpDeviceStatus.setDeviceStatus(2);
                dmpDeviceStatus.setLastOfflineTime(LocalDateTime.now());
                dmpDeviceStatus.setProductCode(devList.get(i).getProductCode());
                dmpDeviceStatus.setDeviceUuid(devList.get(i).getDeviceUuid());
                dmpDeviceStatusList.add(dmpDeviceStatus);
            } else {
                throw new BusinessException("新增设备信息'" + devList.get(i).getDeviceId() + "'失败，无对应产品信息");
            }
        }
        this.saveBatch(devList);
        dmpDeviceStatusService.saveBatch(dmpDeviceStatusList);
    }

    @Override
    public void export(DmpDeviceInfoRequest dmpDeviceInfoRequest, HttpServletResponse response) {
        Workbook workbook = null;
        try {
            ExportParams params = new ExportParams(null, "设备列表");
            workbook = ExcelExportUtil.exportBigExcel(params, DmpDeviceExcelVO.class,
                    (o, i) -> {
                        dmpDeviceInfoRequest.setCurrent(i);
                        dmpDeviceInfoRequest.setSize(30);
                        CommonPage<DmpDeviceInfo> list = this.page(dmpDeviceInfoRequest);
                        return new ArrayList<>(BeanMapperUtils.mapList(list.getRecords(), DmpDeviceInfo.class, DmpDeviceExcelVO.class));
                    }, null);
            if (null != workbook) {
                exportExcel(workbook, response);
            } else {
                throw new BusinessException("表格数据为空");
            }
        } catch (Exception e) {
            log.error("导出文件失败", e);
            throw new BusinessException("导出文件失败" + e.getMessage());
        } finally {
            if (workbook != null) {
                try {
                    workbook.close();
                } catch (IOException e) {
                    log.error("===export spec=== 关闭workbook失败", e);
                }
            }
        }
    }

    @Override
    public Map<String, Map<String, GatewayDeviceExportItemVO>> gatewayExport(GatewayDeviceInfoRequestVO gatewayDeviceInfoRequestVO) {
        if (StringUtils.isBlank(gatewayDeviceInfoRequestVO.getGatewayUuid())) {
            throw new BusinessException("网关UUID不能为空");
        }
        LambdaQueryWrapper<DmpDeviceInfo> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(DmpDeviceInfo::getCategoryType, 3)
                .eq(DmpDeviceInfo::getDeleteFlag, 0)
                .eq(DmpDeviceInfo::getGatewayUuid, gatewayDeviceInfoRequestVO.getGatewayUuid())
                .eq(DmpDeviceInfo::getTenantId, SecurityUtils.getTenantId())
                .orderByDesc(DmpDeviceInfo::getId);
        List<DmpDeviceInfo> gatewayDeviceList = this.list(queryWrapper);
        if (CollectionUtil.isEmpty(gatewayDeviceList)) {
            throw new BusinessException("未查询到网关子设备信息");
        }
        return buildGatewayDeviceExportMap(gatewayDeviceList);
    }

    /**
     * 按设备类型简称 -> 地址码 构建网关子设备配置
     */
    private Map<String, Map<String, GatewayDeviceExportItemVO>> buildGatewayDeviceExportMap(List<DmpDeviceInfo> deviceList) {
        List<Integer> productIds = deviceList.stream()
                .map(DmpDeviceInfo::getProductId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        Map<Integer, String> productTypeAbbreviaMap = getProductTypeAbbreviaMap(productIds);

        Map<String, Map<String, GatewayDeviceExportItemVO>> grouped = new LinkedHashMap<>();
        for (DmpDeviceInfo device : deviceList) {
            if (StringUtils.isBlank(device.getAddressCode())) {
                continue;
            }
            String typeAbbrevia = productTypeAbbreviaMap.get(device.getProductId());
            if (StringUtils.isBlank(typeAbbrevia)) {
                throw new BusinessException("产品ID " + device.getProductId() + " 未找到对应设备类型简称");
            }
            GatewayDeviceExportItemVO deviceInfo = new GatewayDeviceExportItemVO();
            deviceInfo.setDeviceid(device.getDeviceId());
            deviceInfo.setDeviceUuid(device.getDeviceUuid());
            deviceInfo.setProductCode(device.getProductCode());
            grouped.computeIfAbsent(typeAbbrevia, key -> new LinkedHashMap<>())
                    .put(device.getAddressCode(), deviceInfo);
        }
        if (grouped.isEmpty()) {
            throw new BusinessException("网关子设备地址码为空，无法导出配置");
        }
        return grouped;
    }

    /**
     * 根据产品ID批量查询设备类型简称
     */
    private Map<Integer, String> getProductTypeAbbreviaMap(List<Integer> productIds) {
        if (CollectionUtil.isEmpty(productIds)) {
            return Collections.emptyMap();
        }
        List<Map<String, Object>> products = dmpProductInfoMapper.selectDeviceTypeByProductIds(productIds);
        if (CollectionUtil.isEmpty(products)) {
            return Collections.emptyMap();
        }

        Map<Integer, Integer> productDeviceTypeMap = products.stream()
                .collect(Collectors.toMap(
                        map -> Integer.valueOf(map.get("id").toString()),
                        map -> Integer.valueOf(map.get("deviceType").toString()),
                        (a, b) -> a));

        Set<String> typeCodes = productDeviceTypeMap.values().stream()
                .filter(Objects::nonNull)
                .map(String::valueOf)
                .collect(Collectors.toSet());
        if (CollectionUtil.isEmpty(typeCodes)) {
            return Collections.emptyMap();
        }

        LambdaQueryWrapper<DmpDeviceType> typeQuery = Wrappers.lambdaQuery();
        typeQuery.select(DmpDeviceType::getTypeCode, DmpDeviceType::getTypeAbbrevia)
                .in(DmpDeviceType::getTypeCode, typeCodes);
        Map<String, String> typeCodeAbbreviaMap = dmpDeviceTypeService.list(typeQuery).stream()
                .collect(Collectors.toMap(DmpDeviceType::getTypeCode, DmpDeviceType::getTypeAbbrevia, (a, b) -> a));

        Map<Integer, String> result = new HashMap<>();
        productDeviceTypeMap.forEach((productId, deviceType) -> {
            String typeAbbrevia = typeCodeAbbreviaMap.get(String.valueOf(deviceType));
            if (StringUtils.isNotBlank(typeAbbrevia)) {
                result.put(productId, typeAbbrevia);
            }
        });
        return result;
    }

    public void exportExcel(Workbook workbook, HttpServletResponse response) {
        // 定义一个流，用作流式输出
        ServletOutputStream outputStream = null;
        try {
            // 使用流的形式传输
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            // 防止中文乱码
            response.setCharacterEncoding("utf-8");
            outputStream = response.getOutputStream();
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != outputStream) {
                try {
                    // 关闭流
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 获取表格数据
     * @param multipartFile
     * @return
     */
    public List<DmpDeviceInfo> getDeviceByFile(Integer productId, MultipartFile multipartFile) {
        ImportParams importParams = new ImportParams();
        importParams.setHeadRows(1);
        try {
            List<DmpDeviceExportVO> dmpDeviceExportVOS = ExcelImportUtil.importExcel(
                    multipartFile.getInputStream(),
                    DmpDeviceExportVO.class,
                    importParams
            );
            if (CollectionUtils.isEmpty(dmpDeviceExportVOS)) {
                throw new BusinessException("表格数据为空");
            }
            List<DmpDeviceInfo> deviceInfos = BeanMapperUtils.mapList(dmpDeviceExportVOS, DmpDeviceExportVO.class, DmpDeviceInfo.class);
            long count = deviceInfos.stream()
                    .peek(device -> {
                        device.setProductId(productId);
                        device.setDeviceId(UUIDUtils.uuid());
                    })
                    .filter(device -> StringUtils.isBlank(device.getDeviceName()) ||
                            StringUtils.isBlank(device.getDeviceName())
                            || StringUtils.isBlank(device.getSimCode())
                            || null == device.getSubscribeFlag()
                    ).count();
            long count1 = deviceInfos.stream()
                    .collect(Collectors.toMap(DmpDeviceInfo::getDeviceName, s -> 1, Integer::sum))
                    .entrySet()
                    .stream()
                    .filter(entry -> entry.getValue() > 1)
                    .count();
            if (count > 0) {
                throw new BusinessException("表格字段不能为空");
            }
            if (count1 > 0) {
                throw new BusinessException("设备名称不能重复");
            }
            return deviceInfos;
        } catch (Exception e) {
            throw new BusinessException("解析表格异常,检查表格格式" + e.getMessage());
        }
    }

    @Override
    public CommonPage<Object> deviceCurrentDataList(String deviceName, String installAddress, String productCode, Integer pageNum, Integer pageSize) {
        List<Object> list = new ArrayList<>();

        List<DmpDeviceInfo> devList = new ArrayList<>();
        LambdaQueryWrapper<DmpDeviceInfo> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(DmpDeviceInfo::getDeleteFlag, 0)
                .eq(DmpDeviceInfo::getTenantId, SecurityUtils.getTenantId())
                .like(StringUtils.isNotBlank(deviceName), DmpDeviceInfo::getDeviceName, deviceName)
                .like(StringUtils.isNotBlank(installAddress), DmpDeviceInfo::getInstallAddress, installAddress)
                .eq(DmpDeviceInfo::getProductCode, productCode)
                .orderByAsc(DmpDeviceInfo::getId);
        devList = this.list(queryWrapper);
        if (devList.size() <= 0) {
            return new CommonPage<>(list, 0, pageNum, pageSize);
        }

        if (devList.size() > 0) {
            List<String> deviceList = new ArrayList<>();
            for (int k = 0; k < devList.size(); k++) {
                deviceList.add(devList.get(k).getDeviceId());
            }

            if (deviceList.size() > 0) {
                List<DataRealTimeResponseVO> dataRealList = deviceDataClient.data(productCode, deviceList);
                if (dataRealList.size() > 0) {
                    for (int i = 0; i < devList.size(); i++) {
                        Map<String, Object> map = new HashMap<>();
                        map.put("deviceId", devList.get(i).getDeviceId());
                        map.put("deviceName", devList.get(i).getDeviceName());
                        map.put("installAddress", devList.get(i).getInstallAddress());
                        map.put("latestTime", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

                        for (int j = 0; j < dataRealList.size(); j++) {
                            if (devList.get(i).getProductCode().equals(dataRealList.get(j).getProductCode()) && devList.get(i).getDeviceId().equals(dataRealList.get(j).getDeviceId())) {
                                map.put(dataRealList.get(j).getAttributeName(), dataRealList.get(j).getAttributeData());
                                map.put(dataRealList.get(j).getAttributeName() + "Time", dataRealList.get(j).getDataTime());
                            }

                        }
                        list.add(map);

                    }
                }

            }
        }

        List<Object> objectList = new ArrayList<>();
        int total = 0;
        if (list.size() > 0) {
            total = list.size();
        }
        int current = 0;
        if (pageNum != 0 && pageSize > 0) {
            current = (pageNum - 1) * pageSize;
        }

        objectList = list.stream().skip(current).limit(pageSize).collect(Collectors.toList());


        return new CommonPage<>(objectList, total, pageNum, pageSize);
    }

    @Override
    public CommonPage<DataTVResponseVO> dataTVList(DataTVRequestVO requestVO) {
        List<DataTVResponseVO> list = new ArrayList<>();

        IPage<DmpDeviceInfo> page = new Page<>(requestVO.getCurrent(), requestVO.getSize());
        LambdaQueryWrapper<DmpDeviceInfo> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(DmpDeviceInfo::getProductId, DmpDeviceInfo::getDeviceId, DmpDeviceInfo::getDeviceName, DmpDeviceInfo::getDeviceType, DmpDeviceInfo::getInstallAddress)
                .eq(DmpDeviceInfo::getTenantId, SecurityUtils.getTenantId())
                .eq(DmpDeviceInfo::getDeleteFlag, 0)
                .eq(requestVO.getDeviceType() != null, DmpDeviceInfo::getDeviceType, requestVO.getDeviceType())
                .eq(StringUtils.isNotBlank(requestVO.getDeviceId()), DmpDeviceInfo::getDeviceId, requestVO.getDeviceId())
                .orderByDesc(DmpDeviceInfo::getId);
        page = this.page(page, queryWrapper);
        if (page.getSize() <= 0) {
            return new CommonPage<>(list, 0, requestVO.getSize(), requestVO.getCurrent());
        }

        if (page.getRecords().size() > 0) {
            List<String> deviceIdList = new ArrayList<>();
            List<Integer> productIdList = new ArrayList<>();
            for (int i = 0; i < page.getRecords().size(); i++) {
                deviceIdList.add(page.getRecords().get(i).getDeviceId());
                if (!productIdList.contains(page.getRecords().get(i).getProductId())) {
                    productIdList.add(page.getRecords().get(i).getProductId());
                }
            }

            List<ProductTVAttributeVO> attributeVOList = baseMapper.attributeList(productIdList);

            if (deviceIdList.size() > 0) {
                LambdaQueryWrapper<DmpDeviceStatus> queryWrapper1 = Wrappers.lambdaQuery();
                queryWrapper1.in(DmpDeviceStatus::getDeviceId, deviceIdList);
                List<DmpDeviceStatus> deviceStatusList = dmpDeviceStatusService.list(queryWrapper1);

                List<BaseAlarm> baseAlarmList = baseMapper.baseAlarmList(deviceIdList);

                List<DataRealTimeResponseVO> dataRealList = deviceDataClient.data(null, deviceIdList);
                for (int i = 0; i < page.getRecords().size(); i++) {
                    DataTVResponseVO dataTVResponseVO = new DataTVResponseVO();
                    dataTVResponseVO.setDeviceId(page.getRecords().get(i).getDeviceId());
                    dataTVResponseVO.setDeviceName(page.getRecords().get(i).getDeviceName());
                    dataTVResponseVO.setDeviceType(page.getRecords().get(i).getDeviceType());
                    dataTVResponseVO.setInstallAddress(page.getRecords().get(i).getInstallAddress());
                    if (CollectionUtils.isNotEmpty(deviceStatusList)) {
                        for (int j = 0; j < deviceStatusList.size(); j++) {
                            if (page.getRecords().get(i).getDeviceId().equals(deviceStatusList.get(j).getDeviceId())) {
                                dataTVResponseVO.setDeviceStatus(deviceStatusList.get(j).getDeviceStatus());
                            }
                        }
                    }

                    if (CollectionUtils.isNotEmpty(baseAlarmList)) {
                        for (int j = 0; j < baseAlarmList.size(); j++) {
                            if (page.getRecords().get(i).getDeviceId().equals(baseAlarmList.get(j).getDeviceId())) {
                                List<BaseAlarmVO> list1 = new ArrayList<>();
                                if (baseAlarmList.get(j).getAlarmType().equals("815")) {
                                    dataTVResponseVO.setAlarmStatus(2);
                                } else {
                                    dataTVResponseVO.setAlarmStatus(1);
                                }
                                BaseAlarmVO baseAlarmVO = new BaseAlarmVO();
                                baseAlarmVO.setAlarmContent(baseAlarmList.get(j).getAlarmContent());
                                baseAlarmVO.setAlarmTime((baseAlarmList.get(j).getAlarmTime()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                                list1.add(baseAlarmVO);
                                dataTVResponseVO.setAlarmList(list1);
                            }
                        }
                    }

                    List<DeviceAttributeVO> list1 = new ArrayList<>();
                    if (dataRealList.size() > 0) {
                        for (int j = 0; j < dataRealList.size(); j++) {
                            if (page.getRecords().get(i).getDeviceId().equals(dataRealList.get(j).getDeviceId())) {
                                DeviceAttributeVO attributeVO = new DeviceAttributeVO();
                                attributeVO.setCode(dataRealList.get(j).getAttributeName());
                                attributeVO.setValue(dataRealList.get(j).getAttributeData());
                                attributeVO.setTime("" + dataRealList.get(j).getDataTime());
                                if ((attributeVOList.size() > 0)) {
                                    for (int k = 0; k < attributeVOList.size(); k++) {
                                        if ((dataRealList.get(j).getProductCode().equals(attributeVOList.get(k).getProductCode())) && (dataRealList.get(j).getAttributeName().equals(attributeVOList.get(k).getAttributeCode()))) {
                                            if (Objects.nonNull(attributeVOList.get(k).getAttributeName())) {
                                                attributeVO.setName(attributeVOList.get(k).getAttributeName());
                                            }
                                            if (Objects.nonNull(attributeVOList.get(k).getAttributeUnit())) {
                                                attributeVO.setUnit(attributeVOList.get(k).getAttributeUnit());
                                            }
                                            if (Objects.nonNull(attributeVOList.get(k).getMaximum())) {
                                                attributeVO.setMaximum(Math.round(attributeVOList.get(k).getMaximum() * 100) / 100f);
                                            }
                                            if (Objects.nonNull(attributeVOList.get(k).getMinimum())) {
                                                attributeVO.setMinimum(Math.round(attributeVOList.get(k).getMinimum() * 100) / 100f);
                                            }
                                            break;
                                        }
                                    }
                                }

                                list1.add(attributeVO);
                            }
                        }
                    }
                    dataTVResponseVO.setDp(list1);
                    list.add(dataTVResponseVO);
                }


            }
        }


        return new CommonPage<>(list, page.getTotal(), page.getSize(), page.getCurrent());
    }

    @Override
    public List<DataTVStatisticResponseVO> dataTVStatistic(DataTVRequestVO requestVO) {
        List<DataTVStatisticResponseVO> list = new ArrayList<>();
        LambdaQueryWrapper<DmpDeviceInfo> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(DmpDeviceInfo::getProductId, DmpDeviceInfo::getDeviceId, DmpDeviceInfo::getDeviceName, DmpDeviceInfo::getDeviceType, DmpDeviceInfo::getInstallAddress)
                .eq(DmpDeviceInfo::getTenantId, SecurityUtils.getTenantId())
                .eq(DmpDeviceInfo::getDeleteFlag, 0)
                .eq(requestVO.getDeviceType() != null, DmpDeviceInfo::getDeviceType, requestVO.getDeviceType())
                .orderByDesc(DmpDeviceInfo::getId);
        List<DmpDeviceInfo> list1 = this.list(queryWrapper);
        if (CollectionUtils.isNotEmpty(list1)) {
            List<String> deviceIdList = new ArrayList<>();
            for (int i = 0; i < list1.size(); i++) {
                deviceIdList.add(list1.get(i).getDeviceId());
            }
            Integer alarmCount = baseMapper.baseAlarmCount(deviceIdList);
            Integer faultCount = baseMapper.baseFaultCount(deviceIdList);
            Integer offlineCount = baseMapper.deviceOfflineCount(deviceIdList);
            DataTVStatisticResponseVO responseVO = new DataTVStatisticResponseVO();
            responseVO.setAlarmNum(alarmCount);
            responseVO.setFaultNum(faultCount);
            responseVO.setOfflineNum(offlineCount);
            list.add(responseVO);
        }

        return list;
    }

    @Override
    public List<Map<String, Object>> deviceDataTotal(DataTotalRequestVO requestVO) {
        List<Map<String, Object>> list = dataQueryClient.deviceDataTotal(requestVO);

        return list;
    }

    @Override
    public List<DataAverageResponseVO> deviceDataAverage(DataAverageRequestVO requestVO) {
        List<DataAverageResponseVO> list = dataQueryClient.deviceDataAverage(requestVO);

        if (requestVO.getGroupType().equals("Each")) {
            if (list.size() > 0) {
                List<String> deviceIdList = new ArrayList<>();
                for (int i = 0; i < list.size(); i++) {
                    deviceIdList.add(list.get(i).getDeviceId());
                }
                LambdaQueryWrapper<DmpDeviceInfo> queryWrapper = Wrappers.lambdaQuery();
                queryWrapper.in(DmpDeviceInfo::getDeviceId, deviceIdList)
                        .eq(DmpDeviceInfo::getDeleteFlag, 0)
                        .eq(DmpDeviceInfo::getTenantId, SecurityUtils.getTenantId());
                List<DmpDeviceInfo> deviceInfoList = this.list(queryWrapper);
                if (CollectionUtils.isNotEmpty(deviceIdList)) {
                    for (int i = 0; i < list.size(); i++) {
                        for (int j = 0; j < deviceInfoList.size(); j++) {
                            if (list.get(i).getDeviceId().equals(deviceInfoList.get(j).getDeviceId())) {
                                list.get(i).setDeviceName(deviceInfoList.get(j).getDeviceName());
                                break;
                            }
                        }
                    }
                }
            }
        }

        return list;
    }

    @Override
    public List<DataAverageExportVO> DataAverageExport(DataAverageRequestVO requestVO) {
        List<DataAverageExportVO> list = dataQueryClient.DataAverageExport(requestVO);

        if (requestVO.getGroupType().equals("Each")) {
            if (list.size() > 0) {
                List<String> deviceIdList = new ArrayList<>();
                for (int i = 0; i < list.size(); i++) {
                    deviceIdList.add(list.get(i).getDeviceName());
                }
                LambdaQueryWrapper<DmpDeviceInfo> queryWrapper = Wrappers.lambdaQuery();
                queryWrapper.in(DmpDeviceInfo::getDeviceId, deviceIdList)
                        .eq(DmpDeviceInfo::getDeleteFlag, 0)
                        .eq(DmpDeviceInfo::getTenantId, SecurityUtils.getTenantId());
                List<DmpDeviceInfo> deviceInfoList = this.list(queryWrapper);
                if (CollectionUtils.isNotEmpty(deviceIdList)) {
                    for (int i = 0; i < list.size(); i++) {
                        for (int j = 0; j < deviceInfoList.size(); j++) {
                            if (list.get(i).getDeviceName().equals(deviceInfoList.get(j).getDeviceId())) {
                                list.get(i).setDeviceName(deviceInfoList.get(j).getDeviceName());
                                break;
                            }
                        }
                    }
                }
            }
        }

        return list;
    }
}
