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.StrUtil;
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.common.pojo.enums.common.DataStateEnum;
import com.njcn.csdevice.constant.DataParam;
import com.njcn.csdevice.controller.project.EngineeringController;
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.PqSensitiveUserFeignClient;
import com.njcn.csharmonic.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.api.UserFeignClient;
import com.njcn.user.enums.AppRoleEnum;
import com.njcn.user.pojo.constant.UserType;
import com.njcn.user.pojo.vo.UserVO;
import com.njcn.web.utils.RequestUtil;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

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 PqSensitiveUserFeignClient pqSensitiveUserFeignClient;
    private final UserFeignClient userFeignClient;


    @Override
    public List<CsLedgerVO> getLedgerTree() {
        List<CsLedgerVO> list = new ArrayList<>();
        List<CsLedgerVO> engineeringList = getLineTree();
        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() {
        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> 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());
                })
                .filter(item -> Objects.equals(poMap.get(item.getId()).getUsageStatus(), 1))
                .sorted(Comparator.comparing(CsLedgerVO::getSort))
                .collect(Collectors.toList());

        List<CsLedgerVO> finalLineList = allList.stream()
                .filter(item -> item.getLevel().equals(LineBaseEnum.LINE_LEVEL.getCode()))
                .sorted(Comparator.comparing(CsLedgerVO::getSort))
                .peek(
                        item -> {
                            item.setType("line");
                            String index = item.getId().substring(item.getId().length() - 1);
                            if (Objects.equals(index, "0")) {
                                item.setLineType(0);
                            } else {
                                item.setLineType(1);
                            }
                            LambdaQueryWrapper<CsLinePO> queryWrapper = new LambdaQueryWrapper<>();
                            queryWrapper.eq(CsLinePO::getLineId, item.getId()).eq(CsLinePO::getStatus, 1);
                            CsLinePO po = csLinePOService.getOne(queryWrapper);
                            item.setConType(po.getConType());
                        }
                )
                .collect(Collectors.toList());

        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;
        String role = RequestUtil.getUserRole();
        List<String> roles = JSONArray.parseArray(role, String.class);
        if (roles.contains(AppRoleEnum.ROOT.getCode()) || roles.contains(AppRoleEnum.OPERATION_MANAGER.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());
        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<>();
        if (CollUtil.isNotEmpty(portables)) {
            tree.add(portable);
        }
        if (CollUtil.isNotEmpty(deviceList)) {
            tree.add(government);
        }
        if (CollUtil.isNotEmpty(cldDeviceList)) {
            tree.add(cld);
        }
        return tree;
    }

    //剔除未接入的设备(根据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() {
        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())) {
            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)) {
            tree.add(portable);
        }
        if (CollUtil.isNotEmpty(deviceList)) {
            tree.add(government);
        }
        if (CollUtil.isNotEmpty(cldDevList)) {
            tree.add(cld);
        }
        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);
        //如果是便携式设备，pid为0,项目，工程都设置为/
        if (Objects.equals(dev.getPid(), "0")) {
            device.setEquipmentName(dev.getName());
            device.setEquipmentId(devId);
            device.setProjectId("/");
            device.setProjectName("/");
            device.setEngineeringid("/");
            device.setEngineeringName("/");
        } else {
            device.setEquipmentName(dev.getName());
            device.setEquipmentId(devId);
            CsLedger project = this.findDataById(dev.getPid());
            device.setProjectId(project.getId());
            device.setProjectName(project.getName());
            CsLedger engineer = this.findDataById(project.getPid());
            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();
        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());

        List<CsLedgerVO> deviceList = allList.stream().filter(item -> device.contains(item.getId()) && !Objects.equals(item.getPid(), "0")).
                peek(
                        temp -> {
                            CsEquipmentDeliveryPO po = csEquipmentDeliveryMapper.selectById(temp.getId());
                            temp.setComFlag(po.getRunStatus());
                            temp.setNDId(po.getNdid());
                            temp.setType("device");
                        }
                ).
                sorted(Comparator.comparing(CsLedgerVO::getSort))
                .collect(Collectors.toList());
        checkDevSetData(deviceList);
        projectList.forEach(pro -> pro.setChildren(getChildren(pro, deviceList)));
        engineeringList.forEach(eng -> eng.setChildren(getChildren(eng, projectList)));

        //获取便携式项目数
        CsLedgerVO portable = new CsLedgerVO();
        portable.setLevel(0);
        portable.setName(DataParam.PORTABLE_SYSTEM);
        portable.setPid("0");
        portable.setId(IdUtil.simpleUUID());

        CsLedgerVO project = new CsLedgerVO();
        project.setLevel(1);
        project.setName(DataParam.WIRELESS_PROJECT);
        project.setPid("0");
        project.setId(DataParam.WIRELESS_PROJECT_ID);

        List<CsLedgerVO> portables = allList.stream().filter(item -> Objects.equals(item.getLevel(), 2) && Objects.equals(item.getPid(), "0")).collect(Collectors.toList());
        checkDevSetData(portables);
        for (CsLedgerVO c : portables) {
            c.setPid(project.getId());
            CsEquipmentDeliveryPO po = csEquipmentDeliveryMapper.selectById(c.getId());
            c.setComFlag(po.getRunStatus());
            c.setNDId(po.getNdid());
            c.setType("device");
        }
        project.setChildren(portables);

        List<CsLedgerVO> wxProjectList = new ArrayList<>();
        wxProjectList.add(project);

        portable.setChildren(wxProjectList);


        CsLedgerVO government = new CsLedgerVO();
        government.setLevel(0);
        government.setName(DataParam.GOVERNANCE_SYSTEM);
        government.setPid("0");
        government.setId(IdUtil.simpleUUID());
        government.setChildren(engineeringList);
        List<CsLedgerVO> tree = new ArrayList<>();

        if (CollUtil.isNotEmpty(portables)) {
            tree.add(portable);
        }
        if (CollUtil.isNotEmpty(deviceList)) {
            tree.add(government);
        }

        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().select(CsLinePO::getLineId).in(CsLinePO::getDeviceId, devIds)
                .eq(CsLinePO::getStatus, DataStateEnum.ENABLE.getCode()).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();
        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()],Collectors.mapping(CsLedger::getId,Collectors.toList())));

        List<String> projectIds = csLineList.stream().map(it -> it.getPids().split(StrUtil.COMMA)[LineBaseEnum.PROJECT_LEVEL.getCode()]).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());

            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());
                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(it -> it.getPids().split(StrUtil.COMMA)[LineBaseEnum.ENGINEERING_LEVEL.getCode()]).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());

            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> engineerTree = new ArrayList<>();
        List<CsLedgerVO> projectTree = new ArrayList<>();
        List<CsLedgerVO> deviceTree = new ArrayList<>();
        List<CsLedgerVO> lineTree = new ArrayList<>();

        List<CsLedgerVO> allList = this.baseMapper.getAll();
        if (CollectionUtil.isNotEmpty(allList)) {
            //工程集合
            List<CsLedgerVO> tree1 = allList.stream().filter(item -> item.getLevel().equals(LineBaseEnum.ENGINEERING_LEVEL.getCode())).collect(Collectors.toList());
            //项目集合
            List<CsLedgerVO> tree2 = allList.stream().filter(item -> item.getLevel().equals(LineBaseEnum.PROJECT_LEVEL.getCode())).collect(Collectors.toList());
            //设备集合
            List<CsLedgerVO> tree3 = allList.stream().filter(item -> item.getLevel().equals(LineBaseEnum.DEVICE_LEVEL.getCode())).collect(Collectors.toList());
            //监测点集合
            List<CsLedgerVO> tree4 = allList.stream().filter(item -> item.getLevel().equals(LineBaseEnum.LINE_LEVEL.getCode())).collect(Collectors.toList());

            //筛选出云前置设备
            if (CollectionUtil.isNotEmpty(tree3)) {
                Set<String> list1 = new HashSet<>();
                List<String> devList = tree3.stream().map(CsLedgerVO::getId).collect(Collectors.toList());
                List<CsEquipmentDeliveryPO> devs = csEquipmentDeliveryMapper.selectBatchIds(devList);
                Map<String, CsEquipmentDeliveryPO> devsMap = devs.stream().collect(Collectors.toMap(CsEquipmentDeliveryPO::getId, Function.identity()));
                DictTreeVO vo1 = dictTreeFeignClient.queryByCode(DicDataEnum.DEV_CLD.getCode()).getData();

                //list1是 cld设备
                devs.forEach(item -> {
                    if (item.getDevType().equals(vo1.getId())) {
                        list1.add(item.getId());
                    }
                });
                //list2是 非cld设备
                Set<String> list2 = devList.stream().filter(item -> !list1.contains(item)).collect(Collectors.toSet());
                List<CsLedgerVO> tree5 = tree3.stream().filter(vo -> list2.contains(vo.getId())).collect(Collectors.toList());
                Set<String> list3 = tree5.stream().map(CsLedgerVO::getPid).collect(Collectors.toSet());
                projectTree = tree2.stream().filter(vo -> !list3.contains(vo.getId())).collect(Collectors.toList());

                List<CsLedgerVO> tree6 = tree2.stream().filter(vo -> list3.contains(vo.getId())).collect(Collectors.toList());
                Set<String> proList = tree6.stream().map(CsLedgerVO::getPid).collect(Collectors.toSet());
                engineerTree = tree1.stream().filter(vo -> !proList.contains(vo.getId())).collect(Collectors.toList());

                if (CollectionUtil.isNotEmpty(list1)) {
                    deviceTree = tree3.stream()
                            .filter(vo -> list1.contains(vo.getId()))
                            .peek(item -> {
                                CsEquipmentDeliveryPO dev = devsMap.get(item.getId());
                                if (dev != null) {
                                    item.setComFlag(dev.getRunStatus());
                                }
                            })
                            .collect(Collectors.toList());

                    lineTree = tree4.stream()
                            .filter(vo -> list1.contains(vo.getPid()))
                            .peek(item -> {
                                CsEquipmentDeliveryPO dev = devsMap.get(item.getId());
                                if (dev != null) {
                                    item.setComFlag(dev.getRunStatus());
                                }
                            })
                            .collect(Collectors.toList());
                }
            }
        }

        if (CollectionUtil.isNotEmpty(deviceTree)) {
            List<CsLedgerVO> finalLineTree = lineTree;
            deviceTree.forEach(item -> {
                item.setChildren(getChildren(item, finalLineTree));
            });
        }
        if (CollectionUtil.isNotEmpty(projectTree)) {
            List<CsLedgerVO> finalDeviceTree = deviceTree;
            projectTree.forEach(item -> {
                item.setChildren(getChildren(item, finalDeviceTree));
            });
        }
        if (CollectionUtil.isNotEmpty(engineerTree)) {
            List<CsLedgerVO> finalProjectTree = projectTree;
            engineerTree.forEach(item -> {
                item.setChildren(getChildren(item, finalProjectTree));
            });
        }

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

        return government;
    }

    @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 -> {
                DevDetailDTO detail = new DevDetailDTO();
                detail.setEngineeringid(item.getId());
                detail.setEngineeringName(item.getName());
                details.add(detail);
            });
        }
        return details;
    }

    @Override
    public List<DevDetailDTO> getDevInfoByEngineerIds(List<String> list) {
        List<DevDetailDTO> details = new ArrayList<>();
        LambdaQueryWrapper<CsLedger> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(CsLedger::getPid, list);
        List<CsLedger> project = this.list(queryWrapper);
        //工程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);
        dev.forEach(item -> {
            DevDetailDTO detail = new DevDetailDTO();
            detail.setEquipmentName(item.getName());
            detail.setEquipmentId(item.getId());
            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);
            //工程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;
    }

    /**
     * 获取子节点
     */
    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;
    }
}
