package com.dcs.hnyz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.dcs.common.enums.GeneralStatus;
import com.dcs.common.exception.CustomException;
import com.dcs.common.exception.ServiceException;
import com.dcs.common.utils.StringUtils;
import com.dcs.common.utils.StringUtils;
import com.dcs.common.utils.bean.BeanUtils;
import com.dcs.equipment.task.ModbusTcpTask;
import com.dcs.hnyz.domain.Equipment;
import com.dcs.hnyz.domain.EquipmentParam;
import com.dcs.hnyz.domain.vo.EquipmentParamFormVO;
import com.dcs.hnyz.enums.DeviceTypeEnum;
import com.dcs.hnyz.enums.RegisterTypeEnum;
import com.dcs.hnyz.mapper.EquipmentParamMapper;
import com.dcs.hnyz.service.IEquipmentParamService;
import com.dcs.hnyz.service.IEquipmentService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.dcs.framework.datasource.DynamicDataSourceContextHolder.log;

/**
 * 设备参数管理Service业务层处理
 *
 * @author hmy
 * @date 2025-04-23
 */
@Service
public class EquipmentParamServiceImpl implements IEquipmentParamService {
    @Resource
    private EquipmentParamMapper equipmentParamMapper;

    @Resource
    private IEquipmentService equipmentService;

    //设备id-->寄存器唯一code，用于配置
//    private Map<Integer,String> registerCodeMap = new HashMap<>();

    /**
     * 查询设备参数管理
     *
     * @param registerId 设备参数管理主键
     * @return 设备参数管理
     */
    @Override
    public EquipmentParam selectEquipmentParamByRegisterId(Long registerId) {
        return equipmentParamMapper.selectById(registerId);
    }

    /**
     * 查询设备参数管理列表
     *
     * @param equipmentParam 设备参数管理
     * @return 设备参数管理
     */
    @Override
    public List<EquipmentParam> selectEquipmentParamList(EquipmentParam equipmentParam) {
        return equipmentParamMapper.selectEquipmentParamList(equipmentParam);
    }

