/*
 * 文 件 名:  SquareLightCtlHandler
 * 版    权:  华设设计集团股份有限公司
 * 描    述:  <描述>
 * 修 改 人:  lvwenbin
 * 修改时间:  2025/9/19
 * 跟踪单号:  <跟踪单号>
 * 修改单号:  <修改单号>
 * 修改内容:  <修改内容>
 */
package com.ruoyi.ems.handle;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.huashe.common.domain.JsonEntity;
import com.huashe.common.exception.Assert;
import com.ruoyi.ems.config.SquareLightCtlConfig;
import com.ruoyi.ems.core.SquareLightCtlTemplate;
import com.ruoyi.ems.domain.EmsDevice;
import com.ruoyi.ems.domain.EmsObjAttrValue;
import com.ruoyi.ems.enums.DevObjType;
import com.ruoyi.ems.model.AbilityPayload;
import com.ruoyi.ems.model.CallData;
import com.ruoyi.ems.model.CallResponse;
import com.ruoyi.ems.model.QueryDevice;
import com.ruoyi.ems.model.slightctl.BaselineInfo;
import com.ruoyi.ems.model.slightctl.CcElecInfo;
import com.ruoyi.ems.model.slightctl.DevSub;
import com.ruoyi.ems.model.slightctl.DeviceInfo;
import com.ruoyi.ems.model.slightctl.SlcDevice;
import com.ruoyi.ems.model.slightctl.SlcDeviceLamp;
import com.ruoyi.ems.model.slightctl.SlcProject;
import com.ruoyi.ems.model.slightctl.SlcProjectSubset;
import com.ruoyi.ems.model.slightctl.StatusInfo;
import com.ruoyi.ems.util.PingUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 广场灯控
 * <功能详细描述>
 *
 * @author lvwenbin
 * @version [版本号, 2025/9/19]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Service
public class SquareLightCtlHandler extends BaseDevHandler {
    private static final Logger log = LoggerFactory.getLogger(SquareLightCtlHandler.class);

    // 对接系统
    private static final String SYS_MODE_CODE = "M_Z010_SYS_SQUARE_LIGHT";

    // 灯杆模型代码
    private static final String LAMP_POST_MODE_CODE = "M_Z010_DEV_SQUARE_LAMP_POST";

    // 照明灯组模型代码
    private static final String DEV_MODE_CODE = "M_Z010_DEV_SQUARE_LIGHT";

    // 集中器设备代码
    private static final String CONCENTRATOR = "M_Z010_DEV_SQUARE_CONCENTRATOR";

    // 设备子系统代码
    private static final String SUBSYSTEM_CODE = "SYS_ZHZM";

    @Autowired
    private SquareLightCtlConfig config;

    @Override
    public List<EmsDevice> getDeviceList() {
        QueryDevice queryDevice = new QueryDevice();
        queryDevice.setDeviceModel(DEV_MODE_CODE);
        return deviceService.selectList(queryDevice);
    }

    @Override
    public void refreshOnline() {
        try {
            // 1. 从URL中提取IP地址
            String url = config.getUrl();
            if (StringUtils.isBlank(url)) {
                log.warn("广场灯控系统URL配置为空，跳过心跳检测");
                return;
            }

            String ipAddress = PingUtils.extractIpFromUrl(url);
            if (StringUtils.isBlank(ipAddress)) {
                log.warn("无法从URL中提取IP地址: {}", url);
                return;
            }

            // 2. 执行ping检测
            boolean isOnline = PingUtils.pingHost(ipAddress, 3000); // 3秒超时

            // 3. 获取当前系统状态
            String statusKey = "interfaceStatus";

            // 查询当前状态
            EmsObjAttrValue currentStatus = objAttrValueService.selectObjAttrValue(SYS_MODE_CODE, SUBSYSTEM_CODE,
                statusKey);

            String newStatus = isOnline ? "1" : "0";
            String oldStatus = currentStatus != null ? currentStatus.getAttrValue() : null;

            // 4. 状态发生变化时更新并记录
            if (!StringUtils.equals(oldStatus, newStatus)) {
                log.info("能耗监测系统连接状态变化: {} -> {}, IP: {}", oldStatus, newStatus, ipAddress);

                // 更新系统属性状态
                objAttrValueService.updateObjAttrValue(SYS_MODE_CODE, SUBSYSTEM_CODE, statusKey, newStatus);

                String key = isOnline ? "connect" : "disconnect";
                triggerEvent(SYS_MODE_CODE, SUBSYSTEM_CODE, key, null, new Date());
            }

            // 5. 记录心跳日志（可选，用于调试）
            log.debug("广场灯控系统心跳检测完成 - IP: {}, 状态: {}", ipAddress, isOnline ? "在线" : "离线");
        }
        catch (Exception e) {
            log.error("广场灯控系统心跳检测异常", e);
        }
    }

