package com.njcn.csdevice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.csdevice.api.CsCommTerminalFeignClient;
import com.njcn.csdevice.constant.DataParam;
import com.njcn.csdevice.enums.LineBaseEnum;
import com.njcn.csdevice.mapper.*;
import com.njcn.csdevice.pojo.dto.DevDetailDTO;
import com.njcn.csdevice.pojo.dto.LineParamDTO;
import com.njcn.csdevice.pojo.param.CsLedgerParam;
import com.njcn.csdevice.pojo.po.*;
import com.njcn.csdevice.pojo.vo.CsLedgerVO;
import com.njcn.csdevice.service.*;
import com.njcn.csharmonic.api.PqGovernPlanFeignClient;
import com.njcn.csharmonic.api.PqSensitiveUserFeignClient;
import com.njcn.csharmonic.pojo.po.PqGovernPlan;
import com.njcn.device.biz.pojo.po.PqSensitiveUser;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.system.api.AreaFeignClient;
import com.njcn.system.api.DictTreeFeignClient;
import com.njcn.system.enums.DicDataEnum;
import com.njcn.system.pojo.po.Area;
import com.njcn.system.pojo.vo.DictTreeVO;
import com.njcn.user.enums.AppRoleEnum;
import com.njcn.web.utils.RequestUtil;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 台账表 服务实现类
 * </p>
 *
 * @author xuyang
 * @since 2023-05-31
 */
@Service
@AllArgsConstructor
public class CsLedgerServiceImpl extends ServiceImpl<CsLedgerMapper, CsLedger> implements ICsLedgerService {

    private final AreaFeignClient areaFeignClient;
    private final RedisUtil redisUtil;
    private final AppTopologyDiagramMapper appTopologyDiagramMapper;
    private final AppProjectMapper appProjectMapper;
    private final CsEngineeringMapper csEngineeringMapper;
    private final CsLinePOService csLinePOService;
    private final RoleEngineerDevService roleEngineerDevService;
    private final CsDevModelRelationService csDevModelRelationService;
    private final CsEquipmentDeliveryMapper csEquipmentDeliveryMapper;
    private final ICsDataSetService csDataSetService;
    private final DictTreeFeignClient dictTreeFeignClient;
    private final CsDeviceUserPOMapper csDeviceUserPOMapper;
    private final PqGovernPlanFeignClient pqGovernPlanFeignClient;
    private final PqSensitiveUserFeignClient pqSensitiveUserFeignClient;
    private final ICsUserPinsService csUserPinsService;
    private final CsCommTerminalFeignClient csCommTerminalFeignClient;


    @Override
    public List<CsLedgerVO> getLedgerTree() {
        List<CsLedgerVO> list = new ArrayList<>();
        List<CsLedgerVO> engineeringList = getLineTree(null);
        CsLedgerVO vo = new CsLedgerVO();
        vo.setId("9999999");
        vo.setLevel(0);
        vo.setName("台账管理");
        if (CollectionUtil.isNotEmpty(engineeringList)) {
            vo.setChildren(engineeringList);
        }
        list.add(vo);
        return list;
    }