    /**
     * 新增设备参数管理
     *
     * @param equipmentParam 设备参数管理
     * @return 结果
     */
    @Override
    public int insertEquipmentParam(EquipmentParam equipmentParam) {
        LambdaQueryWrapper<EquipmentParam> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentParam::getCode, equipmentParam.getCode());
        EquipmentParam ep = equipmentParamMapper.selectOne(wrapper);
        if (ep != null) {
            throw new CustomException("该寄存器标识已存在");
        }
        return equipmentParamMapper.insert(equipmentParam);
    }

    /**
     * 修改设备参数管理
     *
     * @param equipmentParam 设备参数管理
     * @return 结果
     */
    @Override
    public int updateEquipmentParam(EquipmentParam equipmentParam) {
        LambdaQueryWrapper<EquipmentParam> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentParam::getCode, equipmentParam.getCode());
        wrapper.ne(EquipmentParam::getRegisterId, equipmentParam.getRegisterId());
        EquipmentParam ep = equipmentParamMapper.selectOne(wrapper);
        if (ep != null) {
            throw new CustomException("该寄存器标识已存在");
        }
        return equipmentParamMapper.updateById(equipmentParam);
    }

    /**
     * 批量删除设备参数管理
     *
     * @param registerIds 需要删除的设备参数管理主键
     * @return 结果
     */
    @Override
    public int deleteEquipmentParamByRegisterIds(Long[] registerIds) {
        return equipmentParamMapper.deleteBatchIds(Arrays.asList(registerIds));
    }

    /**
     * 删除设备参数管理信息
     *
     * @param registerId 设备参数管理主键
     * @return 结果
     */
    @Override
    public int deleteEquipmentParamByRegisterId(Long registerId) {
        return equipmentParamMapper.deleteById(registerId);
    }

    @Override
    public List<EquipmentParamFormVO> selectEquipmentParamForm(EquipmentParam equipmentParam) {
        return equipmentParamMapper.selectEquipmentParamForm(equipmentParam);
    }

    // TODO 改ID获取为识别码获取 保存到缓存 equipmentParamList变更才更新缓存
    @Override
    public Map<Integer, Integer> getEquipmentIndexList() {
        Map<Integer, Integer> swappedMap = new HashMap<>();
        List<EquipmentParam> equipmentFormVoList = ModbusTcpTask.equipmentParamList;
        for (int i = 0; i < equipmentFormVoList.size(); i++) {
            swappedMap.put(Math.toIntExact(equipmentFormVoList.get(i).getRegisterId()), i);
        }
        return swappedMap;
    }

    // TODO 根据设备id获取对应的主数据所在寄存器的唯一code（暂时只处理了传感器和阀门相关）
    @Override
    public String getCodeByParentId(Long parentId) {
        if (parentId == null) {
            log.warn("parentId is null");
            return null;
        }
        Equipment e = equipmentService.selectEquipmentByEquipmentId(parentId);
        if (e == null) {
            log.warn("根据 parentId:{} 没有查询到设备信息", parentId);
            return null;
        }
        DeviceTypeEnum type = DeviceTypeEnum.fromCode(e.getEquipmentType());
        LambdaQueryWrapper<EquipmentParam> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentParam::getRelationId, parentId);
        switch (type) {
            case SENSOR:
            case VALVE_WITH_FEEDBACK:
                // 处理有反馈阀门逻辑
                // 处理传感器逻辑
                wrapper.eq(EquipmentParam::getParamType, RegisterTypeEnum.MASTER_DATA.getCode());
                break;
            case VALVE_NO_FEEDBACK:
                // 处理无反馈阀门逻辑(用控制信号来代替反馈信号)
                wrapper.eq(EquipmentParam::getParamType, RegisterTypeEnum.MASTER_SET.getCode());
                break;
            case PUMP:
                // 处理泵逻辑
                return null;
            default:
                // 其他类型
                return null;
        }
        EquipmentParam ep = equipmentParamMapper.selectOne(wrapper);
        if (ep == null) {
            log.warn("根据 parentId:{} 查询不到设备参数1", parentId);
            return null;
        }
        return ep.getCode();
    }

    @Override
    public Integer getSetCodeByParentId(Long parentId) {
        if (parentId == null) {
            log.warn("parentId is null");
            return null;
        }
        Equipment e = equipmentService.selectEquipmentByEquipmentId(parentId);
        if (e == null) {
            log.warn("根据 parentId:{} 没有查询到设备信息", parentId);
            return null;
        }
        DeviceTypeEnum type = DeviceTypeEnum.fromCode(e.getEquipmentType());
        LambdaQueryWrapper<EquipmentParam> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentParam::getRelationId, parentId);
        switch (type) {
            case SENSOR:
            case VALVE_WITH_FEEDBACK:
            case VALVE_NO_FEEDBACK:
                // 处理传感器,阀门逻辑
                wrapper.eq(EquipmentParam::getParamType, RegisterTypeEnum.MASTER_SET.getCode());
                break;
            case PUMP:
                // 处理泵逻辑
                return null;
            default:
                // 其他类型
                return null;
        }
        EquipmentParam ep = equipmentParamMapper.selectOne(wrapper);
        if (ep == null) {
            log.warn("根据 parentId:{} 查询不到设备参数2", parentId);
            return null;
        }
        return ep.getAddress();
    }

    @Override
    public List<String> getCodesByParentId(Long parentId) {
        if (parentId == null) {
            log.warn("parentId is null");
            return Collections.emptyList();
        }

        Equipment equipment = equipmentService.selectEquipmentByEquipmentId(parentId);
        if (equipment == null) {
            log.warn("根据 parentId:{} 没有查询到设备信息", parentId);
            return Collections.emptyList();
        }

        DeviceTypeEnum type = DeviceTypeEnum.fromCode(equipment.getEquipmentType());
        if (type == null) {
            log.warn("未知设备类型: {}", equipment.getEquipmentType());
            return Collections.emptyList();
        }

        // 初始化查询 wrapper
        LambdaQueryWrapper<EquipmentParam> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentParam::getRelationId, parentId);

        List<String> paramTypes = new ArrayList<>();

        // 根据设备类型确定查询的寄存器类型
        switch (type) {
            case SENSOR://传感器
                paramTypes.add(RegisterTypeEnum.MASTER_DATA.getCode());
                break;
            case VALVE_WITH_FEEDBACK://有反馈阀门
                paramTypes.add(RegisterTypeEnum.MASTER_DATA.getCode());
                paramTypes.add(RegisterTypeEnum.SLAVE_DATA.getCode());
                paramTypes.add(RegisterTypeEnum.MASTER_SET.getCode());
                break;
            case VALVE_NO_FEEDBACK://无反馈阀门
                paramTypes.add(RegisterTypeEnum.MASTER_SET.getCode());
                break;
            case PUMP://泵
                paramTypes.add(RegisterTypeEnum.MASTER_DATA.getCode());//状态
                paramTypes.add(RegisterTypeEnum.SLAVE_DATA.getCode());//频率
                break;
            default:
                return Collections.emptyList();
        }

        // 查询所有符合条件的寄存器
        wrapper.in(EquipmentParam::getParamType, paramTypes);
        List<EquipmentParam> paramList = equipmentParamMapper.selectList(wrapper);
        // 根据 paramTypes 顺序排序
        paramList.sort(Comparator.comparingInt(p -> paramTypes.indexOf(p.getParamType())));
        if (CollectionUtils.isEmpty(paramList)) {
            log.warn("根据 parentId:{} 没有查询到对应类型的寄存器", parentId);
            return Collections.emptyList();
        }

        // 提取 code 并返回
        return paramList.stream()
                .map(EquipmentParam::getCode)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    @Override
    public List<EquipmentParam> selectEquipmentParamListByDataType(List<String> dataTypes) {
        LambdaQueryWrapper<EquipmentParam> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(EquipmentParam::getDataType, dataTypes);
        wrapper.in(EquipmentParam::getParamType, RegisterTypeEnum.MASTER_DATA.getCode(), RegisterTypeEnum.SLAVE_DATA.getCode());
        wrapper.eq(EquipmentParam::getStatus, GeneralStatus.ENABLE.getCode());
        return equipmentParamMapper.selectList(wrapper);
    }

    @Override
    public Map<String, Object> getRegisterQuantity() {
        Map<String, Object> map = new HashMap<>();
        //查询目前传感器数量
        int sensorNum_now = Math.toIntExact(equipmentParamMapper.selectCount(null));
        map.put("value", sensorNum_now);
        //昨日传感器数量
        LocalDate today = LocalDate.now();
        LocalDateTime startOfDay = today.atStartOfDay();
        LambdaQueryWrapper<EquipmentParam> w = new LambdaQueryWrapper<>();
        w.lt(EquipmentParam::getCreateTime, startOfDay);
        int sensorNum_yesterday = Math.toIntExact(equipmentParamMapper.selectCount(w));
        //今日传感器数量变化
        map.put("trend", sensorNum_now - sensorNum_yesterday);
        return map;
    }

    @Override
    public Map<Long, String> getCodeMapByParentIds(List<Long> validEquipmentIds) {
        if (CollectionUtils.isEmpty(validEquipmentIds)) {
            return Collections.emptyMap();
        }
        Map<Long, String> result = new HashMap<>();
        for (Long id : validEquipmentIds) {
            String code = getCodeByParentId(id);
            if (code != null) {
                result.put(id, code);
            }
        }
        return result;
    }

    @Override
    public List<EquipmentParam> selectEquipmentParamListByProtocolId(Integer protocolId) {
        return equipmentParamMapper.selectEquipmentParamListByProtocolId(protocolId);
    }

    @Override
    public EquipmentParam selectEquipmentParamByCode(String code) {
        return equipmentParamMapper.selectEquipmentParamByCode(code);
    }

    @Override
    public EquipmentParam getMainSetParam(String code) {
        Equipment e = equipmentService.getEquipmentByCode(code);
        LambdaQueryWrapper<EquipmentParam> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentParam::getRelationId, e.getEquipmentId());
        wrapper.eq(EquipmentParam::getParamType, RegisterTypeEnum.MASTER_SET.getCode());
        EquipmentParam ep = equipmentParamMapper.selectOne(wrapper);

        ep.setIpAddress(e.getIpAddress());
        ep.setPort(e.getPort());
        ep.setProtocolId(e.getProtocolId());
        return ep;
    }

    @Override
    public List<EquipmentParam> getAllSetParam(String code) {
        Equipment e = equipmentService.getEquipmentByCode(code);
        if (e == null) {
            throw new CustomException("未找到设备：" + code);
        }
        LambdaQueryWrapper<EquipmentParam> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentParam::getRelationId, e.getEquipmentId());
        wrapper.in(EquipmentParam::getParamType, RegisterTypeEnum.MASTER_SET.getCode(), RegisterTypeEnum.SLAVE_SET.getCode());
        wrapper.eq(EquipmentParam::getStatus, GeneralStatus.ENABLE.getCode());
        //按ParamType升序(主设置,从设置)
        wrapper.orderByAsc(EquipmentParam::getParamType);
        List<EquipmentParam> epList = equipmentParamMapper.selectList(wrapper);
        //填充通信参数
        for (EquipmentParam ep : epList) {
            ep.setIpAddress(e.getIpAddress());
            ep.setPort(e.getPort());
            ep.setProtocolId(e.getProtocolId());
        }
        return epList;
    }

    @Override
    public String importEquipment(List<EquipmentParam> equipmentList, boolean isUpdateSupport, String operName) {

        if (StringUtils.isNull(equipmentList) || equipmentList.size() == 0)
        {
            throw new ServiceException("导入设备数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (EquipmentParam param : equipmentList)
        {
            try
            {
                // 验证是否存在这个设备
                EquipmentParam e = equipmentParamMapper.selectOne(new QueryWrapper<EquipmentParam>().eq("code", param.getCode()));
                if (StringUtils.isNull(e))
                {
                    // TODO 获取设备类型字符串查询设备类型库 填充相应的设备类型 id
                    // TODO 模糊查询设备 识别码 填充相应的设备 id 没有命中需返回消息提示无设备
                    param.setCreateBy(operName);
                    equipmentParamMapper.insert(param);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、设备参数 " + param.getCode() + " 导入成功");
                }
                else if (isUpdateSupport)
                {
                    param.setCreateBy(operName);
                    equipmentParamMapper.insert(param);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、设备参数 " + param.getCode() + " 更新成功");
                }
                else
                {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、设备参数 " + param.getCode() + " 已存在");
                }
            }
            catch (Exception e)
            {
                failureNum++;
                String msg = "<br/>" + failureNum + "、设备 " + param.getCode() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
//                log.error(msg, e);
            }
        }
        if (failureNum > 0)
        {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        }
        else
        {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }
    @Override
    public int updateRegisterNameByEquipment(Equipment equipment) {
        if (equipment == null || equipment.getEquipmentId() == null ||
                StringUtils.isBlank(equipment.getEquipmentName())) {
            // 校验入参，避免空指针或无效数据
            return 0;
        }

        String eqName = equipment.getEquipmentName();
        LambdaQueryWrapper<EquipmentParam> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentParam::getRelationId, equipment.getEquipmentId())
                .eq(EquipmentParam::getStatus, GeneralStatus.ENABLE.getCode());

        List<EquipmentParam> epList = equipmentParamMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(epList)) {
            // 没有需要更新的参数，直接返回
            return 0;
        }

        // 预编译正则表达式，避免循环中重复编译
        Pattern pattern = Pattern.compile("[\\u4e00-\\u9fa5\\uF900-\\uFA2D]+$");
        int updateCount = 0; // 记录成功更新的数量

        for (EquipmentParam ep : epList) {
            String registerName = ep.getRegisterName();
            if (StringUtils.isBlank(registerName)) {
                continue; // 跳过空注册名的参数
            }

            Matcher matcher = pattern.matcher(registerName);
            String newRegisterName;

            if (matcher.find()) {
                // 保留原有的中文后缀，前面拼接设备名称
                newRegisterName = eqName + matcher.group();
            } else {
                // 如果没有中文后缀，直接使用设备名称作为注册名
                newRegisterName = eqName;
            }

            // 只有当注册名发生变化时才执行更新
            if (!newRegisterName.equals(registerName)) {
                ep.setRegisterName(newRegisterName);
                updateCount += equipmentParamMapper.updateById(ep);
            }
        }

        return updateCount; // 返回实际更新成功的数量
    }

    @Override
//    public Map<String, List<Object>> getAllParamConfigDataByCodeList(List<String> codeList) {
//        Map<String, Long> equipmentIdCodeMap = equipmentService.getEquipmentIdCodeMap();//设备code与id的映射
//        List<EquipmentParamFormVO> broadCastEquipmentParamFormVOList = ModbusTcpTask.getBroadCastEquipmentParamFormVOList();
//        Map<String, List<Object>> result = new HashMap<>();
//        codeList.forEach(code -> {
//            List<Object> dataList = new ArrayList<>();
//            if (equipmentIdCodeMap.containsKey(code)) {
//                long equipmentId = equipmentIdCodeMap.get(code);
//                LambdaQueryWrapper<EquipmentParam> wrapper = new LambdaQueryWrapper<>();
//                wrapper.eq(EquipmentParam::getRelationId, equipmentId);
//                wrapper.eq(EquipmentParam::getStatus, GeneralStatus.ENABLE.getCode());
//                wrapper.in(EquipmentParam::getParamType, RegisterTypeEnum.PARAM_CONFIG1.getCode(), RegisterTypeEnum.PARAM_CONFIG2.getCode(), RegisterTypeEnum.PARAM_CONFIG3.getCode(), RegisterTypeEnum.PARAM_CONFIG4.getCode(), RegisterTypeEnum.PARAM_CONFIG5.getCode());
//                wrapper.orderByAsc(EquipmentParam::getParamType);//按ParamType升序(参数配置1,2,3,4,5)
//                List<EquipmentParam> epList = equipmentParamMapper.selectList(wrapper);
//                epList.forEach(equipmentParam -> {
//                    //把对应的value加入dataList
//                    dataList.add(broadCastEquipmentParamFormVOList.stream().filter(broadCastEquipmentParamFormVO -> broadCastEquipmentParamFormVO.getCode().equals(equipmentParam.getCode())).findFirst().orElse(null).getValue());
//                });
//            }
//            result.put(code, dataList);
//        });
//        return result;
//    }

    public Map<String, List<Object>> getAllParamConfigDataByCodeList(List<String> codeList) {
        // 1. 获取设备code与id的映射（原逻辑保留）
        Map<String, Long> equipmentIdCodeMap = equipmentService.getEquipmentIdCodeMap();
        if (equipmentIdCodeMap.isEmpty()) {
            return Collections.emptyMap();
        }

        // 2. 预构建broadCastVO的code->VO映射（O(m)构建，后续查询O(1)）
        List<EquipmentParamFormVO> broadCastList = ModbusTcpTask.getBroadCastEquipmentParamFormVOList();
        Map<String, EquipmentParamFormVO> broadCastCodeMap = broadCastList.stream()
                .collect(Collectors.toMap(
                        EquipmentParamFormVO::getCode,  // key为VO的code
                        vo -> vo,                      // value为VO本身
                        (existing, replacement) -> existing  // 处理code重复（保留第一个）
                ));

        // 3. 收集有效的equipmentId（过滤不存在的code，去重）
        Set<Long> validEquipmentIds = codeList.stream()
                .filter(equipmentIdCodeMap::containsKey)  // 只保留存在的code
                .map(equipmentIdCodeMap::get)             // 转为equipmentId
                .collect(Collectors.toSet());             // 去重，避免重复查询

        if (validEquipmentIds.isEmpty()) {
            return Collections.emptyMap();
        }

        // 4. 批量查询所有有效的EquipmentParam（一次数据库查询）
        LambdaQueryWrapper<EquipmentParam> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(EquipmentParam::getRelationId, validEquipmentIds)  // 批量匹配equipmentId
                .eq(EquipmentParam::getStatus, GeneralStatus.ENABLE.getCode())
                .in(EquipmentParam::getParamType,
                        RegisterTypeEnum.PARAM_CONFIG1.getCode(),
                        RegisterTypeEnum.PARAM_CONFIG2.getCode(),
                        RegisterTypeEnum.PARAM_CONFIG3.getCode(),
                        RegisterTypeEnum.PARAM_CONFIG4.getCode(),
                        RegisterTypeEnum.PARAM_CONFIG5.getCode()
                )
                .orderByAsc(EquipmentParam::getParamType);

        List<EquipmentParam> allEpList = equipmentParamMapper.selectList(wrapper);

        // 5. 按relationId（即equipmentId）分组，便于后续快速获取
        Map<Long, List<EquipmentParam>> epGroupByEquipmentId = allEpList.stream()
                .collect(Collectors.groupingBy(EquipmentParam::getRelationId));

        // 6. 构建结果（遍历codeList，填充数据）
        Map<String, List<Object>> result = new HashMap<>(codeList.size());  // 预设容量
        for (String code : codeList) {
            List<Object> dataList = new ArrayList<>();
            Long equipmentId = equipmentIdCodeMap.get(code);
            if (equipmentId == null) {
                result.put(code, dataList);  // 无效code，返回空列表
                continue;
            }

            // 从分组中获取当前equipmentId对应的参数列表
            List<EquipmentParam> epList = epGroupByEquipmentId.getOrDefault(equipmentId, Collections.emptyList());
            for (EquipmentParam ep : epList) {
                // 从预构建的map中快速获取VO，避免遍历
                EquipmentParamFormVO vo = broadCastCodeMap.get(ep.getCode());
                dataList.add(vo != null ? vo.getValue() : null);  // 避免空指针
            }
            result.put(code, dataList);
        }

        return result;
    }

    @Override
    public List<EquipmentParam> getAllParamConfigByCode(String code) {
        Equipment e = equipmentService.getEquipmentByCode(code);
        if (e == null) {
            throw new CustomException("未找到设备：" + code);
        }
        LambdaQueryWrapper<EquipmentParam> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentParam::getRelationId, e.getEquipmentId());
        wrapper.eq(EquipmentParam::getStatus, GeneralStatus.ENABLE.getCode());
        wrapper.in(EquipmentParam::getParamType, RegisterTypeEnum.PARAM_CONFIG1.getCode(), RegisterTypeEnum.PARAM_CONFIG2.getCode(), RegisterTypeEnum.PARAM_CONFIG3.getCode(), RegisterTypeEnum.PARAM_CONFIG4.getCode(), RegisterTypeEnum.PARAM_CONFIG5.getCode());
        wrapper.orderByAsc(EquipmentParam::getParamType);//按ParamType升序(参数配置1,2,3,4,5)
        List<EquipmentParam> epList = equipmentParamMapper.selectList(wrapper);
        epList.forEach(ep -> {
            ep.setIpAddress(e.getIpAddress());
            ep.setPort(e.getPort());
            ep.setProtocolId(e.getProtocolId());
        });
        return epList;
    }

}