    @Override
    public CallResponse<Void> call(AbilityPayload abilityParam) {
        CallResponse<Void> callResponse = null;

        try {
            if (DevObjType.SYSTEM.getCode() == abilityParam.getObjType()) {
                switch (abilityParam.getAbilityKey()) {
                    case "GetProjectList":
                        execGetProjectList();
                        break;
                    case "GetProjectSubsetList":
                        execGetProjectSubsetList();
                        break;
                    case "GetDeviceList":
                        CompletableFuture.runAsync(this::execGetDeviceList);
                        break;
                    case "SyncDevAttrAll":
                        CompletableFuture.runAsync(this::execSyncDevAttrAll);
                        break;
                    case "lightControlAll":
                        lightControlAll(abilityParam.getAbilityParam());
                        break;
                    default:
                        throw new UnsupportedOperationException("不支持的abilityKey");
                }
            }
            else if (DevObjType.DEVC.getCode() == abilityParam.getObjType() && StringUtils.equals(LAMP_POST_MODE_CODE,
                abilityParam.getModelCode())) {
                switch (abilityParam.getAbilityKey()) {
                    case "lightControlAll":
                        lampPostLightControl(abilityParam.getObjCode(), abilityParam.getAbilityParam());
                        break;
                    default:
                        throw new UnsupportedOperationException("不支持的abilityKey");
                }
            }
            else if (DevObjType.DEVC.getCode() == abilityParam.getObjType() && StringUtils.equals(DEV_MODE_CODE,
                abilityParam.getModelCode())) {
                switch (abilityParam.getAbilityKey()) {
                    case "lightControl":
                        lightControl(abilityParam.getObjCode(), abilityParam.getAbilityParam());
                        break;
                    case "SyncDevAttr":
                        execSyncDevAttr(abilityParam.getObjCode());
                        break;
                    case "lightControlBrightness":
                        lightControlBrightness(abilityParam.getObjCode(), abilityParam.getAbilityParam());
                        break;
                    default:
                        throw new UnsupportedOperationException("不支持的abilityKey");
                }
            }

            callResponse = new CallResponse<>(0, "成功");
        }
        catch (Exception e) {
            callResponse = new CallResponse<>(-1, e.getMessage());
            log.error("调用ability异常", e);
        }

        return callResponse;
    }

    public void execSyncDevAttrAll() {
        SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
        CallData<SlcProject> projecCallData = template.getProjectList();
        List<SlcProject> projects = projecCallData.getList();

        if (CollectionUtils.isNotEmpty(projects)) {
            for (SlcProject project : projects) {
                CallData<SlcDevice> callData = template.getDeviceList(project.getProjectId(), null);

                // 灯组设备同步
                List<SlcDevice> lightDevs = callData.getList().stream()
                    .filter(dev -> StringUtils.equals(dev.getDeviceModelId(), "1945454135655632897"))
                    .collect(Collectors.toList());
                mergeLightDevAttrs(project.getProjectId(), lightDevs);

                // 集中器设备同步
                List<SlcDevice> centDevs = callData.getList().stream()
                    .filter(dev -> StringUtils.equals(dev.getDeviceModelId(), "1943504597877362689"))
                    .collect(Collectors.toList());
                mergeCentDevAttrValue(project.getProjectId(), centDevs);
            }
        }
    }

    public void execSyncDevAttr(String objCode) {
        EmsObjAttrValue proAttr = objAttrValueService.selectObjAttrValue(DEV_MODE_CODE, objCode, "projectId");
        SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
        mergeLightDevAttr(template, proAttr.getAttrValue(), objCode, null);
    }