    @Override
    public List<CsLedgerVO> getLineTree(String type) {
        List<CsLedgerVO> engineeringList;
        List<CsLedgerVO> allList = this.baseMapper.getAll();
        /*获取用户工程，设备信息过滤*/
        List<String> roleengineer = roleEngineerDevService.getRoleengineer();
        List<String> device = roleEngineerDevService.getDevice();
        //区分治理装置和云前置装置
        List<String> zhiLianDevice = new ArrayList<>();
        List<String> portableDevice = new ArrayList<>();
        List<String> cldDevice = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(device)) {
            List<CsEquipmentDeliveryPO> csEquipmentDeliveryPOS = csEquipmentDeliveryMapper.selectBatchIds(device);
            DictTreeVO vo1 = dictTreeFeignClient.queryByCode(DicDataEnum.DEV_CLD.getCode()).getData();
            Optional.ofNullable(vo1)
                    .map(DictTreeVO::getId)
                    .ifPresent(id -> csEquipmentDeliveryPOS.stream()
                            .filter(item -> Objects.equals(item.getDevType(), id))
                            .map(CsEquipmentDeliveryPO::getId)
                            .forEach(cldDevice::add)
                    );
            DictTreeVO vo2 = dictTreeFeignClient.queryByCode(DicDataEnum.CONNECT_DEV.getCode()).getData();
            Optional.ofNullable(vo2)
                    .map(DictTreeVO::getId)
                    .ifPresent(id -> csEquipmentDeliveryPOS.stream()
                            .filter(item -> Objects.equals(item.getDevType(), id))
                            .map(CsEquipmentDeliveryPO::getId)
                            .forEach(zhiLianDevice::add)
                    );
            DictTreeVO vo3 = dictTreeFeignClient.queryByCode(DicDataEnum.PORTABLE.getCode()).getData();
            Optional.ofNullable(vo3)
                    .map(DictTreeVO::getId)
                    .ifPresent(id -> csEquipmentDeliveryPOS.stream()
                            .filter(item -> Objects.equals(item.getDevType(), id))
                            .map(CsEquipmentDeliveryPO::getId)
                            .forEach(portableDevice::add)
                    );
        }
        engineeringList = allList.stream().filter(item -> roleengineer.contains(item.getId())).collect(Collectors.toList());
        List<CsLedgerVO> projectList = allList.stream().filter(item -> item.getLevel().equals(LineBaseEnum.PROJECT_LEVEL.getCode())).sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());

        Map<String, CsEquipmentDeliveryPO> poMap = allList.stream()
                .filter(item -> device.contains(item.getId()) && !Objects.equals(item.getPid(), "0"))
                .map(CsLedgerVO::getId)
                .distinct()
                .collect(Collectors.toMap(
                        Function.identity(),
                        csEquipmentDeliveryMapper::selectById
                ));

        List<CsLedgerVO> deviceList = allList.stream()
                .filter(item -> zhiLianDevice.contains(item.getId()) && !Objects.equals(item.getPid(), "0"))
                .peek(item -> {
                    CsEquipmentDeliveryPO po = poMap.get(item.getId());
                    item.setComFlag(po.getRunStatus());
                    item.setNDId(po.getNdid());
                    item.setType("device");
                    item.setProcess(po.getProcess());
                    item.setDevConType(po.getDevAccessMethod());
                })
                .filter(item -> Objects.equals(poMap.get(item.getId()).getUsageStatus(), 1))
                .sorted(Comparator.comparing(CsLedgerVO::getSort))
                .collect(Collectors.toList());

        List<CsLedgerVO> cldDeviceList = allList.stream()
                .filter(item -> cldDevice.contains(item.getId()) && !Objects.equals(item.getPid(), "0"))
                .peek(item -> {
                    CsEquipmentDeliveryPO po = poMap.get(item.getId());
                    item.setComFlag(po.getRunStatus());
                    item.setNDId(po.getNdid());
                    item.setType("device");
                    item.setProcess(po.getProcess());
                    item.setDevConType(po.getDevAccessMethod());
                })
                .filter(item -> Objects.equals(poMap.get(item.getId()).getUsageStatus(), 1))
                .sorted(Comparator.comparing(CsLedgerVO::getSort))
                .collect(Collectors.toList());
        //获取治理方案
        List<PqGovernPlan> governPlan = pqGovernPlanFeignClient.getListExcludeNull().getData();
        Map<String, PqGovernPlan> beforeMap = Optional.ofNullable(governPlan)
                .orElse(Collections.emptyList())
                .stream()
                .filter(p -> p.getGovernBefore() != null)
                .collect(Collectors.toMap(
                        PqGovernPlan::getGovernBefore,
                        Function.identity(),
                        (v1, v2) -> v1
                ));
        Map<String, PqGovernPlan> afterMap = Optional.ofNullable(governPlan)
                .orElse(Collections.emptyList())
                .stream()
                .filter(p -> p.getGovernAfter() != null)
                .collect(Collectors.toMap(
                        PqGovernPlan::getGovernAfter,
                        Function.identity(),
                        (v1, v2) -> v1
                ));
        //获取治理用户
        // 1. governPlan 防 null + 过滤掉 pid 为 null 的数据
        List<String> sensitiveUser = Optional.ofNullable(governPlan)
                .orElse(Collections.emptyList())
                .stream()
                .map(PqGovernPlan::getPid)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        // 2. 没有 id 就不调用远程接口，直接返回空 Map
        Map<String, PqSensitiveUser> sensitiveUserMap;
        if (CollectionUtils.isEmpty(sensitiveUser)) {
            sensitiveUserMap = Collections.emptyMap();
        } else {
            List<PqSensitiveUser> sensitiveUserList = pqSensitiveUserFeignClient
                    .getListByIds(sensitiveUser)
                    .getData();
            // 3. sensitiveUserList 防 null
            sensitiveUserMap = Optional.ofNullable(sensitiveUserList)
                    .orElse(Collections.emptyList())
                    .stream()
                    .filter(u -> u != null && u.getId() != null)
                    .collect(Collectors.toMap(
                            PqSensitiveUser::getId,
                            Function.identity(),
                            (v1, v2) -> v1
                    ));
        }
        List<CsLedgerVO> finalLineList;
        //获取监测点数据
        Integer targetLevel = LineBaseEnum.LINE_LEVEL.getCode();
        List<String> lineIds = allList.stream()
                .filter(item -> item != null && targetLevel.equals(item.getLevel()))
                .map(CsLedgerVO::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(lineIds)) {
            List<CsLinePO> poList = csLinePOService.listByIds(lineIds);
            Map<String, CsLinePO> lineMap = poList.stream().collect(Collectors.toMap(CsLinePO::getLineId,Function.identity(),(v1, v2) -> v1));
            finalLineList = allList.stream()
                    .filter(item -> item.getLevel().equals(targetLevel))
                    .peek(
                            item -> {
                                PqGovernPlan beforePlan = beforeMap.get(item.getId());
                                PqGovernPlan afterPlan  = afterMap.get(item.getId());
                                if (beforePlan != null) {
                                    PqSensitiveUser user = sensitiveUserMap.get(beforePlan.getPid());
                                    item.setSensitiveUserId(beforePlan.getPid());
                                    item.setSensitiveUserName(Objects.isNull(user) ? null : user.getName());
                                    item.setGovernPlanName(beforePlan.getGovernName());
                                }
                                if (afterPlan != null) {
                                    PqSensitiveUser user = sensitiveUserMap.get(afterPlan.getPid());
                                    item.setSensitiveUserId(afterPlan.getPid());
                                    item.setSensitiveUserName(Objects.isNull(user) ? null : user.getName());
                                    item.setGovernPlanName(afterPlan.getGovernName());
                                }
                                item.setType("line");
                                CsLinePO po = lineMap.get(item.getId());
                                item.setConType(po.getConType());
                                if (Objects.isNull(po.getClDid())) {
                                    item.setSort(po.getLineNo());
                                } else {
                                    item.setSort(po.getClDid());
                                }
                                item.setLineType(Objects.equals(po.getClDid(), 0) ? 0 : 1);
                            }
                    )
                    .sorted(Comparator.comparing(CsLedgerVO::getSort, Comparator.nullsLast(Comparator.naturalOrder())))
                    .collect(Collectors.toList());
        } else {
            finalLineList = allList;
        }
        checkDevSetData(deviceList);
        List<CsLedgerVO> engineeringList1 = new ArrayList<>();
        List<CsLedgerVO> projectList1 = new ArrayList<>();
        List<String> dev = deviceList.stream().map(CsLedgerVO::getId).collect(Collectors.toList());
        List<CsLedgerVO> ledger1 = getProAndEngineer(dev);
        if (CollectionUtil.isNotEmpty(ledger1)) {
            deviceList.forEach(dev1 -> dev1.setChildren(getChildren(dev1, finalLineList)));
            engineeringList1 = ledger1.stream().filter(item -> item.getLevel().equals(LineBaseEnum.ENGINEERING_LEVEL.getCode())).sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());
            projectList1 = ledger1.stream().filter(item -> item.getLevel().equals(LineBaseEnum.PROJECT_LEVEL.getCode())).sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());
            projectList1.forEach(pro -> pro.setChildren(getChildren(pro, deviceList)));
            List<CsLedgerVO> finalProjectList = projectList1;
            engineeringList1.forEach(eng -> eng.setChildren(getChildren(eng, finalProjectList)));
        }

        checkDevSetData(cldDeviceList);
        List<CsLedgerVO> engineeringList2 = new ArrayList<>();
        List<CsLedgerVO> projectList2 = new ArrayList<>();
        List<String> dev2 = cldDeviceList.stream().map(CsLedgerVO::getId).collect(Collectors.toList());
        List<CsLedgerVO> ledger2 = getProAndEngineer(dev2);
        if (CollectionUtil.isNotEmpty(ledger2)) {
            cldDeviceList.forEach(dev1 -> dev1.setChildren(getChildren(dev1, finalLineList)));
            engineeringList2 = ledger2.stream().filter(item -> item.getLevel().equals(LineBaseEnum.ENGINEERING_LEVEL.getCode())).sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());
            projectList2 = ledger2.stream().filter(item -> item.getLevel().equals(LineBaseEnum.PROJECT_LEVEL.getCode())).sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());
            projectList2.forEach(pro -> pro.setChildren(getChildren(pro, cldDeviceList)));
            List<CsLedgerVO> finalProjectList = projectList2;
            engineeringList2.forEach(eng -> eng.setChildren(getChildren(eng, finalProjectList)));
        }

        //获取便携式设备树
        CsLedgerVO portable = new CsLedgerVO();
        portable.setLevel(0);
        portable.setName(DataParam.portableDev);
        portable.setPid("0");
        portable.setId(IdUtil.simpleUUID());

        List<CsLedgerVO> ledger = allList.stream().filter(obj -> portableDevice.contains(obj.getId())).collect(Collectors.toList());
        Map<String, CsEquipmentDeliveryPO> poMap2 = ledger.stream()
                .collect(Collectors.toMap(
                        CsLedgerVO::getId,
                        csEquipmentDeliveryMapper::selectById,
                        (existing, replacement) -> existing
                ));
        List<CsLedgerVO> portables = ledger.stream()
                .peek(c -> {
                    CsEquipmentDeliveryPO po = poMap2.get(c.getId());
                    c.setPid("2");
                    c.setComFlag(po.getRunStatus());
                    c.setNDId(po.getNdid());
                    c.setType("device");
                    c.setName(po.getName());
                    c.setSort(po.getSort());
                    c.setDevConType(po.getDevAccessMethod());
                })
                .filter(c -> poMap2.get(c.getId()).getUsageStatus() == 1)
                .collect(Collectors.toList());
        portables = portables.stream().sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());
        portables.forEach(dev3 -> dev3.setChildren(getChildren(dev3, finalLineList)));
        checkDevSetData(portables);
        portable.setChildren(portables);

        CsLedgerVO government = new CsLedgerVO();
        government.setLevel(0);
        government.setName(DataParam.governmentDev);
        government.setPid("0");
        government.setId(IdUtil.simpleUUID());
        government.setChildren(engineeringList1);

        //获取云前置设备树
        CsLedgerVO cld = new CsLedgerVO();
        cld.setLevel(0);
        cld.setName(DataParam.cldDev);
        cld.setPid("0");
        cld.setId(IdUtil.simpleUUID());
        cld.setChildren(engineeringList2);

        List<CsLedgerVO> tree = new ArrayList<>();
        //获取置顶的工程
        List<CsUserPins> list = csUserPinsService.getPinToTopList();
        if (Objects.equals(type,"engineering")) {

            Map<String, CsLedgerVO> engineeringMap = new HashMap<>();

            engineeringList1.forEach(eng -> {
                CsLedgerVO existingEng = engineeringMap.get(eng.getId());
                if (existingEng == null) {
                    engineeringMap.put(eng.getId(), eng);
                } else {
                    List<CsLedgerVO> mergedChildren = mergeProjectList(existingEng.getChildren(), eng.getChildren());
                    existingEng.setChildren(mergedChildren);
                }
            });

            engineeringList2.forEach(eng -> {
                CsLedgerVO existingEng = engineeringMap.get(eng.getId());
                if (existingEng == null) {
                    engineeringMap.put(eng.getId(), eng);
                } else {
                    List<CsLedgerVO> mergedChildren = mergeProjectList(existingEng.getChildren(), eng.getChildren());
                    existingEng.setChildren(mergedChildren);
                }
            });

            tree.addAll(new ArrayList<>(engineeringMap.values()));

            if (CollUtil.isNotEmpty(portables)) {
                String id = IdUtil.simpleUUID();
                CsLedgerVO portable1 = new CsLedgerVO();
                portable1.setLevel(0);
                portable1.setName("便携式工程");
                portable1.setPid("0");
                portable1.setId("1");

                CsLedgerVO portable2 = new CsLedgerVO();
                portable2.setLevel(1);
                portable2.setName("便携式项目");
                portable2.setPid("1");
                portable2.setId("2");
                portable2.setChildren(portables);

                portable1.setChildren(Collections.singletonList(portable2));
                tree.add(portable1);
            }

            if (CollectionUtil.isNotEmpty(list)) {
                csUserPinsService.channelTree(list, tree, 4);
            }
        } else {
            //按设备类型统计
            if (CollUtil.isNotEmpty(portables)) {
                tree.add(portable);
            }
            if (CollUtil.isNotEmpty(deviceList)) {
                tree.add(government);
            }
            if (CollUtil.isNotEmpty(cldDeviceList)) {
                tree.add(cld);
            }

            if (CollectionUtil.isNotEmpty(list)) {
                csUserPinsService.channelTree(list, tree, 5);
            }
        }
        return tree;
    }

    @Override
    public List<CsLedgerVO> appLineTree() {
        //根据用户获取监测点
        List<String> lineIds = csCommTerminalFeignClient.getLineIdsByUser(RequestUtil.getUserIndex()).getData();
        List<String> engineeringIds = roleEngineerDevService.getRoleengineer();

        if (CollectionUtil.isEmpty(lineIds) && CollectionUtil.isEmpty(engineeringIds)) {
            return Collections.emptyList();
        }

        //获取所有台账数据
        List<CsLedgerVO> allList = this.baseMapper.getAll();
        if (CollectionUtil.isEmpty(allList)) {
            return Collections.emptyList();
        }

        Set<String> resultEngineeringIds = new HashSet<>();

        //1. 反推：从监测点向上找到所有相关的工程
        if (CollectionUtil.isNotEmpty(lineIds)) {
            //过滤出监测点数据 (level=3)
            List<CsLedgerVO> lineList = allList.stream()
                    .filter(item -> Objects.equals(item.getLevel(), LineBaseEnum.LINE_LEVEL.getCode()))
                    .filter(item -> lineIds.contains(item.getId()))
                    .collect(Collectors.toList());

            //从监测点向上追溯到工程
            lineList.forEach(line -> {
                String[] pids = line.getPids().split(",");
                //根据层级结构，工程 ID 在 pids 的第一个位置（索引为 1，因为索引 0 是"0"）
                if (pids.length > LineBaseEnum.ENGINEERING_LEVEL.getCode() + 1) {
                    String engineeringId = pids[LineBaseEnum.ENGINEERING_LEVEL.getCode() + 1];
                    resultEngineeringIds.add(engineeringId);
                }
            });
        }

        //2. 正推：添加用户已有的工程 ID
        if (CollectionUtil.isNotEmpty(engineeringIds)) {
            resultEngineeringIds.addAll(engineeringIds);
        }

        if (CollectionUtil.isEmpty(resultEngineeringIds)) {
            return Collections.emptyList();
        }

        //获取所有层级数据并排序
        //监测点数据
        List<CsLedgerVO> lineList = allList.stream()
                .filter(item -> Objects.equals(item.getLevel(), LineBaseEnum.LINE_LEVEL.getCode()))
                .filter(item -> lineIds.contains(item.getId()))
                .sorted(Comparator.comparing(CsLedgerVO::getSort))
                .collect(Collectors.toList());

        //设备数据
        List<CsLedgerVO> deviceList = allList.stream()
                .filter(item -> Objects.equals(item.getLevel(), LineBaseEnum.DEVICE_LEVEL.getCode()))
                .sorted(Comparator.comparing(CsLedgerVO::getSort))
                .collect(Collectors.toList());

        //项目数据
        List<CsLedgerVO> projectList = allList.stream()
                .filter(item -> Objects.equals(item.getLevel(), LineBaseEnum.PROJECT_LEVEL.getCode()))
                .sorted(Comparator.comparing(CsLedgerVO::getSort))
                .collect(Collectors.toList());

        //工程数据，过滤掉名字是"便携式工程"的数据
        List<CsLedgerVO> engineeringList = allList.stream()
                .filter(item -> Objects.equals(item.getLevel(), LineBaseEnum.ENGINEERING_LEVEL.getCode()))
                .filter(item -> resultEngineeringIds.contains(item.getId()))
                .filter(item -> !Objects.equals(item.getName(), "便携式工程"))
                .sorted(Comparator.comparing(CsLedgerVO::getSort))
                .collect(Collectors.toList());

        //构建设备与监测点的关系
        deviceList.forEach(device -> {
            List<CsLedgerVO> children = lineList.stream()
                    .filter(line -> Objects.equals(line.getPid(), device.getId()))
                    .collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(children)) {
                device.setChildren(children);
            }
        });

        //构建项目与设备的关系
        projectList.forEach(project -> {
            List<CsLedgerVO> children = deviceList.stream()
                    .filter(device -> Objects.equals(device.getPid(), project.getId()))
                    .collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(children)) {
                project.setChildren(children);
            }
        });

        //构建工程与项目的关系
        engineeringList.forEach(engineering -> {
            List<CsLedgerVO> children = projectList.stream()
                    .filter(project -> Objects.equals(project.getPid(), engineering.getId()))
                    .collect(Collectors.toList());
            //工程下面可以没有项目，所以即使 children 为空也要保留
            engineering.setChildren(children);
        });

        return engineeringList;
    }

    /**
     * 合并两个项目列表，根据项目 ID 去重并合并子节点
     */
    private List<CsLedgerVO> mergeProjectList(List<CsLedgerVO> list1, List<CsLedgerVO> list2) {
        if (CollectionUtil.isEmpty(list1)) {
            return list2 != null ? new ArrayList<>(list2) : new ArrayList<>();
        }
        if (CollectionUtil.isEmpty(list2)) {
            return new ArrayList<>(list1);
        }

        Map<String, CsLedgerVO> projectMap = new HashMap<>();

        list1.forEach(project -> {
            projectMap.put(project.getId(), cloneProject(project));
        });

        list2.forEach(project -> {
            CsLedgerVO existingProject = projectMap.get(project.getId());
            if (existingProject == null) {
                projectMap.put(project.getId(), cloneProject(project));
            } else {
                List<CsLedgerVO> mergedDevices = new ArrayList<>();
                if (existingProject.getChildren() != null) {
                    mergedDevices.addAll(existingProject.getChildren());
                }
                if (project.getChildren() != null) {
                    mergedDevices.addAll(project.getChildren());
                }
                existingProject.setChildren(mergedDevices);
            }
        });

        List<CsLedgerVO> result = new ArrayList<>(projectMap.values());
        result.sort(Comparator.comparing(CsLedgerVO::getSort, Comparator.nullsLast(Comparator.naturalOrder())));
        return result;
    }

    /**
     * 克隆项目对象，避免引用问题
     */
    private CsLedgerVO cloneProject(CsLedgerVO project) {
        CsLedgerVO cloned = new CsLedgerVO();
        cloned.setId(project.getId());
        cloned.setPid(project.getPid());
        cloned.setLevel(project.getLevel());
        cloned.setName(project.getName());
        cloned.setType(project.getType());
        cloned.setComFlag(project.getComFlag());
        cloned.setNDId(project.getNDId());
        cloned.setProcess(project.getProcess());
        cloned.setLineType(project.getLineType());
        cloned.setConType(project.getConType());
        cloned.setSort(project.getSort());
        if (project.getChildren() != null) {
            cloned.setChildren(new ArrayList<>(project.getChildren()));
        }
        return cloned;
    }

    //剔除未接入的设备(根据status判断不太稳,所有这里直接判断该设备有没有对应的模板指标)
    private void checkDevSetData(List<CsLedgerVO> ledgerVOS) {
        Iterator<CsLedgerVO> iterator = ledgerVOS.iterator();
        while (iterator.hasNext()) {
            CsLedgerVO csLedgerVO = iterator.next();
            // 只针对设备
            if (csLedgerVO.getLevel() == 2) {
                List<CsDevModelRelationPO> modelIds = csDevModelRelationService.findModelByDevId(csLedgerVO.getId());
                // 检查模型是否存在，如果不存在，移除设备
                if (CollUtil.isEmpty(modelIds) || !hasValidDataSets(modelIds)) {
                    iterator.remove();
                }
            }
        }
    }

    //新增的方法用于检查数据集的有效性
    private boolean hasValidDataSets(List<CsDevModelRelationPO> modelIds) {
        for (CsDevModelRelationPO item : modelIds) {
            if (CollUtil.isEmpty(csDataSetService.findDataSetByModelId(item.getModelId()))) {
                //找到无效数据集，返回false
                return false;
            }
        }
        //所有数据集均有效，返回true
        return true;
    }


    @Override
    public List<CsLedgerVO> getDeviceTree(String type) {
        List<CsLedgerVO> engineeringList;
        List<CsLedgerVO> allList = this.baseMapper.getAll();
        /*获取用户工程，设备信息过滤*/
        List<String> roleengineer = roleEngineerDevService.getRoleengineer();
        List<String> device = roleEngineerDevService.getDevice();

        List<String> zhiLianDevice = new ArrayList<>();
        List<String> portableDevice = new ArrayList<>();
        List<String> cldDevice = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(device)) {
            List<CsEquipmentDeliveryPO> csEquipmentDeliveryPOS = csEquipmentDeliveryMapper.selectBatchIds(device);
            DictTreeVO vo1 = dictTreeFeignClient.queryByCode(DicDataEnum.DEV_CLD.getCode()).getData();
            Optional.ofNullable(vo1)
                    .map(DictTreeVO::getId)
                    .ifPresent(id -> csEquipmentDeliveryPOS.stream()
                            .filter(item -> Objects.equals(item.getDevType(), id))
                            .map(CsEquipmentDeliveryPO::getId)
                            .forEach(cldDevice::add)
                    );
            DictTreeVO vo2 = dictTreeFeignClient.queryByCode(DicDataEnum.CONNECT_DEV.getCode()).getData();
            Optional.ofNullable(vo2)
                    .map(DictTreeVO::getId)
                    .ifPresent(id -> csEquipmentDeliveryPOS.stream()
                            .filter(item -> Objects.equals(item.getDevType(), id))
                            .map(CsEquipmentDeliveryPO::getId)
                            .forEach(zhiLianDevice::add)
                    );
            DictTreeVO vo3 = dictTreeFeignClient.queryByCode(DicDataEnum.PORTABLE.getCode()).getData();
            Optional.ofNullable(vo3)
                    .map(DictTreeVO::getId)
                    .ifPresent(id -> csEquipmentDeliveryPOS.stream()
                            .filter(item -> Objects.equals(item.getDevType(), id))
                            .map(CsEquipmentDeliveryPO::getId)
                            .forEach(portableDevice::add)
                    );
        }

        engineeringList = allList.stream().filter(item -> roleengineer.contains(item.getId())).collect(Collectors.toList());
        List<CsLedgerVO> projectList = allList.stream().filter(item -> item.getLevel().equals(LineBaseEnum.PROJECT_LEVEL.getCode())).sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());

        Map<String, CsEquipmentDeliveryPO> poMap = allList.stream()
                .filter(item -> device.contains(item.getId()) && !Objects.equals(item.getPid(), "0"))
                .map(CsLedgerVO::getId)
                .distinct()
                .collect(Collectors.toMap(
                        Function.identity(),
                        csEquipmentDeliveryMapper::selectById
                ));

        //获取治理设备
        List<CsLedgerVO> deviceList = allList.stream()
                .filter(item -> zhiLianDevice.contains(item.getId()) && !Objects.equals(item.getPid(), "0"))
                .peek(item -> {
                    CsEquipmentDeliveryPO po = poMap.get(item.getId());
                    item.setComFlag(po.getRunStatus());
                    item.setNDId(po.getNdid());
                    item.setType("device");
                    item.setProcess(po.getProcess());
                    item.setDevConType(po.getDevAccessMethod());
                })
                .filter(item -> Objects.equals(poMap.get(item.getId()).getUsageStatus(), 1))
                .sorted(Comparator.comparing(CsLedgerVO::getSort))
                .collect(Collectors.toList());

        List<CsLedgerVO> engineeringList1 = new ArrayList<>();
        List<CsLedgerVO> projectList1 = new ArrayList<>();
        checkDevSetData(deviceList);
        List<String> dev = deviceList.stream().map(CsLedgerVO::getId).collect(Collectors.toList());
        List<CsLedgerVO> ledger1 = getProAndEngineer(dev);
        if (CollectionUtil.isNotEmpty(ledger1)) {
            engineeringList1 = ledger1.stream().filter(item -> item.getLevel().equals(LineBaseEnum.ENGINEERING_LEVEL.getCode())).sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());
            projectList1 = ledger1.stream().filter(item -> item.getLevel().equals(LineBaseEnum.PROJECT_LEVEL.getCode())).sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());
            projectList1.forEach(pro -> pro.setChildren(getChildren(pro, deviceList)));
            List<CsLedgerVO> finalProjectList = projectList1;
            engineeringList1.forEach(eng -> eng.setChildren(getChildren(eng, finalProjectList)));
        }

        //获取云前置设备
        List<CsLedgerVO> cldDevList = allList.stream()
                .filter(item -> cldDevice.contains(item.getId()) && !Objects.equals(item.getPid(), "0"))
                .peek(item -> {
                    CsEquipmentDeliveryPO po = poMap.get(item.getId());
                    item.setComFlag(po.getRunStatus());
                    item.setNDId(po.getNdid());
                    item.setType("device");
                    item.setProcess(po.getProcess());
                    item.setDevConType(po.getDevAccessMethod());
                })
                .filter(item -> Objects.equals(poMap.get(item.getId()).getUsageStatus(), 1))
                .sorted(Comparator.comparing(CsLedgerVO::getSort))
                .collect(Collectors.toList());
        checkDevSetData(cldDevList);
        List<CsLedgerVO> engineeringList2 = new ArrayList<>();
        List<CsLedgerVO> projectList2 = new ArrayList<>();

        List<String> dev2 = cldDevList.stream().map(CsLedgerVO::getId).collect(Collectors.toList());
        List<CsLedgerVO> ledger2 = getProAndEngineer(dev2);
        if (CollectionUtil.isNotEmpty(ledger2)) {
            engineeringList2 = ledger2.stream().filter(item -> item.getLevel().equals(LineBaseEnum.ENGINEERING_LEVEL.getCode())).sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());
            projectList2 = ledger2.stream().filter(item -> item.getLevel().equals(LineBaseEnum.PROJECT_LEVEL.getCode())).sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());
            projectList2.forEach(pro -> pro.setChildren(getChildren(pro, cldDevList)));
            List<CsLedgerVO> finalProjectList = projectList2;
            engineeringList2.forEach(eng -> eng.setChildren(getChildren(eng, finalProjectList)));
        }

        //获取便携式设备树
        CsLedgerVO portable = new CsLedgerVO();
        portable.setLevel(0);
        portable.setName(DataParam.portableDev);
        portable.setPid("0");
        portable.setId(IdUtil.simpleUUID());

        List<CsLedgerVO> ledger = allList.stream().filter(obj -> portableDevice.contains(obj.getId())).collect(Collectors.toList());
        Map<String, CsEquipmentDeliveryPO> poMap2 = ledger.stream()
                .collect(Collectors.toMap(
                        CsLedgerVO::getId,
                        csEquipmentDeliveryMapper::selectById,
                        (existing, replacement) -> existing
                ));
        List<CsLedgerVO> portables = ledger.stream()
                .peek(c -> {
                    CsEquipmentDeliveryPO po = poMap2.get(c.getId());
                    c.setPid("2");
                    c.setComFlag(po.getRunStatus());
                    c.setNDId(po.getNdid());
                    c.setType("device");
                    c.setName(po.getName());
                    c.setSort(po.getSort());
                })
                .filter(c -> poMap2.get(c.getId()).getUsageStatus() == 1)
                .collect(Collectors.toList());

        portables = portables.stream().sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());
        portable.setChildren(portables);

        CsLedgerVO government = new CsLedgerVO();
        government.setLevel(0);
        government.setName(DataParam.governmentDev);
        government.setPid("0");
        government.setId(IdUtil.simpleUUID());
        government.setChildren(engineeringList1);

        //获取云前置设备树
        CsLedgerVO cld = new CsLedgerVO();
        cld.setLevel(0);
        cld.setName(DataParam.cldDev);
        cld.setPid("0");
        cld.setId(IdUtil.simpleUUID());
        cld.setChildren(engineeringList2);

        List<CsLedgerVO> tree = new ArrayList<>();
        List<CsUserPins> list = csUserPinsService.getPinToTopList();
        if (Objects.equals(type,"engineering")) {

            Map<String, CsLedgerVO> engineeringMap = new HashMap<>();

            engineeringList1.forEach(eng -> {
                CsLedgerVO existingEng = engineeringMap.get(eng.getId());
                if (existingEng == null) {
                    engineeringMap.put(eng.getId(), eng);
                } else {
                    List<CsLedgerVO> mergedChildren = mergeProjectList(existingEng.getChildren(), eng.getChildren());
                    existingEng.setChildren(mergedChildren);
                }
            });

            engineeringList2.forEach(eng -> {
                CsLedgerVO existingEng = engineeringMap.get(eng.getId());
                if (existingEng == null) {
                    engineeringMap.put(eng.getId(), eng);
                } else {
                    List<CsLedgerVO> mergedChildren = mergeProjectList(existingEng.getChildren(), eng.getChildren());
                    existingEng.setChildren(mergedChildren);
                }
            });

            tree.addAll(new ArrayList<>(engineeringMap.values()));

            if (CollUtil.isNotEmpty(portables)) {
                CsLedgerVO portable1 = new CsLedgerVO();
                portable1.setLevel(0);
                portable1.setName("便携式工程");
                portable1.setPid("0");
                portable1.setId("1");

                CsLedgerVO portable2 = new CsLedgerVO();
                portable2.setLevel(1);
                portable2.setName("便携式项目");
                portable2.setPid("1");
                portable2.setId("2");
                portable2.setChildren(portables);

                List<CsLedgerVO> portable2List = new ArrayList<>();
                portable2List.add(portable2);
                portable1.setChildren(portable2List);
                tree.add(portable1);
            }

            if (CollectionUtil.isNotEmpty(list)) {
                csUserPinsService.channelTree(list, tree, 4);
            }
        } else {
            //按设备类型统计
            if (CollUtil.isNotEmpty(portables)) {
                tree.add(portable);
            }
            if (CollUtil.isNotEmpty(deviceList)) {
                tree.add(government);
            }
            if (CollUtil.isNotEmpty(cldDevList)) {
                tree.add(cld);
            }
        }
        if (CollectionUtil.isNotEmpty(list)) {
            csUserPinsService.channelTree(list, tree, 5);
        }
        return tree;
    }

    @Override
    public CsLedger addLedgerTree(CsLedgerParam csLedgerParam) {
        CsLedger fatherCsLedger = this.lambdaQuery().eq(CsLedger::getId, csLedgerParam.getPid()).one();
        CsLedger csLedger = new CsLedger();
        BeanUtils.copyProperties(csLedgerParam, csLedger);
        csLedger.setState(1);
        if (Objects.equals(csLedgerParam.getPid(), "9999999")) {
            csLedger.setPid("0");
            csLedger.setPids("0");
        } else {
            csLedger.setPids(fatherCsLedger.getPids() + "," + csLedgerParam.getPid());
        }
        this.save(csLedger);
        return csLedger;
    }

    @Override
    public void deleteLedgerTree(String id) {
        CsLedger csLedger = this.lambdaQuery().eq(CsLedger::getId, id).one();
        csLedger.setState(0);
        this.updateById(csLedger);
    }

    @Override
    public void updateLedgerTree(CsLedgerParam.Update csLedgerParam) {
        CsLedger csLedger = new CsLedger();
        BeanUtil.copyProperties(csLedgerParam, csLedger);
        this.updateById(csLedger);
    }

    @Override
    public String findDevByLineId(String lineId) {
        String deviceId = null;
        CsLedger csLedger = this.lambdaQuery().eq(CsLedger::getId, lineId).eq(CsLedger::getState, 1).one();
        if (!Objects.isNull(csLedger)) {
            deviceId = csLedger.getPid();
        }
        return deviceId;
    }

    @Override
    public CsLedger findDataById(String id) {
        return this.lambdaQuery().eq(CsLedger::getId, id).eq(CsLedger::getState, 1).one();
    }

    @Override
    public List<CsLedgerVO> getProjectTree() {
        List<CsLedgerVO> engineeringList = new ArrayList<>();
        List<CsLedgerVO> allList = this.baseMapper.getAll();
        List<String> roleengineer = roleEngineerDevService.getRoleengineer();
        engineeringList = allList.stream().filter(item -> roleengineer.contains(item.getId())).collect(Collectors.toList());
        List<CsLedgerVO> projectList = allList.stream().filter(item -> item.getLevel().equals(LineBaseEnum.PROJECT_LEVEL.getCode())).sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());
        QueryWrapper<AppTopologyDiagramPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", "1");
        List<AppTopologyDiagramPO> appTopologyDiagramPOS = appTopologyDiagramMapper.selectList(queryWrapper);
        projectList.forEach(temp -> {
            AppProjectPO appProjectPO = appProjectMapper.selectById(temp.getId());
            temp.setArea(appProjectPO.getArea());
            temp.setRemark(appProjectPO.getDescription());
            List<CsLedgerVO> collect = appTopologyDiagramPOS.stream().filter(appTopologyDiagramPO -> Objects.equals(appTopologyDiagramPO.getProjectId(), temp.getId()))
                    .map(po -> {
                        CsLedgerVO vo = new CsLedgerVO();
                        vo.setId(po.getId());
                        vo.setPid(po.getProjectId());
                        vo.setName(po.getName());
                        vo.setPath(po.getFilePath());
                        return vo;
                    }).collect(Collectors.toList());
            temp.setChildren(collect);
        });
        engineeringList.forEach(eng -> {
                    CsEngineeringPO csEngineeringPO = csEngineeringMapper.selectById(eng.getId());
                    eng.setArea(this.getAreaById(csEngineeringPO.getProvince()) + this.getAreaById(csEngineeringPO.getCity()));
                    eng.setProvinceId(csEngineeringPO.getProvince());
                    eng.setCityId(csEngineeringPO.getCity());
                    eng.setRemark(csEngineeringPO.getDescription());
                    eng.setChildren(getChildren(eng, projectList));
                }
        );

        return engineeringList;
    }

    @Override
    public List<CsLedger> queryLine(LineParamDTO lineParamdto) {
        return this.getBaseMapper().queryLine(lineParamdto);
    }

    @Override
    public DevDetailDTO queryDevDetail(String devId) {
        DevDetailDTO device = new DevDetailDTO();
        CsLedger dev = this.findDataById(devId);
        //获取设备mac
        CsEquipmentDeliveryPO po = csEquipmentDeliveryMapper.selectById(devId);

        //如果是便携式设备，pid为0,项目，工程都设置为/
        if (Objects.equals(dev.getPid(), "0")) {
            device.setEquipmentName(dev.getName());
            device.setEquipmentId(devId);
            device.setDevMac(po.getMac());
            device.setNDid(po.getNdid());
            device.setProjectId("/");
            device.setProjectName("/");
            device.setEngineeringid("/");
            device.setEngineeringName("/");
        } else {
            device.setEquipmentName(dev.getName());
            device.setEquipmentId(devId);
            device.setDevMac(po.getMac());
            device.setNDid(po.getNdid());
            CsLedger project = this.findDataById(dev.getPid());
            if (ObjectUtil.isNotNull(project)) {
                device.setProjectId(project.getId());
                device.setProjectName(project.getName());
                CsLedger engineer = this.findDataById(project.getPid());
                if (ObjectUtil.isNotNull(engineer)) {
                    device.setEngineeringid(engineer.getId());
                    device.setEngineeringName(engineer.getName());
                }
            }
        }
        return device;
    }
    @Override
    public List<CsLedgerVO> getztProjectTree() {
        List<CsLedgerVO> engineeringList;
        List<CsLedgerVO> allList = this.baseMapper.getAll();
        /*获取用户工程，设备信息过滤*/
        List<String> roleengineer = roleEngineerDevService.getRoleengineer();
        List<String> device = roleEngineerDevService.getDevice();

        List<String> zhiLianDevice = new ArrayList<>();
        List<String> cldDevice = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(device)) {
            List<CsEquipmentDeliveryPO> csEquipmentDeliveryPOS = csEquipmentDeliveryMapper.selectBatchIds(device);
            DictTreeVO vo1 = dictTreeFeignClient.queryByCode(DicDataEnum.DEV_CLD.getCode()).getData();
            Optional.ofNullable(vo1)
                    .map(DictTreeVO::getId)
                    .ifPresent(id -> csEquipmentDeliveryPOS.stream()
                            .filter(item -> Objects.equals(item.getDevType(), id))
                            .map(CsEquipmentDeliveryPO::getId)
                            .forEach(cldDevice::add)
                    );
            DictTreeVO vo2 = dictTreeFeignClient.queryByCode(DicDataEnum.CONNECT_DEV.getCode()).getData();
            Optional.ofNullable(vo2)
                    .map(DictTreeVO::getId)
                    .ifPresent(id -> csEquipmentDeliveryPOS.stream()
                            .filter(item -> Objects.equals(item.getDevType(), id))
                            .map(CsEquipmentDeliveryPO::getId)
                            .forEach(zhiLianDevice::add)
                    );
        }

        engineeringList = allList.stream().filter(item -> roleengineer.contains(item.getId())).collect(Collectors.toList());
        List<CsLedgerVO> projectList = allList.stream().filter(item -> item.getLevel().equals(LineBaseEnum.PROJECT_LEVEL.getCode())).sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());

        Map<String, CsEquipmentDeliveryPO> poMap = allList.stream()
                .filter(item -> device.contains(item.getId()) && !Objects.equals(item.getPid(), "0"))
                .map(CsLedgerVO::getId)
                .distinct()
                .collect(Collectors.toMap(
                        Function.identity(),
                        csEquipmentDeliveryMapper::selectById
                ));

        //获取治理设备
        List<CsLedgerVO> deviceList = allList.stream()
                .filter(item -> zhiLianDevice.contains(item.getId()) && !Objects.equals(item.getPid(), "0"))
                .peek(item -> {
                    CsEquipmentDeliveryPO po = poMap.get(item.getId());
                    item.setComFlag(po.getRunStatus());
                    item.setNDId(po.getNdid());
                    item.setType("device");
                    item.setProcess(po.getProcess());
                })
                .filter(item -> Objects.equals(poMap.get(item.getId()).getUsageStatus(), 1))
                .sorted(Comparator.comparing(CsLedgerVO::getSort))
                .collect(Collectors.toList());

        List<CsLedgerVO> engineeringList1 = new ArrayList<>();
        List<CsLedgerVO> projectList1 = new ArrayList<>();
        checkDevSetData(deviceList);
        List<String> dev = deviceList.stream().map(CsLedgerVO::getId).collect(Collectors.toList());
        List<CsLedgerVO> ledger1 = getProAndEngineer(dev);
        if (CollectionUtil.isNotEmpty(ledger1)) {
            engineeringList1 = ledger1.stream().filter(item -> item.getLevel().equals(LineBaseEnum.ENGINEERING_LEVEL.getCode())).sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());
            projectList1 = ledger1.stream().filter(item -> item.getLevel().equals(LineBaseEnum.PROJECT_LEVEL.getCode())).sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());
            projectList1.forEach(pro -> pro.setChildren(getChildren(pro, deviceList)));
            List<CsLedgerVO> finalProjectList = projectList1;
            engineeringList1.forEach(eng -> eng.setChildren(getChildren(eng, finalProjectList)));
        }

        //获取云前置设备
        List<CsLedgerVO> cldDevList = allList.stream()
                .filter(item -> cldDevice.contains(item.getId()) && !Objects.equals(item.getPid(), "0"))
                .peek(item -> {
                    CsEquipmentDeliveryPO po = poMap.get(item.getId());
                    item.setComFlag(po.getRunStatus());
                    item.setNDId(po.getNdid());
                    item.setType("device");
                    item.setProcess(po.getProcess());
                })
                .filter(item -> Objects.equals(poMap.get(item.getId()).getUsageStatus(), 1))
                .sorted(Comparator.comparing(CsLedgerVO::getSort))
                .collect(Collectors.toList());
        checkDevSetData(cldDevList);
        List<CsLedgerVO> engineeringList2 = new ArrayList<>();
        List<CsLedgerVO> projectList2 = new ArrayList<>();

        List<String> dev2 = cldDevList.stream().map(CsLedgerVO::getId).collect(Collectors.toList());
        List<CsLedgerVO> ledger2 = getProAndEngineer(dev2);
        if (CollectionUtil.isNotEmpty(ledger2)) {
            engineeringList2 = ledger2.stream().filter(item -> item.getLevel().equals(LineBaseEnum.ENGINEERING_LEVEL.getCode())).sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());
            projectList2 = ledger2.stream().filter(item -> item.getLevel().equals(LineBaseEnum.PROJECT_LEVEL.getCode())).sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());
            projectList2.forEach(pro -> pro.setChildren(getChildren(pro, cldDevList)));
            List<CsLedgerVO> finalProjectList = projectList2;
            engineeringList2.forEach(eng -> eng.setChildren(getChildren(eng, finalProjectList)));
        }

        //获取便携式设备树
        CsLedgerVO portable = new CsLedgerVO();
        portable.setLevel(0);
        portable.setName(DataParam.portableDev);
        portable.setPid("0");
        portable.setId(IdUtil.simpleUUID());

        List<CsLedgerVO> ledger;
        String role = RequestUtil.getUserRole();
        List<String> roles = JSONArray.parseArray(role, String.class);
        if(roles.contains(AppRoleEnum.ROOT.getCode()) || roles.contains(AppRoleEnum.OPERATION_MANAGER.getCode()) || roles.contains(AppRoleEnum.REGULAR_USER.getCode())){
            ledger = allList.stream()
                    .filter(item -> Objects.equals(item.getLevel(), 2) && Objects.equals(item.getPid(), "0"))
                    .collect(Collectors.toList());
        } else {
            LambdaQueryWrapper<CsDeviceUserPO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(CsDeviceUserPO::getPrimaryUserId, RequestUtil.getUserIndex());
            List<CsDeviceUserPO> list1 = csDeviceUserPOMapper.selectList(queryWrapper);
            List<String> result = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(list1)) {
                result = list1.stream().map(CsDeviceUserPO::getDeviceId).collect(Collectors.toList());
            }
            //针对未启用的装置判断
            List<String> finalResult = result;
            ledger = allList.stream()
                    .filter(item -> Objects.equals(item.getLevel(), 2) && Objects.equals(item.getPid(), "0") && finalResult.contains(item.getId()))
                    .collect(Collectors.toList());
        }

        Map<String, CsEquipmentDeliveryPO> poMap2 = ledger.stream()
                .collect(Collectors.toMap(
                        CsLedgerVO::getId,
                        csEquipmentDeliveryMapper::selectById,
                        (existing, replacement) -> existing
                ));
        List<CsLedgerVO> portables = ledger.stream()
                .peek(c -> {
                    CsEquipmentDeliveryPO po = poMap2.get(c.getId());
                    c.setPid(portable.getId());
                    c.setComFlag(po.getRunStatus());
                    c.setNDId(po.getNdid());
                    c.setType("device");
                    c.setName(po.getName());
                    c.setSort(po.getSort());
                })
                .filter(c -> poMap2.get(c.getId()).getUsageStatus() == 1)
                .collect(Collectors.toList());

        portables = portables.stream().sorted(Comparator.comparing(CsLedgerVO::getSort)).collect(Collectors.toList());
        portable.setChildren(portables);

        CsLedgerVO government = new CsLedgerVO();
        government.setLevel(0);
        government.setName(DataParam.governmentDev);
        government.setPid("0");
        government.setId(IdUtil.simpleUUID());
        government.setChildren(engineeringList1);

        //获取云前置设备树
        CsLedgerVO cld = new CsLedgerVO();
        cld.setLevel(0);
        cld.setName(DataParam.cldDev);
        cld.setPid("0");
        cld.setId(IdUtil.simpleUUID());
        cld.setChildren(engineeringList2);

        List<CsLedgerVO> tree = new ArrayList<>();
        if (CollUtil.isNotEmpty(portables)) {
            CsLedgerVO vo1 = new CsLedgerVO();
            vo1.setLevel(0);
            vo1.setName(DataParam.PORTABLE_SYSTEM);
            vo1.setPid("0");
            vo1.setId(IdUtil.simpleUUID());

            CsLedgerVO vo2 = new CsLedgerVO();
            vo2.setLevel(1);
            vo2.setName(DataParam.WIRELESS_PROJECT);
            vo2.setPid("0");
            vo2.setId(DataParam.WIRELESS_PROJECT_ID);
            vo2.setChildren(portables);
            vo1.setChildren(Collections.singletonList(vo2));
            tree.add(vo1);
        }
        if (CollUtil.isNotEmpty(deviceList)) {
            tree.add(government);
        }
        if (CollUtil.isNotEmpty(cldDevList)) {
            tree.add(cld);
        }
        return tree;
    }