    public void execGetProjectList() {
        SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
        CallData<SlcProject> callData = template.getProjectList();
        List<SlcProject> projects = callData.getList();
        saveCallLog(SUBSYSTEM_CODE, SYS_MODE_CODE, "GetProjectList", callData.getCallStatus(),
            callData.getCallPayload(), callData.getResPayload());
        objAttrValueService.updateObjAttrValue(SYS_MODE_CODE, SUBSYSTEM_CODE, "projectList",
            JSON.toJSONString(projects));
    }

    public void execGetProjectSubsetList() {
        SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
        CallData<SlcProject> projectCallData = template.getProjectList();
        List<SlcProject> projects = projectCallData.getList();

        if (CollectionUtils.isNotEmpty(projects)) {
            List<SlcProjectSubset> subsets = new ArrayList<>();

            for (SlcProject project : projects) {
                CallData<SlcProjectSubset> callData = template.getProjectSubsetList(project.getProjectId());
                List<SlcProjectSubset> slcProjectSubsets = callData.getList();
                saveCallLog(SUBSYSTEM_CODE, SYS_MODE_CODE, "GetProjectSubsetList", callData.getCallStatus(),
                    callData.getCallPayload(), callData.getResPayload());
                subsets.addAll(slcProjectSubsets);
            }

            objAttrValueService.updateObjAttrValue(SYS_MODE_CODE, SUBSYSTEM_CODE, "projectSubsetList",
                JSON.toJSONString(subsets));
        }
    }

    public void lightControlAll(String paramValue) {
        QueryDevice queryDevice = new QueryDevice();
        queryDevice.setDeviceModel(LAMP_POST_MODE_CODE);
        queryDevice.setSubsystemCode(SUBSYSTEM_CODE);
        queryDevice.setDeviceStatus(1);
        List<EmsDevice> devices = deviceService.selectList(queryDevice);

        if (CollectionUtils.isNotEmpty(devices)) {
            for (EmsDevice device : devices) {
                lampPostLightControl(device.getDeviceCode(), paramValue);
            }
        }
    }

    public void lampPostLightControl(String lampPostId, String paramValue) {
        EmsObjAttrValue lampPostSubDev = objAttrValueService.selectObjAttrValue(LAMP_POST_MODE_CODE, lampPostId,
            "subDev");

        if (null != lampPostSubDev) {
            JSONArray lights = JSONArray.parseArray(lampPostSubDev.getAttrValue());

            JsonEntity.ObjBuilder json = JsonEntity.objBuilder();

            lights.forEach(item -> {
                JSONObject jsonObject = (JSONObject) item;
                json.addKeyArray("deviceIds", jsonObject.getString("deviceCode"));
            });

            JSONObject jsonObject = (JSONObject) lights.get(0);

            EmsObjAttrValue projectIdAttr = objAttrValueService.selectObjAttrValue(DEV_MODE_CODE,
                jsonObject.getString("deviceCode"), "projectId");

            JsonEntity.ObjBuilder lampListObj = JsonEntity.objBuilder().putKv("lampNo", "1")
                .putKv("lampOnOff", paramValue).putKv("brightness", 0);
            json.addKeyArray("lampList", lampListObj.build().getJsonObj());

            // 下发执行命令
            lightControl(projectIdAttr.getAttrValue(), json.build().getJsonObj());
        }
    }

    public void lightControl(String objCode, String paramValue) {
        List<EmsObjAttrValue> attrValues = objAttrValueService.selectByObjCode(DEV_MODE_CODE, objCode);
        Map<String, EmsObjAttrValue> attrValueMap = attrValues.stream()
            .collect(Collectors.toMap(EmsObjAttrValue::getAttrKey, Function.identity()));

        EmsObjAttrValue projectIdAttr = attrValueMap.get("projectId");
        Assert.notNull(projectIdAttr, -1, "lampList 属性未同步");
        EmsObjAttrValue deviceIdAttr = attrValueMap.get("deviceId");
        Assert.notNull(deviceIdAttr, -1, "deviceId 属性未同步");
        EmsObjAttrValue lampListAttr = attrValueMap.get("lampList");
        Assert.notNull(lampListAttr, -1, "lampList 属性未同步");

        JsonEntity.ObjBuilder json = JsonEntity.objBuilder().addKeyArray("deviceIds", deviceIdAttr.getAttrValue());

        List<SlcDeviceLamp> lampList = JSONArray.parseArray(lampListAttr.getAttrValue(), SlcDeviceLamp.class);
        Assert.notEmpty(lampList, -1, "灯组列表为空");

        for (SlcDeviceLamp lamp : lampList) {
            JsonEntity.ObjBuilder lampListObj = JsonEntity.objBuilder().putKv("lampNo", lamp.getLampNo())
                .putKv("lampOnOff", paramValue).putKv("brightness", 0);

            json.addKeyArray("lampList", lampListObj.build().getJsonObj());
        }

        // 下发执行命令
        lightControl(projectIdAttr.getAttrValue(), json.build().getJsonObj());
    }

    /**
     * 灯组开关控制
     */
    public void lightControl(String projectId, JSONObject req) {
        SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
        CallData<Void> callData = template.lightControl(projectId, req);
        saveCallLog(SUBSYSTEM_CODE, SYS_MODE_CODE, "lightControl", callData.getCallStatus(), callData.getCallPayload(),
            callData.getResPayload());
    }

    public void lightControlBrightness(String objCode, String paramValue) {
        List<EmsObjAttrValue> attrValues = objAttrValueService.selectByObjCode(DEV_MODE_CODE, objCode);
        Map<String, EmsObjAttrValue> attrValueMap = attrValues.stream()
            .collect(Collectors.toMap(EmsObjAttrValue::getAttrKey, v -> v));

        EmsObjAttrValue projectIdAttr = attrValueMap.get("projectId");
        Assert.notNull(projectIdAttr, -1, "projectId 属性未同步");
        EmsObjAttrValue deviceIdAttr = attrValueMap.get("deviceId");
        Assert.notNull(deviceIdAttr, -1, "deviceId 属性未同步");
        EmsObjAttrValue lampListAttr = attrValueMap.get("lampList");
        Assert.notNull(lampListAttr, -1, "lampList 属性未同步");

        JsonEntity.ObjBuilder json = JsonEntity.objBuilder().addKeyArray("deviceIds", deviceIdAttr.getAttrValue());

        List<SlcDeviceLamp> lampList = JSONArray.parseArray(lampListAttr.getAttrValue(), SlcDeviceLamp.class);
        Assert.notEmpty(lampList, -1, "灯组列表为空");

        for (SlcDeviceLamp lamp : lampList) {
            JsonEntity.ObjBuilder lampListObj = JsonEntity.objBuilder().putKv("lampNo", lamp.getLampNo())
                .putKv("brightness", paramValue);

            json.addKeyArray("lampList", lampListObj.build().getJsonObj());
        }

        // 下发控制命令
        lightControlBrightness(projectIdAttr.getAttrValue(), json.build().getJsonObj());
    }

    /**
     * 灯组亮度控制
     */
    public void lightControlBrightness(String projectId, JSONObject req) {
        SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
        CallData<Void> callData = template.controlBrightness(projectId, req);
        saveCallLog(SUBSYSTEM_CODE, SYS_MODE_CODE, "lightControlBrightness", callData.getCallStatus(),
            callData.getCallPayload(), callData.getResPayload());
    }

    public void execGetDeviceList() {
        SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
        CallData<SlcProject> projecCallData = template.getProjectList();
        List<SlcProject> projects = projecCallData.getList();

        if (CollectionUtils.isNotEmpty(projects)) {
            for (SlcProject project : projects) {
                CallData<SlcDevice> callData = template.getDeviceList(project.getProjectId(), null);
                saveCallLog(SUBSYSTEM_CODE, SYS_MODE_CODE, "GetDeviceList", callData.getCallStatus(),
                    callData.getCallPayload(), callData.getResPayload());

                // 灯组设备同步
                List<SlcDevice> lightDevs = callData.getList().stream()
                    .filter(dev -> StringUtils.equals(dev.getDeviceModelId(), "1945454135655632897"))
                    .collect(Collectors.toList());
                syncLightDeviceList(lightDevs);
                mergeLightDevAttrs(project.getProjectId(), lightDevs);

                // 集中器设备同步
                List<SlcDevice> centDevs = callData.getList().stream()
                    .filter(dev -> StringUtils.equals(dev.getDeviceModelId(), "1943504597877362689"))
                    .collect(Collectors.toList());
                syncCentDeviceList(centDevs);
                mergeCentDevAttrValue(project.getProjectId(), centDevs);
            }
        }
    }