//    @Override
//    public List<CsLedgerVO> objTree() {
//        List<CsLedgerVO> result = new ArrayList<>();
//        String userId = RequestUtil.getUserIndex();
//        UserVO userVO = userFeignClient.getUserById(userId).getData();
//        List<String> devIds;
//        if (userVO.getType().equals(UserType.SUPER_ADMINISTRATOR) || userVO.getType().equals(UserType.ADMINISTRATOR)) {
//            devIds = csEquipmentDeliveryMapper.selectList(null).stream().map(CsEquipmentDeliveryPO::getId).collect(Collectors.toList());
//        } else {
//            LambdaQueryWrapper<CsDeviceUserPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//            lambdaQueryWrapper.select(CsDeviceUserPO::getDeviceId)
//                    .and(w -> w.eq(CsDeviceUserPO::getPrimaryUserId, userId).or().eq(CsDeviceUserPO::getSubUserId, userId))
//                    .eq(CsDeviceUserPO::getStatus, DataStateEnum.ENABLE.getCode());
//            List<CsDeviceUserPO> devList = csDeviceUserPOMapper.selectList(lambdaQueryWrapper);
//            devIds = devList.stream().map(CsDeviceUserPO::getDeviceId).distinct().collect(Collectors.toList());
//        }
//        if (CollUtil.isEmpty(devIds)) {
//            return result;
//        }
//        List<CsLinePO> poList = csLinePOService.lambdaQuery().in(CsLinePO::getDeviceId, devIds)
//                .eq(CsLinePO::getStatus, DataStateEnum.ENABLE.getCode()).ne(CsLinePO::getMonitorUser,"").isNotNull(CsLinePO::getMonitorUser).list();
//        if (CollUtil.isEmpty(poList)) {
//            return result;
//        }
//        List<String> objIds = poList.stream().map(CsLinePO::getMonitorUser).distinct().collect(Collectors.toList());
//        List<String> lineIds = poList.stream().map(CsLinePO::getLineId).distinct().collect(Collectors.toList());
//
//        List<PqSensitiveUser> pqSensitiveUserList = pqSensitiveUserFeignClient.getListByIds(objIds).getData();
//        if (CollUtil.isEmpty(pqSensitiveUserList)) {
//            return result;
//        }
//        Map<String,String> objMap = pqSensitiveUserList.stream().collect(Collectors.toMap(PqSensitiveUser::getId, PqSensitiveUser::getName));
//
//        List<CsLedger> csLineList = this.baseMapper.selectList(new LambdaQueryWrapper<CsLedger>().in(CsLedger::getId, lineIds));
//        Map<String,List<String>> lineMap = csLineList.stream().collect(Collectors.groupingBy(it->it.getPids().split(StrUtil.COMMA)[LineBaseEnum.PROJECT_LEVEL.getCode()+1],Collectors.mapping(CsLedger::getId,Collectors.toList())));
//
//        List<String> projectIds = csLineList.stream().map(it -> it.getPids().split(StrUtil.COMMA)[LineBaseEnum.PROJECT_LEVEL.getCode()+1]).distinct().collect(Collectors.toList());
//        List<CsLedger> projectList = this.baseMapper.selectList(new LambdaQueryWrapper<CsLedger>().in(CsLedger::getId, projectIds));
//
//       List<CsLedgerVO> realProjectList = new ArrayList<>();
//        projectList.forEach(pro->{
//            CsLedgerVO csLedgerVO = new CsLedgerVO();
//            csLedgerVO.setId(pro.getId());
//            csLedgerVO.setPid(pro.getPid());
//            csLedgerVO.setLevel(pro.getLevel());
//            csLedgerVO.setName(pro.getName());
//
//            List<CsLedgerVO> temObjList = new ArrayList<>();
//            if(lineMap.containsKey(pro.getId())){
//                List<String> ids = lineMap.get(pro.getId());
//                List<String> objTemIds = poList.stream().filter(it->ids.contains(it.getLineId())).map(CsLinePO::getMonitorUser).distinct().collect(Collectors.toList());
//                if(CollUtil.isNotEmpty(objTemIds)){
//                    objTemIds.forEach(it->{
//                        CsLedgerVO inner = new CsLedgerVO();
//                        inner.setName(objMap.getOrDefault(it,"未知异常用户"));
//                        inner.setId(it);
//                        inner.setLevel(2);
//                        temObjList.add(inner);
//                    });
//                }
//            }
//            csLedgerVO.setChildren(temObjList);
//            realProjectList.add(csLedgerVO);
//        });
//
//        List<String> gcIds = projectList.stream().map(CsLedger::getPid).collect(Collectors.toList());
//        List<CsLedger> gcList = this.baseMapper.selectList(new LambdaQueryWrapper<CsLedger>().in(CsLedger::getId, gcIds));
//
//        List<CsLedgerVO> realGcList = new ArrayList<>();
//        gcList.forEach(gc->{
//            CsLedgerVO csLedgerVO = new CsLedgerVO();
//            csLedgerVO.setId(gc.getId());
//            csLedgerVO.setPid(gc.getPid());
//            csLedgerVO.setLevel(gc.getLevel());
//            csLedgerVO.setName(gc.getName());
//
//            List<CsLedgerVO> proList = realProjectList.stream().filter(it->gc.getId().equals(it.getPid())).collect(Collectors.toList());
//            csLedgerVO.setChildren(proList);
//            realGcList.add(csLedgerVO);
//        });
//        return realGcList;
//    }

    @Override
    public List<CsLedgerVO> getProAndEngineer(List<String> id) {
        List<CsLedgerVO> result = new ArrayList<>();
        List<CsLedgerVO> allList = this.baseMapper.getAll();
        Set<String> idSet = new HashSet<>(id);
        if (CollectionUtil.isNotEmpty(id)) {
            id.forEach(item -> {
                allList.forEach(item2 -> {
                    if (Objects.equals(item2.getId(), item)) {
                        idSet.addAll(Arrays.asList(item2.getPids().split(",")));
                    }
                });
            });
        }
        if (CollectionUtil.isNotEmpty(idSet)) {
            idSet.forEach(item -> {
                allList.forEach(item2 -> {
                    if (Objects.equals(item2.getId(), item)) {
                        result.add(item2);
                    }
                });
            });
        }
        return result;
    }

    @Override
    public CsLedgerVO cldTree() {
        List<CsLedgerVO> allList = this.baseMapper.getAll();
        if (CollectionUtil.isEmpty(allList)) {
            return buildTreeRootNode(new ArrayList<>());
        }

        Map<Integer, List<CsLedgerVO>> levelMap = allList.stream()
                .sorted(Comparator.comparing(CsLedgerVO::getSort))
                .collect(Collectors.groupingBy(CsLedgerVO::getLevel));

        List<CsLedgerVO> engineeringList = levelMap.getOrDefault(LineBaseEnum.ENGINEERING_LEVEL.getCode(), new ArrayList<>());
        List<CsLedgerVO> projectList = levelMap.getOrDefault(LineBaseEnum.PROJECT_LEVEL.getCode(), new ArrayList<>());
        List<CsLedgerVO> deviceList = levelMap.getOrDefault(LineBaseEnum.DEVICE_LEVEL.getCode(), new ArrayList<>());
        List<CsLedgerVO> lineList = levelMap.getOrDefault(LineBaseEnum.LINE_LEVEL.getCode(), new ArrayList<>());

        if (CollectionUtil.isEmpty(deviceList)) {
            Map<String, List<CsLedgerVO>> projectByPidMap = projectList.stream()
                    .collect(Collectors.groupingBy(CsLedgerVO::getPid));
            engineeringList.forEach(eng -> eng.setChildren(projectByPidMap.getOrDefault(eng.getId(), new ArrayList<>())));
            return buildTreeRootNode(engineeringList);
        }

        // 批量查询设备交付信息
        List<String> devIds = deviceList.stream().map(CsLedgerVO::getId).collect(Collectors.toList());
        List<CsEquipmentDeliveryPO> devs = csEquipmentDeliveryMapper.selectBatchIds(devIds);
        Map<String, CsEquipmentDeliveryPO> devsMap = devs.stream()
                .collect(Collectors.toMap(CsEquipmentDeliveryPO::getId, Function.identity()));
        Set<String> cldDevIds = devs.stream().map(CsEquipmentDeliveryPO::getId).collect(Collectors.toSet());

        // 填充设备状态信息
        deviceList.forEach(device -> {
            CsEquipmentDeliveryPO dev = devsMap.get(device.getId());
            if (dev != null) {
                device.setComFlag(dev.getRunStatus());
                device.setDevConType(dev.getDevAccessMethod());
            }
        });

        // 填充监测点状态信息
        Map<String, String> lineDevMap = lineList.stream()
                .collect(Collectors.toMap(CsLedgerVO::getId, CsLedgerVO::getPid));
        lineList.forEach(line -> {
            String devId = lineDevMap.get(line.getId());
            if (devId != null) {
                CsEquipmentDeliveryPO dev = devsMap.get(devId);
                if (dev != null) {
                    line.setComFlag(dev.getRunStatus());
                }
            }
        });

        // 预构建pid映射
        Map<String, List<CsLedgerVO>> projectByEngineeringMap = projectList.stream()
                .collect(Collectors.groupingBy(CsLedgerVO::getPid));
        Map<String, List<CsLedgerVO>> deviceByProjectMap = deviceList.stream()
                .collect(Collectors.groupingBy(CsLedgerVO::getPid));
        Map<String, List<CsLedgerVO>> lineByDeviceMap = lineList.stream()
                .collect(Collectors.groupingBy(CsLedgerVO::getPid));

        // 逐层构建树：设备 -> 监测点
        deviceList.forEach(device -> {
            if (cldDevIds.contains(device.getId())) {
                device.setChildren(lineByDeviceMap.getOrDefault(device.getId(), new ArrayList<>()));
            }
        });

        // 项目 -> 设备（仅包含有交付记录的设备）
        projectList.forEach(project -> {
            List<CsLedgerVO> projectDevices = deviceByProjectMap.getOrDefault(project.getId(), new ArrayList<>());
            if (CollectionUtil.isNotEmpty(projectDevices)) {
                List<CsLedgerVO> validDevices = projectDevices.stream()
                        .filter(device -> cldDevIds.contains(device.getId()))
                        .collect(Collectors.toList());
                project.setChildren(validDevices);
            }
        });

        // 工程 -> 项目
        engineeringList.forEach(eng ->
                eng.setChildren(projectByEngineeringMap.getOrDefault(eng.getId(), new ArrayList<>()))
        );

        return buildTreeRootNode(engineeringList);
    }

    private CsLedgerVO buildTreeRootNode(List<CsLedgerVO> children) {
        CsLedgerVO root = new CsLedgerVO();
        root.setLevel(-1);
        root.setName("台账树");
        root.setPid("0");
        root.setId(IdUtil.simpleUUID());
        root.setChildren(children);
        return root;
    }

    @Override
    public List<DevDetailDTO> getInfoByIds(List<String> list) {
        List<DevDetailDTO> details = new ArrayList<>();
        List<CsLedger> ledgers = this.listByIds(list);
        Set<String> enginingeringIds = new HashSet<>();
        ledgers.forEach(item -> {
            DevDetailDTO device = new DevDetailDTO();
            if (Objects.equals(item.getPid(), "0")) {
                device.setEquipmentName(item.getName());
                device.setEquipmentId(item.getId());
                device.setProjectId("/");
                device.setProjectName("/");
                device.setEngineeringid("/");
                device.setEngineeringName("/");
                details.add(device);
            } else {
                enginingeringIds.add(item.getPids().split(",")[1]);
            }
        });
        if (CollectionUtil.isNotEmpty(enginingeringIds)) {
            List<CsLedger> engineer = this.listByIds(enginingeringIds);
            engineer.forEach(item -> {
                List<String> devNames = new ArrayList<>();
                List<String> devIds = new ArrayList<>();
                DevDetailDTO detail = new DevDetailDTO();
                detail.setEngineeringid(item.getId());
                detail.setEngineeringName(item.getName());
                ledgers.forEach(item2->{
                    if (item2.getPids().contains(item.getId())) {
                        devIds.add(item2.getId());
                        devNames.add(item2.getName());
                    }
                });
                detail.setEquipmentId(String.join(",", devIds));
                detail.setEquipmentName(String.join(",", devNames));
                details.add(detail);
            });
        }
        return details;
    }

    @Override
    public List<DevDetailDTO> getDevInfoByEngineerIds(List<String> list) {
        // 参数校验，确保 list 不为空
        if (CollUtil.isEmpty(list)) {
            return new ArrayList<>();
        }

        List<DevDetailDTO> details = new ArrayList<>();

        // 工程
        LambdaQueryWrapper<CsLedger> queryWrapper0 = new LambdaQueryWrapper<>();
        queryWrapper0.in(CsLedger::getId, list);
        List<CsLedger> engineering = this.list(queryWrapper0);
        if (CollUtil.isEmpty(engineering)) {
            return details;
        }
        Map<String, CsLedger> engineeringMap = engineering.stream().collect(Collectors.toMap(CsLedger::getId, item -> item));

        // 项目
        LambdaQueryWrapper<CsLedger> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(CsLedger::getPid, list);
        List<CsLedger> project = this.list(queryWrapper);
        if (CollUtil.isEmpty(project)) {
            return details;
        }
        Map<String, CsLedger> projectMap = project.stream().collect(Collectors.toMap(CsLedger::getId, item -> item));

        // 设备
        List<String> projectIds = project.stream().map(CsLedger::getId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(projectIds)) {
            LambdaQueryWrapper<CsLedger> queryWrapper2 = new LambdaQueryWrapper<>();
            queryWrapper2.in(CsLedger::getPid, projectIds);
            List<CsLedger> dev = this.list(queryWrapper2);

            if (CollUtil.isNotEmpty(dev)) {
                List<String> devIds = dev.stream().map(CsLedger::getId).collect(Collectors.toList());

                //监测点
                LambdaQueryWrapper<CsLedger> queryWrapper3 = new LambdaQueryWrapper<>();
                queryWrapper3.in(CsLedger::getPid, devIds);
                List<CsLedger> line = this.list(queryWrapper3);
                Map<String,List<CsLedger>> lineMap = line.stream().collect(Collectors.groupingBy(CsLedger::getPid));


                List<CsEquipmentDeliveryPO> devs = csEquipmentDeliveryMapper.selectBatchIds(devIds);
                Map<String, CsEquipmentDeliveryPO> devsMap = devs.stream().collect(Collectors.toMap(CsEquipmentDeliveryPO::getId, item -> item));

                dev.forEach(item -> {
                    DevDetailDTO detail = new DevDetailDTO();
                    //监测点
                    List<CsLedger> lines = lineMap.get(item.getId());
                    if (CollUtil.isNotEmpty(lines)) {
                        detail.setLineList(lines.stream().map(CsLedger::getId).collect(Collectors.toList()));
                    }

                    detail.setEquipmentName(item.getName());
                    detail.setEquipmentId(item.getId());

                    CsLedger csLedger = projectMap.get(item.getPid());
                    if (csLedger != null) {
                        detail.setProjectId(csLedger.getId());
                        detail.setProjectName(csLedger.getName());

                        CsLedger csLedger1 = engineeringMap.get(csLedger.getPid());
                        if (csLedger1 != null) {
                            detail.setEngineeringid(csLedger1.getId());
                            detail.setEngineeringName(csLedger1.getName());
                        }
                    }

                    CsEquipmentDeliveryPO devInfo = devsMap.get(item.getId());
                    if (devInfo != null) {
                        detail.setRunStatus(devInfo.getRunStatus());
                    }

                    details.add(detail);
                });
            }
        }
        return details;
    }


    @Override
    public List<DevDetailDTO> getEngineeringHaveDevs(List<String> list) {
        List<DevDetailDTO> result = new ArrayList<>();
        list.forEach(item -> {
            LambdaQueryWrapper<CsLedger> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(CsLedger::getPid, item);
            List<CsLedger> project = this.list(queryWrapper);
            if (CollectionUtil.isNotEmpty(project)) {
                //项目id
                List<String> projectIds = project.stream().map(CsLedger::getId).collect(Collectors.toList());
                LambdaQueryWrapper<CsLedger> queryWrapper2 = new LambdaQueryWrapper<>();
                queryWrapper2.in(CsLedger::getPid, projectIds);
                List<CsLedger> dev = this.list(queryWrapper2);
                if (CollectionUtil.isNotEmpty(dev)) {
                    DevDetailDTO dto = new DevDetailDTO();
                    dto.setEngineeringid(item);
                    result.add(dto);
                }
            }
        });
        return result;
    }

    @Override
    public List<CsLedger> queryByPid(String pid) {
        return this.list(new LambdaQueryWrapper<CsLedger>()
                .eq(CsLedger::getPid, pid)
                .eq(CsLedger::getState, 1));
    }

    /**
     * 获取子节点
     */
    public List<CsLedgerVO> getChildren(CsLedgerVO item, List<CsLedgerVO> all) {
        // 筛选所有具有特定父ID的子项
        List<CsLedgerVO> children = all.stream()
                .filter(allItem -> allItem.getPid().equals(item.getId()))
                .collect(Collectors.toList());
        // 如果父项有comFlag，则更新所有子项的comFlag
        if (!Objects.isNull(item.getComFlag())) {
            children.forEach(child -> child.setComFlag(item.getComFlag()));
        }
        return children;
    }

    public String getAreaById(String id) {
        String areaName = redisUtil.getStringByKey(id);
        areaName = Optional.ofNullable(areaName).orElseGet(() -> {
            Area data = areaFeignClient.selectIdArea(id).getData();
            redisUtil.saveByKey(id, data.getName());
            return data.getName();
        });
        return areaName;
    }
}