    public void syncLightDeviceList(List<SlcDevice> slcDevices) {
        // 查询数据库记录
        QueryDevice param = new QueryDevice();
        param.setDeviceModel(LAMP_POST_MODE_CODE);
        param.setSubsystemCode(SUBSYSTEM_CODE);
        List<EmsDevice> dbDevs = deviceService.selectList(param);

        if (CollectionUtils.isNotEmpty(dbDevs)) {
            for (EmsDevice emsDevice : dbDevs) {
                deviceService.deleteDevice(LAMP_POST_MODE_CODE, emsDevice.getDeviceCode());
                objAttrValueService.deleteByObjCode(LAMP_POST_MODE_CODE, emsDevice.getDeviceCode());
            }
        }

        // 待新增的设备
        if (CollectionUtils.isNotEmpty(slcDevices)) {
            Map<String, SlcDevice> slcDevMap = slcDevices.stream()
                .collect(Collectors.toMap(SlcDevice::getDeviceId, Function.identity()));

            Map<String, List<String>> matchMap = mergeLightDev(slcDevices);

            List<EmsDevice> addDevs = new ArrayList<>();
            List<EmsObjAttrValue> attrValues = new ArrayList<>();

            for (Map.Entry<String, List<String>> entry : matchMap.entrySet()) {
                // 灯杆ID
                String deviceCode = entry.getKey();
                // 原始设备ID
                List<String> deviceIds = entry.getValue();

                SlcDevice slcDeviceTmp = slcDevMap.get(deviceIds.get(0));
                addDevs.add(buildLampPostDevice(deviceCode, slcDeviceTmp));
                attrValues.add(buildLampPostLights(deviceCode, deviceIds));
            }

            addDevs.sort(Comparator.comparing(EmsDevice::getDeviceName));
            deviceService.insertBatch(addDevs);
            objAttrValueService.insertBatch(attrValues);
        }
    }

    private Map<String, List<String>> mergeLightDev(List<SlcDevice> slcDevices) {
        Map<String, List<String>> ret = new HashMap<>();

        for (SlcDevice device : slcDevices) {
            // 获取deviceName的前缀（如"B1"）
            String prefix = "SL-Z-" + StringUtils.substringBefore(device.getDeviceName(), "-");

            // 如果map中不存在该前缀，初始化一个空列表
            ret.computeIfAbsent(prefix, k -> new ArrayList<>());

            // 将当前deviceName添加到对应前缀的列表中
            ret.get(prefix).add(device.getDeviceId());
        }

        return ret;
    }

    public void syncCentDeviceList(List<SlcDevice> slcDevices) {
        // 查询数据库记录
        QueryDevice param = new QueryDevice();
        param.setDeviceModel(CONCENTRATOR);
        param.setSubsystemCode(SUBSYSTEM_CODE);
        List<EmsDevice> dbDevs = deviceService.selectList(param);
        Set<String> dbDevCodeSet = dbDevs.stream().map(EmsDevice::getDeviceCode).collect(Collectors.toSet());

        Map<String, SlcDevice> slcDevMap = slcDevices.stream()
            .collect(Collectors.toMap(SlcDevice::getDeviceCode, Function.identity()));
        Set<String> slcDevCodeSet = slcDevices.stream().map(SlcDevice::getDeviceCode).collect(Collectors.toSet());

        // 待删除的设备
        Set<String> delCodes = new HashSet<>(dbDevCodeSet);
        delCodes.removeAll(slcDevCodeSet);

        if (CollectionUtils.isNotEmpty(delCodes)) {
            for (String code : delCodes) {
                deviceService.deleteDevice(CONCENTRATOR, code);
            }
        }

        // 待新增的设备
        Set<String> addCodes = new HashSet<>(slcDevCodeSet);
        addCodes.removeAll(dbDevCodeSet);

        if (CollectionUtils.isNotEmpty(addCodes)) {
            List<EmsDevice> addDevs = new ArrayList<>();

            for (String code : addCodes) {
                SlcDevice slcDevice = slcDevMap.get(code);
                addDevs.add(buildCentDevice(slcDevice));
            }

            addDevs.sort(Comparator.comparing(EmsDevice::getDeviceName));
            deviceService.insertBatch(addDevs);
        }
    }

    private EmsDevice buildLampPostDevice(String deviceCode, SlcDevice slcDevice) {
        EmsDevice device = new EmsDevice();
        device.setDeviceCode(deviceCode);
        device.setDeviceName(StringUtils.substringBefore(slcDevice.getDeviceName(), "-") + "灯杆");
        device.setDeviceSpec("智慧灯杆");
        device.setDeviceStatus(slcDevice.getStatus());
        device.setDeviceModel(LAMP_POST_MODE_CODE);
        device.setSubsystemCode(SUBSYSTEM_CODE);

        if (StringUtils.startsWith(slcDevice.getDeviceName(), "B")) {
            device.setLocation("北区广场");
            device.setLocationRef("321283124S300104");
            device.setAreaCode("321283124S3001");
            device.setRefFacs("Z-ZM-01");
        }
        else if (StringUtils.startsWith(slcDevice.getDeviceName(), "N")) {
            device.setLocation("南区广场");
            device.setLocationRef("321283124S300204");
            device.setAreaCode("321283124S3002");
            device.setRefFacs("Z-ZM-02");
        }

        return device;
    }

    private EmsObjAttrValue buildLampPostLights(String deviceCode, List<String> lampList) {
        JSONArray jsonArray = new JSONArray();

        for (String lamp : lampList) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("deviceCode", lamp);
            jsonObject.put("modelCode", DEV_MODE_CODE);
            jsonArray.add(jsonObject);
        }

        EmsObjAttrValue attrValue = new EmsObjAttrValue();
        attrValue.setObjCode(deviceCode);
        attrValue.setModelCode(LAMP_POST_MODE_CODE);
        attrValue.setAttrKey("subDev");
        attrValue.setAttrValue(jsonArray.toString());
        return attrValue;
    }

    private EmsDevice buildCentDevice(SlcDevice slcDevice) {
        EmsDevice device = new EmsDevice();
        device.setDeviceCode(slcDevice.getDeviceCode());
        device.setDeviceName(slcDevice.getDeviceName());
        device.setDeviceBrand("佐通");
        device.setDeviceSpec("单灯控制器");
        device.setDeviceStatus(slcDevice.getStatus());
        device.setDeviceModel(CONCENTRATOR);
        device.setSubsystemCode(SUBSYSTEM_CODE);

        if (StringUtils.startsWith(slcDevice.getDeviceName(), "北区")) {
            device.setLocation("北区广场");
            device.setLocationRef("321283124S300104");
            device.setAreaCode("321283124S3001");
            device.setRefFacs("DEV01");
        }
        else if (StringUtils.startsWith(slcDevice.getDeviceName(), "南区")) {
            device.setLocation("南区广场");
            device.setLocationRef("321283124S300204");
            device.setAreaCode("321283124S3002");
            device.setRefFacs("DEV02");
        }

        return device;
    }

    private void mergeLightDevAttrs(String projectId, List<SlcDevice> slcDevices) {
        SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());

        for (SlcDevice slcDevice : slcDevices) {
            mergeLightDevAttr(template, projectId, slcDevice.getDeviceId(), slcDevice);
        }
    }

    private void mergeLightDevAttr(SquareLightCtlTemplate template, String projectId, String deviceId,
        SlcDevice slcDevice) {
        CallData<DeviceInfo> callData = template.getDeviceInfo(projectId, deviceId);
        DeviceInfo deviceInfo = callData.getData();

        List<EmsObjAttrValue> oaValues = objAttrValueService.selectByObjCode(DEV_MODE_CODE, deviceId);

        if (CollectionUtils.isNotEmpty(oaValues)) {
            Map<String, EmsObjAttrValue> vMap = oaValues.stream()
                .collect(Collectors.toMap(EmsObjAttrValue::getAttrKey, Function.identity()));
            checkAndUpdate(vMap, deviceId, CONCENTRATOR, "deviceStatus", convertDeviceStatus(slcDevice.getAbnormal()));

            if (null != deviceInfo.getBaselineInfo()) {
                BaselineInfo baselineInfo = deviceInfo.getBaselineInfo();
                checkAndUpdate(vMap, deviceId, DEV_MODE_CODE, "firmwareVer", baselineInfo.getFirmwareVer());
                checkAndUpdate(vMap, deviceId, DEV_MODE_CODE, "softwareVer", baselineInfo.getSoftwareVer());
            }

            if (null != deviceInfo.getStatusInfo()) {
                StatusInfo sInfo = deviceInfo.getStatusInfo();
                checkAndUpdate(vMap, deviceId, DEV_MODE_CODE, "csq", String.valueOf(sInfo.getCsq()));
                checkAndUpdate(vMap, deviceId, DEV_MODE_CODE, "current", String.valueOf(sInfo.getCurrent()));
                checkAndUpdate(vMap, deviceId, DEV_MODE_CODE, "power", String.valueOf(sInfo.getPower()));
                checkAndUpdate(vMap, deviceId, DEV_MODE_CODE, "factor", String.valueOf(sInfo.getFactor()));
                checkAndUpdate(vMap, deviceId, DEV_MODE_CODE, "voltage", String.valueOf(sInfo.getVoltage()));
                checkAndUpdate(vMap, deviceId, DEV_MODE_CODE, "energy", String.valueOf(sInfo.getEnergy()));
                checkAndUpdate(vMap, deviceId, DEV_MODE_CODE, "temperature", String.valueOf(sInfo.getTemperature()));
            }

            if (CollectionUtils.isNotEmpty(deviceInfo.getLampList())) {
                List<SlcDeviceLamp> lampList = deviceInfo.getLampList();
                SlcDeviceLamp lamp = lampList.get(0);
                checkAndUpdate(vMap, deviceId, DEV_MODE_CODE, "cct", String.valueOf(lamp.getCct()));
                checkAndUpdate(vMap, deviceId, DEV_MODE_CODE, "Switch", String.valueOf(lamp.getLampOnOff()));
            }
        }
        else {
            oaValues = new ArrayList<>();

            oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "projectId", projectId));
            oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "deviceId", deviceId));

            if (null != slcDevice) {
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "deviceName", slcDevice.getDeviceName()));
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "imageUrl", slcDevice.getImageUrl()));
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "deviceStatus", convertDeviceStatus(slcDevice.getAbnormal())));
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "csq", slcDevice.getCsq()));
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "lampList", JSON.toJSONString(slcDevice.getLampList())));
            }

            if (null != deviceInfo.getDeviceInfo()) {
                DevSub subInfo = deviceInfo.getDeviceInfo();
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "deviceUid", subInfo.getDeviceUid()));
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "minCct", String.valueOf(subInfo.getMinCct())));
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "maxCct", String.valueOf(subInfo.getMaxCct())));
            }

            if (null != deviceInfo.getBaselineInfo()) {
                BaselineInfo bInfo = deviceInfo.getBaselineInfo();
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "deviceModelId", bInfo.getDeviceModelId()));
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "firmwareVer", bInfo.getFirmwareVer()));
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "softwareVer", bInfo.getSoftwareVer()));
            }

            if (null != deviceInfo.getStatusInfo()) {
                StatusInfo sInfo = deviceInfo.getStatusInfo();
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "current", String.valueOf(sInfo.getCurrent())));
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "power", String.valueOf(sInfo.getPower())));
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "factor", String.valueOf(sInfo.getFactor())));
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "voltage", String.valueOf(sInfo.getVoltage())));
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "energy", String.valueOf(sInfo.getEnergy())));
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "frequency", String.valueOf(sInfo.getFrequency())));
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "temperature", String.valueOf(sInfo.getTemperature())));
            }

            if (CollectionUtils.isNotEmpty(deviceInfo.getLampList())) {
                List<SlcDeviceLamp> lampList = deviceInfo.getLampList();
                SlcDeviceLamp lamp = lampList.get(0);
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "cct", String.valueOf(lamp.getCct())));
                oaValues.add(new EmsObjAttrValue(deviceId, DEV_MODE_CODE, "Switch", String.valueOf(lamp.getLampOnOff())));
            }

            objAttrValueService.insertBatch(oaValues);
        }
    }

    private void mergeCentDevAttrValue(String projectId, List<SlcDevice> slcDevices) {
        for (SlcDevice slc : slcDevices) {
            List<EmsObjAttrValue> objAttrValues = objAttrValueService.selectByObjCode(CONCENTRATOR,
                slc.getDeviceCode());
            CcElecInfo info = slc.getCcElecInfo();

            if (CollectionUtils.isNotEmpty(objAttrValues)) {
                Map<String, EmsObjAttrValue> vMap = objAttrValues.stream().collect(Collectors.toMap(EmsObjAttrValue::getAttrKey, Function.identity()));
                checkAndUpdate(vMap, slc.getDeviceCode(), CONCENTRATOR, "deviceStatus", convertDeviceStatus(slc.getAbnormal()));
                checkAndUpdate(vMap, slc.getDeviceCode(), CONCENTRATOR, "csq", String.valueOf(slc.getCsq()));
                checkAndUpdate(vMap, slc.getDeviceCode(), CONCENTRATOR, "kwh", String.valueOf(info.getKwh()));
                checkAndUpdate(vMap, slc.getDeviceCode(), CONCENTRATOR, "kvarh", String.valueOf(info.getKvarh()));
                checkAndUpdate(vMap, slc.getDeviceCode(), CONCENTRATOR, "ua", String.valueOf(info.getUa()));
                checkAndUpdate(vMap, slc.getDeviceCode(), CONCENTRATOR, "ub", String.valueOf(info.getUb()));
                checkAndUpdate(vMap, slc.getDeviceCode(), CONCENTRATOR, "uc", String.valueOf(info.getUc()));
                checkAndUpdate(vMap, slc.getDeviceCode(), CONCENTRATOR, "ia", String.valueOf(info.getIa()));
                checkAndUpdate(vMap, slc.getDeviceCode(), CONCENTRATOR, "ib", String.valueOf(info.getIb()));
                checkAndUpdate(vMap, slc.getDeviceCode(), CONCENTRATOR, "ic", String.valueOf(info.getIc()));
                checkAndUpdate(vMap, slc.getDeviceCode(), CONCENTRATOR, "pfa", String.valueOf(info.getPfa()));
                checkAndUpdate(vMap, slc.getDeviceCode(), CONCENTRATOR, "pfb", String.valueOf(info.getPfb()));
                checkAndUpdate(vMap, slc.getDeviceCode(), CONCENTRATOR, "pfc", String.valueOf(info.getPfc()));
                checkAndUpdate(vMap, slc.getDeviceCode(), CONCENTRATOR, "hza", String.valueOf(info.getHza()));
                checkAndUpdate(vMap, slc.getDeviceCode(), CONCENTRATOR, "hzb", String.valueOf(info.getHzb()));
                checkAndUpdate(vMap, slc.getDeviceCode(), CONCENTRATOR, "hzc", String.valueOf(info.getHzc()));
            }
            else {
                objAttrValues = new ArrayList<>();
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "projectId", projectId));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "deviceId", slc.getDeviceId()));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "deviceUid", slc.getDeviceUid()));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "deviceModelId", slc.getDeviceModelId()));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "imageUrl", slc.getImageUrl()));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "deviceStatus", convertDeviceStatus(slc.getAbnormal())));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "csq", String.valueOf(slc.getCsq())));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "kwh", String.valueOf(info.getKwh())));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "kvarh", String.valueOf(info.getKvarh())));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "ua", String.valueOf(info.getUa())));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "ub", String.valueOf(info.getUb())));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "uc", String.valueOf(info.getUc())));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "ia", String.valueOf(info.getIa())));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "ib", String.valueOf(info.getIb())));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "ic", String.valueOf(info.getIc())));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "pfa", String.valueOf(info.getPfa())));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "pfb", String.valueOf(info.getPfb())));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "pfc", String.valueOf(info.getPfc())));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "hza", String.valueOf(info.getHza())));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "hzb", String.valueOf(info.getHzb())));
                objAttrValues.add(new EmsObjAttrValue(slc.getDeviceCode(), CONCENTRATOR, "hzc", String.valueOf(info.getHzc())));

                objAttrValueService.insertBatch(objAttrValues);
            }
        }
    }

    private String convertDeviceStatus(Integer abnormal) {
        if (null == abnormal) {
            return "0";
        }
        else {
            return abnormal == 0 ? "1" : "0";
        }
    }
}