package com.yeejoin.equipmanage.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.yeejoin.amos.boot.biz.common.dto.OrgMenuDto;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.component.feign.utils.FeignUtil;
import com.yeejoin.amos.feign.morphic.Morphic;
import com.yeejoin.amos.feign.morphic.model.ResourceDTO;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import com.yeejoin.amos.feign.systemctl.model.DictionarieValueModel;
import com.yeejoin.equipmanage.common.datasync.entity.FireFightingSystem;
import com.yeejoin.equipmanage.common.dto.OrgUsrDto;
import com.yeejoin.equipmanage.common.entity.*;
import com.yeejoin.equipmanage.common.entity.dto.EquipTypeAmountPageDTO;
import com.yeejoin.equipmanage.common.entity.vo.*;
import com.yeejoin.equipmanage.common.enums.*;
import com.yeejoin.equipmanage.common.utils.StringUtil;
import com.yeejoin.equipmanage.common.vo.*;
import com.yeejoin.equipmanage.mapper.*;
import com.yeejoin.equipmanage.remote.RemoteSecurityService;
import com.yeejoin.equipmanage.service.*;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class FireFightingSystemServiceImpl extends ServiceImpl<FireFightingSystemMapper, FireFightingSystemEntity>
        implements IFireFightingSystemService {

    @Autowired
    FireFightingSystemMapper fireFightingSystemMapper;
    @Autowired
    IRiskSourceSceneService iRiskSourceSceneService;
    @Autowired
    private RemoteSecurityService remoteSecurityService;

    @Autowired
    private EquipmentManageMapper equipmentManageMapper;
    @Autowired
    private EquipmentManageService equipmentManageService;
    @Autowired
    private BuildingMapper buildingMapper;
    @Autowired
    private FormInstanceMapper formInstanceMapper;
    @Autowired
    private SourceSceneMapper sourceSceneMapper;
    @Value("${equipment.fire.systemid}")
    private String fireSystemId;
    @Value("${morphic.projectSeq}")
    private Long projectSeq;
    @Value("${mqtt.scene.host}")
    private String sceneUrl;
    @Value("${equip.point.equipmentdata.topic}")
    private String wsTopic;

    @Value("${equip.point.speindex.url}")
    private String speindexUrl;
    @Value("${equip.point.equipmentDetail.url}")
    private String equipmentDetailUrl;

    @Value("${systemctl.dict.iot-core-param}")
    private String iotCoreParam;

    @Autowired
    private IEqDynamicFormGroupService iEqDynamicFormGroupService;

    @Autowired
    private IEqDynamicFormInstanceService instanceService;

    @Autowired
    @Lazy
    private IEquipmentSpecificSerivce equipmentSpecificSerivce;

    @Autowired
    private ISourceSceneService iSourceSceneService;

    @Autowired
    private ISyncDataService syncDataService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    MqttSendGateway mqttSendGateway;

    @Autowired
    private JCSRemoteService jcsRemoteService;

    @Value("${systemctl.sync.switch}")
    private Boolean syncSwitch;

    @Value("${auth-key-fire-system:fire_system_info}")
    private String authKey;

    @Value("${equipment.type}")
    String equipmentCategoryLeftTypeCode;

    @Autowired
    IEquipmentCategoryService iEquipmentCategoryService;

    @Autowired
    ISourceStatistics sourceStatistics;

    @Value("${redis_car_type_count}")
    private String carTypeAndCount;

    @Value("${redis_equip_type_count}")
    private String equipTypeAndCount;

    @Override
    public List<EquipCountBySystemVO> getEquipCountBySystemId(Long systemId) {
        return this.baseMapper.getEquipCountBySystemId(systemId);
    }

    @Override
    public List<EquiplistSpecificBySystemVO> getEquiplistBySystemId(Long systemId) {
        return this.baseMapper.getEquiplistBySystemId(systemId);
    }

    @Override
    public Map<String, Object> queryEquipmenInfoAndCount(String equimentName, String equimentCode, String construction,
                                                         String maintenance, String bizOrgCode, String formGroupId, int current, int pageSize) {
        Map<String, Object> map = equipmentManageService.queryEquipmenInfoAndCount(equimentName, equimentCode,
                construction, maintenance, bizOrgCode, formGroupId, current, pageSize);
        List<EquipmentManageVo> dataList = (List<EquipmentManageVo>) map.get("dataList");
        StringBuilder stb = new StringBuilder();
        dataList.forEach(y -> {
            if (StringUtil.isNotEmpty(String.valueOf(stb))) {
                stb.append("," + y.getChargePerson());
            } else {
                stb.append(y.getChargePerson());
            }
        });
        Map<String, String> userMap = new HashMap<>();
        if (StringUtil.isNotEmpty(stb)) {
            List<AgencyUserModel> agencyUserModels = remoteSecurityService.listUserByUserIds(stb.toString());
            agencyUserModels.forEach(z -> {
                userMap.put(z.getUserId(), z.getRealName());
            });
        }

        dataList.forEach(x -> {
            x.setChargePerson(userMap.get(x.getChargePerson()));
            x.setSystemimg(equipmentManageMapper.getFiles(String.valueOf(x.getId()), "face"));
        });
        map.put("dataList", dataList);
        return map;
    }

    @Override
    public FireFightingSystemEntity getOneById(Long id) {
        FireFightingSystemEntity fireFightingSystemEntity = this.baseMapper.selectById(id);
        return fireFightingSystemEntity;
    }

    @Override
    public String save(FireFightingSystemVo vo) {
        if (!systemCodeCheck(vo)) {
            throw new BadRequest("系统编号已存在，请重新输入");
        }
        List<DynamicFormInstance> formInstance = vo.getFormInstances();
        // 验证必填项 BUG 2725 by kongfm 2021-09-09
        formInstance.forEach(item -> {
            if (item.getNotNull() && StringUtils.isEmpty(item.getFieldValue())) {
                throw new BadRequest(item.getFieldLabel() + "为必填项，请确认");
            }
        });
        String userId = remoteSecurityService.getAgencyUser().getUserId();
        vo.setRecUserId(userId);
        // 冗余名称，数据同步使用
        this.setChargePersonName(vo);
        String s = String.valueOf(System.currentTimeMillis());
        vo.setId(s);
        vo.setSort(s);
        DynamicFormGroup dynamicFormGroup = iEqDynamicFormGroupService.getById(vo.getFormGroupId());
        vo.setSystemType(dynamicFormGroup.getRelationId() != null ? dynamicFormGroup.getRelationId().toString() : "");
        // fireSystemId 为字典表火灾系统id 以此确保第一个生成的火灾报警系统排序为1
        if (vo.getSystemType().equals(fireSystemId)) {
            vo.setSort("1");
        }
        if ("".equals(vo.getInstallDate())) {
            vo.setInstallDate(null);
        }
        if ("".equals(vo.getFirstMaintenanceDate())) {
            vo.setFirstMaintenanceDate(null);
        }
        // 1.保存动态表单数据
        if (vo.getFormInstances() != null && vo.getFormInstances().size() > 0) {
            Long instanceId = instanceService.saveInstanceBatch(vo.getFormInstances());
            vo.setInstanceId(instanceId);
            s = s + "," + instanceId;
        }
        // 2.保存消防系统数据
        int save = fireFightingSystemMapper.save(vo);
        if (save > 0 && syncSwitch) {
            // AST数据同步
            List<FireFightingSystem> fireFightingSystemDetail = getFireFightingSystemDetail(vo);
            syncDataService.syncCreatedFireFightingSystem(fireFightingSystemDetail);
        } else {
            return s;
        }
        // 3.保存图片数据
        this.insertFiles(vo);
        return s;
    }

    @Override
    public String update(FireFightingSystemVo vo) {
        if (!systemCodeCheck(vo)) {
            throw new BadRequest("系统编号已存在，请重新输入");
        }
        // 验证必填项 BUG 2725 by kongfm 2021-09-09
        List<DynamicFormInstance> formInstance = vo.getFormInstances();
        formInstance.stream().forEach(item -> {
            if (item.getNotNull() == true && StringUtils.isEmpty(item.getFieldValue())) {
                throw new BadRequest(item.getFieldLabel() + "为必填项，请确认");
            }
        });
        String userId = remoteSecurityService.getAgencyUser().getUserId();
        vo.setRecUserId(userId);
        // 冗余名称，数据同步使用
        this.setChargePersonName(vo);
        if ("".equals(vo.getInstallDate())) {
            vo.setInstallDate(null);
        }
        if ("".equals(vo.getFirstMaintenanceDate())) {
            vo.setFirstMaintenanceDate(null);
        }

        int update = fireFightingSystemMapper.update(vo);
        if (update > 0 && syncSwitch) {
            // AST数据同步
            List<FireFightingSystem> fireFightingSystemDetail = getFireFightingSystemDetail(vo);
            syncDataService.syncCreatedFireFightingSystem(fireFightingSystemDetail);
        } else {
            return null;
        }
        // 1.更新消防系统数据
        String sequenceNbr = vo.getId();
        fireFightingSystemMapper.deleteFilre(sequenceNbr);
        // 2.更新动态表单数据
        if (vo.getInstanceId() != null && vo.getFormInstances().size() > 0) {
            instanceService.updateInstanceBatch(vo.getInstanceId(), vo.getFormInstances());
        }
        // 3.更新图片数据
        this.insertFiles(vo);
        return vo.getId();
    }

    private void setChargePersonName(FireFightingSystemVo vo) {
        if (StringUtil.isNotEmpty(vo.getRecUserId())) {
            FeignClientResult<AgencyUserModel> result = Privilege.agencyUserClient.queryByUserId(vo.getRecUserId());
            AgencyUserModel userModel = result == null ? new AgencyUserModel() : result.getResult();
            vo.setChargePersonName(userModel.getRealName());
        }
    }

    private boolean systemCodeCheck(FireFightingSystemVo systemVo) {
        if (StringUtils.isEmpty(systemVo.getId())) {
            // 新建系统时
            int count = this.baseMapper.selectCount(new LambdaQueryWrapper<FireFightingSystemEntity>()
                    .eq(FireFightingSystemEntity::getCode, systemVo.getCode()));
            return count < 1;
        } else {
            int count = this.baseMapper.selectCount(new LambdaQueryWrapper<FireFightingSystemEntity>()
                    .eq(FireFightingSystemEntity::getCode, systemVo.getCode())
                    .ne(FireFightingSystemEntity::getId, systemVo.getId()));
            return count < 1;
        }
    }

    @Override
    public FireFightingSystemVo createMorphic(FireFightingSystemVo model) {
        ResourceDTO resourceDTO = new ResourceDTO();
        resourceDTO.setSubjectId(projectSeq);
        resourceDTO.setSubjectid(projectSeq);
        resourceDTO.setName(model.getName());
        // 为首次 添加的画布添加mqtt 相关数据
        String content = "{\"layout\":\"\",\"boardConfig\":{\"modeType\":\"custom\",\"orientation\":\"lengthways\",\"autoRefresh\":true,\"name\":\"1\",\"showMode\":\"actual\",\"paperSize\":\"1280X900\"},\"boardStyle\":{\"backgroundImage\":\"\"},\"dataConfig\":{}}";
        Map parse = (Map) JSON.parse(content);
        Map<String, Object> dataConfig = new HashMap<>();
        dataConfig.put("msgType", "mqtt");
        dataConfig.put("wsUrl", sceneUrl);
        parse.put("dataConfig", dataConfig);
        content = JSONObject.toJSONString(parse);
        dataConfig.put("wsTopic", wsTopic);
        resourceDTO.setContent(content);
        ResourceDTO morphic = Morphic.morphicSubjectClient.create(resourceDTO).getResult();
        model.setSceneId(morphic.getId());
//        fireFightingSystemMapper.setSceneId(model);
        return model;
    }

    @Override
    @Transactional
    public ResourceDTO updateMorphic(ResourceDTO resourceDTO) {
        try {
            // 1.更新画布信息
            resourceDTO.setSubjectId(projectSeq);
            resourceDTO.setSubjectid(projectSeq);
            String content = resourceDTO.getContent();
            Map parse = (Map) JSON.parse(content);
            Map<String, Object> dataConfig = new HashMap<>();
            dataConfig.put("msgType", "mqtt");
            dataConfig.put("wsUrl", sceneUrl);
            dataConfig.put("wsTopic", wsTopic);
            parse.put("dataConfig", dataConfig);
            content = JSONObject.toJSONString(parse);
            resourceDTO.setContent(content);
            FeignUtil.remoteCall(() -> Morphic.morphicSubjectClient.update(resourceDTO));
            // 2.更新业务关联的画布id
            Long systemId = Long.valueOf(resourceDTO.getCode());
            FireFightingSystemVo systemVo = new FireFightingSystemVo();
            systemVo.setId(String.valueOf(systemId));
            systemVo.setSceneId(resourceDTO.getId());
            fireFightingSystemMapper.setSceneId(systemVo);
            // 3.保存场景关联信息表
            SourceScene sourceScene = sourceSceneMapper
                    .selectOne(new LambdaQueryWrapper<SourceScene>().eq(SourceScene::getSceneId, resourceDTO.getId()));
            if (sourceScene == null) {
                sourceScene = new SourceScene();
                sourceScene.setProjectId(String.valueOf(projectSeq));
                sourceScene.setSourceId(systemId);
                sourceScene.setSourceName(resourceDTO.getName());
                sourceScene.setSceneId(resourceDTO.getId());
            }
            // TODO 获取画布下 绑定的装备点、摄像头，目前消防系统只能绑定装备，不能绑定摄像头（树未返回摄像头）
            List<Map> children = (List<Map>) parse.get("children");
            String pointInScene = "";
            String videoInScene = "";
            if (!CollectionUtils.isEmpty(children)) {
                for (Map<String, String> map : children) {
                    String key = map.get("key");
                    if (!"".equals(key) && "equipment".equals(key)) {
                        pointInScene = "".equals(pointInScene) ? map.get("sequenceNbr")
                                : pointInScene + "," + map.get("sequenceNbr");
                    }
                    if (!"".equals(key) && "video".equals(key)) {
                        videoInScene = "".equals(videoInScene) ? map.get("sequenceNbr")
                                : videoInScene + "," + map.get("sequenceNbr");
                    }
                }
            }
            sourceScene.setPointInScene(pointInScene);
            sourceScene.setVideoInScene(videoInScene);
            iSourceSceneService.saveOrUpdate(sourceScene);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BadRequest("保存画布失败");
        }
        return resourceDTO;
    }

    @Override
    public List<PointTreeVo> getPointTree(String id, String orgCode) {
//        CommonResponse se = riskModelFeign.getRiskSourceList(orgCode);
//        List<Map<String, Object>> list = (List<Map<String, Object>>) se.getDataList();
//        List<PointTreeVo> responses = new ArrayList<>();
//        list.forEach(m -> {
//            RiskSourceTreeResponse r = new RiskSourceTreeResponse();
//            PointTreeVo p = new PointTreeVo();
//            mapToBean(m, r);
//            p.setDisplayName(r.getName());
//            p.setParentId(r.getParentId());
//            p.setSequenceNbr(r.getId());
//            p.setIsRegion(r.getIsRegion());
//            responses.add(p);
//        });
//        List<PointTreeVo> regionList = responses.stream().filter(r -> "TRUE".equals(r.getIsRegion())).collect(Collectors.toList());
        List<PointTreeVo> buildList = buildingMapper.getBuildList(orgCode);
        return transferListToPointTree(buildList, id);
    }

    @Override
    public List<SpeIndexVo> getSpeIndex(Long id) {
        return makeStatus(fireFightingSystemMapper.getSpeIndex(id));
    }

    private void insertFiles(FireFightingSystemVo vo) {
        List<FileUploadVo> video = vo.getVideo();
        if (video.size() > 0) {
            for (FileUploadVo f : video) {
                f.setId(String.valueOf(System.currentTimeMillis()));
                f.setUserId(vo.getRecUserId());
                f.setFileType("video");
                f.setObjectId(vo.getId());
                fireFightingSystemMapper.insertFile(f);
            }
        }
        List<FileUploadVo> faceimg = vo.getFaceimg();
        if (faceimg.size() > 0) {
            for (FileUploadVo f : faceimg) {
                f.setId(String.valueOf(System.currentTimeMillis()));
                f.setUserId(vo.getRecUserId());
                f.setFileType("face");
                f.setObjectId(vo.getId());
                fireFightingSystemMapper.insertFile(f);
            }
        }
        List<FileUploadVo> instruction = vo.getInstruction();
        if (instruction.size() > 0) {
            for (FileUploadVo f : instruction) {
                f.setId(String.valueOf(System.currentTimeMillis()));
                f.setUserId(vo.getRecUserId());
                f.setFileType("instruction");
                f.setObjectId(vo.getId());
                fireFightingSystemMapper.insertFile(f);
            }
        }
        List<FileUploadVo> asser = vo.getAsser();
        if (asser.size() > 0) {
            for (FileUploadVo f : asser) {
                f.setId(String.valueOf(System.currentTimeMillis()));
                f.setUserId(vo.getRecUserId());
                f.setFileType("certificate");
                f.setObjectId(vo.getId());
                fireFightingSystemMapper.insertFile(f);
            }
        }

        List<FileUploadVo> spotimg = vo.getSpotimg();
        if (spotimg.size() > 0) {
            for (FileUploadVo f : spotimg) {
                f.setId(String.valueOf(System.currentTimeMillis()));
                f.setUserId(vo.getRecUserId());
                f.setFileType("spotimg");
                f.setObjectId(vo.getId());
                fireFightingSystemMapper.insertFile(f);
            }
        }

        List<FileUploadVo> tdmod = vo.getTdmod();
        if (tdmod.size() > 0) {
            for (FileUploadVo f : tdmod) {
                f.setId(String.valueOf(System.currentTimeMillis()));
                f.setUserId(vo.getRecUserId());
                f.setFileType("tdmod");
                f.setObjectId(vo.getId());
                fireFightingSystemMapper.insertFile(f);
            }
        }
    }

    /**
     * 生成树结构
     *
     * @param allRiskSource
     * @param id
     * @return
     */
    public List<PointTreeVo> transferListToPointTree(List<PointTreeVo> allRiskSource, String id) {
        List<PointTreeVo> treeList = new ArrayList<>();
        // TODO id为空，为消防建筑使用；id不为空，为点位图使用
        List<PointTreeVo> pointData = fireFightingSystemMapper.getPointData(id);
        if (!CollectionUtils.isEmpty(pointData)) {
            List<Long> idList = pointData.stream().map(PointTreeVo::getSequenceNbr).collect(Collectors.toList());
            List<SpeIndexVo> indexVoList = fireFightingSystemMapper.getSpeIndexIn(idList);
            if (!CollectionUtils.isEmpty(indexVoList)) {
                Map<Long, List<SpeIndexVo>> indexMap = indexVoList.stream()
                        .collect(Collectors.groupingBy(SpeIndexVo::getEquipmentSpecificId));
                pointData.stream().forEach(p -> {
                    Map map = new HashMap();
                    map.put("imgPath", p.getImgPath());
                    map.put("equipCode", p.getEquipCode());
                    map.put("equipSyetemId", p.getEquipSyetemId());
                    map.put("equipTypeId", p.getEquipId());
                    map.put("speindexList", makeStatus(indexMap.get(p.getSequenceNbr())));
                    map.put("speindexApi", speindexUrl + p.getSequenceNbr());
                    map.put("detailInfoApi", equipmentDetailUrl + p.getSequenceNbr());
                    map.put("detailApi", equipmentDetailUrl + p.getSequenceNbr());
                    p.setDataConfig(map);
                });
            }
        }
        allRiskSource.addAll(pointData);
        for (PointTreeVo tree : allRiskSource) {
            if (tree.getParentId() == null || tree.getParentId() == -1) {
                treeList.add(tree);
            }
            for (PointTreeVo treeNode : allRiskSource) {
                if (tree.getSequenceNbr().equals(treeNode.getParentId())) {
                    if (tree.getChildren() == null) {
                        tree.setChildren(new ArrayList<>());
                    }
                    tree.getChildren().add(treeNode);
                }
            }
        }
        return treeList;
    }

    /**
     * 生成树结构
     *
     * @param allRiskSource
     * @return
     */
    public List<PointTreeVo> transferListTo3dPointTree(List<PointTreeVo> allRiskSource) {
        List<PointTreeVo> treeList = new ArrayList<>();
        List<PointTreeVo> pointData = fireFightingSystemMapper.get3dPointData();
        if (!CollectionUtils.isEmpty(pointData)) {
            allRiskSource.addAll(pointData);
            for (PointTreeVo tree : allRiskSource) {
                if (tree.getParentId() == null || tree.getParentId() == -1) {
                    treeList.add(tree);
                }
                for (PointTreeVo treeNode : allRiskSource) {
                    if (tree.getSequenceNbr().equals(treeNode.getParentId())) {
                        if (tree.getChildren() == null) {
                            tree.setChildren(new ArrayList<>());
                        }
                        tree.getChildren().add(treeNode);
                    }
                }
            }
            return treeList;
        }
        return Lists.newArrayList();
    }

    private static <T> void mapToBean(Map<String, Object> map, T bean) {
        try {
            BeanUtils.populate(bean, map);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        Set<?> set = new HashSet<>();

    }

    /**
     * 生成 性能指标数据
     *
     * @param list
     * @return
     */
    private List<SpeIndexVo> makeStatus(List<SpeIndexVo> list) {
        if (list == null || list.size() == 0) {
            return new ArrayList<>();
        }
        List<SpeIndexVo> newList = new ArrayList<>();
        List<SpeIndexVo> statusList = new ArrayList<>();
        for (SpeIndexVo vo : list) {
            int status = vo.getIsAlarm();
            if (AlarmStatusEnum.BJ.getCode() == status) {
                statusList.add(vo);
            }
            newList.add(vo);
        }
        if (statusList.size() == 0) {
            return newList;
        }
        SpeIndexVo spe = new SpeIndexVo();
        spe.setKey(EquipmentSpeIndexEnum.YXZT.getCode());
        SpeIndexVo latestVo = statusList.get(0);
        org.springframework.beans.BeanUtils.copyProperties(latestVo, spe);
        spe.setName("当前状态");
        Map<String, String> map = getStatus(statusList);
        spe.setValue(map.get("runStatus"));
        spe.setColor(map.get("color"));
        statusList.clear();
        statusList.add(spe);
        statusList.addAll(newList);
        return statusList;
    }

    /**
     * 判断 装备状态
     *
     * @param statusList
     * @return
     */
    private Map<String, String> getStatus(List<SpeIndexVo> statusList) {
        Map<String, String> map = new HashMap<>();
        SpeIndexVo indexVo = statusList.get(0);
        int i = 0;
        for (SpeIndexVo x : statusList) {
            if (StringUtil.isNotEmpty(x.getIndexValue())) {
                i = i + 1;
            }
        }
        if (0 == i) {
            map.put("runStatus", "无");
            map.put("color", "");
            return map;
        }
        if (StringUtil.isNotEmpty(indexVo.getIndexValue()) && TrueOrFalseEnum.real.value.toUpperCase().equals(indexVo.getIndexValue().toUpperCase())) {
            map.put("runStatus", indexVo.getIndexName());
            map.put("color", indexVo.getColor());
            return map;
        }
        map.put("runStatus", "运行");
        map.put("color", "");
        return map;
    }

    @Override
    public List<FireFightingSystemEntity> getList() {
        return this.list();
    }

    @Override
    public Boolean deleteSystem(Long id) {
//        QueryWrapper<FormInstance> fqw = new QueryWrapper<>();
//        fqw.eq("field_value",id);
//        fqw.groupBy("instance_id");
//        List<FormInstance> formInstances = formInstanceMapper.selectList(fqw);
//        if (formInstances != null && formInstances.size()>0){
//            QueryWrapper<FormInstance> one = new QueryWrapper<>();
//            one.eq("instance_id",formInstances.get(0).getInstanceId());
//            one.eq("field_name","name");
//            List<FormInstance> formInstances1 = formInstanceMapper.selectList(one);
//            FormInstance formInstance = formInstances1.get(0);
//            String name = formInstance.getFieldValue();
//            throw new BadRequest(name+"建筑与该系统存在绑定关系，请清除后再进行删除！");
//        }
        FireFightingSystemEntity entity = baseMapper.selectById(id);
        if (entity.getSceneId() != null) {
            try {
                FeignUtil.remoteCall(() -> Morphic.morphicSubjectClient.delete(entity.getSceneId()));
            } catch (Exception e) {
                throw new RuntimeException("远程调用 MORPHIC 服务的删除操作出错");
            }
        }
        formInstanceMapper.clearSystemId(id);
        // 解除装备与消防系统关系
        this.removeBondSystemId(id);
        this.baseMapper.deleteFilre(String.valueOf(id));
        int i = this.baseMapper.deleteById(id);
        if (i > 0 && syncSwitch) {
            syncDataService.syncDeletedFireFightingSystem(Arrays.asList(id));
        }
        // 删除动态关联表单实例数据
        if (entity.getInstanceId() != null) {
            instanceService.remove(new LambdaQueryWrapper<DynamicFormInstance>().eq(DynamicFormInstance::getInstanceId,
                    entity.getInstanceId()));
        }
        return i > 0;
    }

    private void removeBondSystemId(Long id) {
        List<EquipmentSpecific> equipmentSpecifics = equipmentSpecificSerivce
                .list(new LambdaQueryWrapper<EquipmentSpecific>().like(EquipmentSpecific::getSystemId, id));
        equipmentSpecifics.forEach(equipmentSpecific -> {
            List<String> ids = new ArrayList<>();
            if (StringUtil.isNotEmpty(equipmentSpecific.getSystemId())) {
                ids = Arrays.asList(equipmentSpecific.getSystemId().split(","));
                ids = new ArrayList<>(ids);
                ids.remove(id.toString());
            }
            equipmentSpecific.setSystemId(Joiner.on(",").join(ids));
        });
        if (!equipmentSpecifics.isEmpty()) {
            equipmentSpecificSerivce.saveOrUpdateBatch(equipmentSpecifics);
        }
    }

    @Override
    public Boolean isDeleteCanvas(Long id) {
        FireFightingSystemEntity system = baseMapper
                .selectOne(new QueryWrapper<FireFightingSystemEntity>().eq("scene_id", id));
        if (system != null) {
            return true;
        } else {
            FeignUtil.remoteCall(() -> Morphic.morphicSubjectClient.delete(id));
            return false;
        }
    }

    @Override
    public IPage<EquipTypeImgAmountVO> getColaCategoryAmountList(int hierarchy, String codeHead,
                                                                 EquipTypeAmountPageDTO equipTypeAmountPage) {
        String type = equipTypeAmountPage.getType();
        if (!"".equals(type) && "car".equals(type)) {
            equipTypeAmountPage.setSystemId(null);
            equipTypeAmountPage.setStatus(null);
        }
        IPage<EquipTypeImgAmountVO> list = fireFightingSystemMapper
                .getColaCategoryAmountList(equipTypeAmountPage.getPage(), hierarchy, codeHead, equipTypeAmountPage);
        list.getRecords().forEach(x -> {
            if (!x.getEqtype().startsWith("4") && StringUtil.isNotEmpty(x.getAmount())) {
                x.setAmount(x.getAmount().split("\\.")[0]);
            }
        });
        return list;
    }
    @Override
    public IPage<EquipTypeImgAmountVO> getColaCategoryAmountListIot(int hierarchy, String codeHead,
                                                                 EquipTypeAmountPageDTO equipTypeAmountPage) {
        String type = equipTypeAmountPage.getType();
        if (!"".equals(type) && "car".equals(type)) {
            equipTypeAmountPage.setSystemId(null);
            equipTypeAmountPage.setStatus(null);
        }
        IPage<EquipTypeImgAmountVO> list = fireFightingSystemMapper
                .getColaCategoryAmountListIot(equipTypeAmountPage.getPage(), hierarchy, codeHead, equipTypeAmountPage);
        list.getRecords().forEach(x -> {
            if (!x.getEqtype().startsWith("4") && StringUtil.isNotEmpty(x.getAmount())) {
                x.setAmount(x.getAmount().split("\\.")[0]);
            }
        });
        return list;
    }
    @Override
    public IPage<EquipTypeImgAmountVO> getColaCategoryAmountCarList(int hierarchy, String codeHead,
                                                                    EquipTypeAmountPageDTO equipTypeAmountPage) {
        String type = equipTypeAmountPage.getType();
        if (!"".equals(type) && "car".equals(type)) {
            equipTypeAmountPage.setSystemId(null);
            equipTypeAmountPage.setStatus(null);
        }
        IPage<EquipTypeImgAmountVO> list = fireFightingSystemMapper
                .getColaCategoryAmountCarList(equipTypeAmountPage.getPage(), hierarchy, codeHead, equipTypeAmountPage);
        list.getRecords().forEach(x -> {
            if (!x.getEqtype().startsWith("4") && StringUtil.isNotEmpty(x.getAmount())) {
                x.setAmount(x.getAmount().split("\\.")[0]);
            }
        });
        return list;
    }

    @Override
    public IPage<EquipTypeImgAmountVO> getColaCategoryAmountEquList(int hierarchy, String codeHead,
                                                                    EquipTypeAmountPageDTO equipTypeAmountPage) {
        String type = equipTypeAmountPage.getType();
        if (!"".equals(type) && "car".equals(type)) {
            equipTypeAmountPage.setSystemId(null);
            equipTypeAmountPage.setStatus(null);
        }
        IPage<EquipTypeImgAmountVO> list = fireFightingSystemMapper
                .getColaCategoryAmountEquList(equipTypeAmountPage.getPage(), hierarchy, codeHead, equipTypeAmountPage);
        list.getRecords().forEach(x -> {
            if (!x.getEqtype().startsWith("4") && StringUtil.isNotEmpty(x.getAmount())) {
                x.setAmount(x.getAmount().split("\\.")[0]);
            }
        });
        return list;
    }

    @Override
    public List<EquipmentManageVo> getSystemCategory() {
        return equipmentManageMapper.getSystemList();
    }

    @Override
    public List<FireFightingSystem> getFireFightingSystemDetail(FireFightingSystemVo fireFightingSystemVo) {
        return fireFightingSystemMapper.getFireFightingSystemDetail(fireFightingSystemVo);
    }

    @Override
    public List<FireFightingSystemEntity> getFightingSysByCodes(String[] idsArr) {
        List<FireFightingSystemEntity> fightingSystemList = fireFightingSystemMapper.getFightingSysByCodes(idsArr);
        if (fightingSystemList != null && !fightingSystemList.isEmpty()) {
            return fightingSystemList;
        }
        return Lists.newArrayList();
    }

    @Override
    public List<FireFightingSystem3dVo> get3dFightingSystemList() {
        FeignClientResult<List<DictionarieValueModel>> dictValues = Systemctl.dictionarieClient
                .dictValues(iotCoreParam);
        Optional.ofNullable(dictValues).orElseThrow(() -> new BadRequest("查询字段数据为空"));
        List<DictionarieValueModel> values = dictValues.getResult();
        if (!CollectionUtils.isEmpty(values)) {
            List<String> collect = values.stream().map(DictionarieValueModel::getDictDataKey)
                    .collect(Collectors.toList());
            List<FireFightingSystem3dVo> list = fireFightingSystemMapper.get3dFightingSystemList(collect);
            if (!CollectionUtils.isEmpty(list)) {
                return list;
            }
        }
        return Lists.newArrayList();
    }

    @Override
    public FireFightingSystemEntity getDetailByCode(String systemCode) {
        LambdaQueryWrapper<FireFightingSystemEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FireFightingSystemEntity::getCode, systemCode);
        List<FireFightingSystemEntity> systemEntities = this.list(wrapper);
        if (systemEntities.isEmpty()) {
            throw new RuntimeException("code" + systemCode + "不存在");
        }
        return systemEntities.get(0);
    }

    @Override
    public List<AlarmDataVO> getSystemById(Long id) {
        return this.baseMapper.getSystemById(id);
    }

    @Override
    public IPage<EquipmentAlarmBySystemIdOrSourceIdVO> getEquipmentAlarmBySystemIdOrSourceIdVO(
            IPage<EquipmentAlarmBySystemIdOrSourceIdVO> page, Long sourceId, Long systemId, Integer confirmType,
            String createDate, String type) {
        return this.baseMapper.getEquipmentAlarmBySystemIdOrSourceIdVO(page, sourceId, systemId, confirmType,
                createDate, type);
    }

    private static String getInet4Address() {
        Enumeration<NetworkInterface> nis;
        String ip = null;
        try {
            nis = NetworkInterface.getNetworkInterfaces();
            for (; nis.hasMoreElements(); ) {
                NetworkInterface ni = nis.nextElement();
                Enumeration<InetAddress> ias = ni.getInetAddresses();
                for (; ias.hasMoreElements(); ) {
                    InetAddress ia = ias.nextElement();
                    if (ia instanceof Inet4Address && !ia.getHostAddress().equals("127.0.0.1")) {
                        ip = ia.getHostAddress();
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return ip;
    }

    @Override
    public Map<String, Object> integrationPageSysData(String systemCode, Boolean isUpdate) {
        // TODO Auto-generated method stub
        if (!StringUtil.isNotEmpty(SystemTypeEnum.getEnum(systemCode))) {
            return null;
        }
        Map<String, Object> data;
        if (isUpdate) {
            data = saveIntegrationPageSysData(systemCode);
        } else {
            if (redisUtils.hasKey(systemCode)) {
                data = JSONObject.parseObject(redisUtils.get(systemCode).toString(), Map.class);
            } else {
                data = saveIntegrationPageSysData(systemCode);
            }

        }
        if (!ObjectUtils.isEmpty(data)) {
            mqttSendGateway.sendToMqtt(String.format("%s%s", "INTEGRATE_TOPIC/", systemCode), JSON.toJSONString(data));
        }
        return null;
    }

    public Map<String, Object> saveIntegrationPageSysData(String systemCode) {
        Map<String, Object> data = null;
        if (SystemTypeEnum.fireAlarmSys.getCode().equals(systemCode)) {
            data = fireFightingSystemMapper.fireAlarmSysEquipmentNumber();
            this.putAll(data, fireFightingSystemMapper.fireAlarmSysIndexNumber());
        } else if (SystemTypeEnum.fireCAFSSys.getCode().equals(systemCode)) {
            data = fireFightingSystemMapper.getFireCafsSystem();
        } else if (SystemTypeEnum.fireONLSys.getCode().equals(systemCode)) {
            data = fireFightingSystemMapper.getFireOnlSystem();
            this.putAll(data, fireFightingSystemMapper.getFireOnlSystemThreeSmall());
        } else if (SystemTypeEnum.fireFoamSys.getCode().equals(systemCode)) {
            data = fireFightingSystemMapper.fireFoamSysEquipmentIndexNumber();
        } else if (SystemTypeEnum.fireFoamMistSys.getCode().equals(systemCode)
                || SystemTypeEnum.envMonitoringSys.getCode().equals(systemCode)) {
            // TODO 灯泡及门状态，实时数据库刷新,存放数据，套用后续逻辑进行数据的发送
            data = new HashMap<>();
            data.put("waitRefresh", true);
        } else if (SystemTypeEnum.fireWaterSys.getCode().equals(systemCode)) {
            data = fireFightingSystemMapper.fireWaterSysCollectingDevice();
            this.putAll(data, fireFightingSystemMapper.fireWaterSysPool());
            this.putAll(data, fireFightingSystemMapper.fireWaterSysWaterPump());
            this.putAll(data, fireFightingSystemMapper.fireWaterSysHydrant());
            this.putAll(data, fireFightingSystemMapper.fireWaterSysPipeNetwork());
        } else {
            data = fireFightingSystemMapper.otherSysIndexNumAndTotal();
        }
        if (!ObjectUtils.isEmpty(data)) {
            redisUtils.set(systemCode, JSONObject.toJSONString(data));
        }
        return data;
    }

    private void putAll(Map<String, Object> data, Map<String, Object> addMap) {
        if (!CollectionUtils.isEmpty(addMap)) {
            data.putAll(addMap);
        }
    }

    @Override
    public List<FireFightingSystemTreeVo> getSystemTreeByOrgCode(String bizOrgCode) {
        // 获取公司部门list
        List<OrgUsrDto> orgUsrLists = jcsRemoteService.getCompanyDeptListWithAuth("COMPANY,DEPARTMENT", bizOrgCode);
        List<FireFightingSystemTreeVo> fireFightingSystemTreeList = orgUsrLists.stream().map(key -> {
            FireFightingSystemTreeVo vo = new FireFightingSystemTreeVo();
            vo.setId(String.valueOf(key.getSequenceNbr()));
            vo.setName(key.getBizOrgName());
            vo.setType(key.getBizOrgType());
            vo.setBizOrgCode(key.getBizOrgCode());
            vo.setParentId(key.getParentId());
            return vo;
        }).collect(Collectors.toList());

        // 根据bizOrgCode获取系统list
        List<String> bizOrgCodes = fireFightingSystemTreeList.stream().map(FireFightingSystemTreeVo::getBizOrgCode)
                .collect(Collectors.toList());
        LambdaQueryWrapper<FireFightingSystemEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(FireFightingSystemEntity::getBizOrgCode, bizOrgCodes);
        List<FireFightingSystemEntity> fireFightingSystemEntityList = this.baseMapper.selectList(wrapper);
        List<FireFightingSystemTreeVo> systemList = fireFightingSystemEntityList.stream().map(key -> {
            FireFightingSystemTreeVo vo = new FireFightingSystemTreeVo();
            vo.setId(String.valueOf(key.getId()));
            vo.setName(key.getName());
            vo.setType("system");
            vo.setBizOrgCode(key.getBizOrgCode());
            return vo;
        }).collect(Collectors.toList());

        // 组装公司部门树
        fireFightingSystemTreeList.addAll(systemList);
        return fireFightingSystemTreeList.stream().filter(d -> !"system".equals(d.getType()))
                .peek((m) -> m.setChildren(getChildren(m, fireFightingSystemTreeList))).collect(Collectors.toList());
    }

    private List<FireFightingSystemTreeVo> getChildren(FireFightingSystemTreeVo root,
                                                       List<FireFightingSystemTreeVo> all) {
        return all.stream()
                .filter(d -> StringUtil.isNotEmpty(d.getParentId()) && d.getParentId().equals(root.getId())
                        || (StringUtil.isNotEmpty(d.getBizOrgCode()) && d.getBizOrgCode().equals(root.getBizOrgCode())
                        && !"system".equals(root.getType()) && !d.getId().equals(root.getId())))
                .peek(m -> m.setChildren(getChildren(m, all))).collect(Collectors.toList());
    }

    @Override
    public List<OrgMenuDto> companyTreeByUserAndType(String type) {
        return jcsRemoteService.getCompanyDeptTreeWithAuth(authKey, type);
    }

    @Override
    public List<FireFightingSystemTypeTreeVo> systemTypeTree(String bizOrgCode) {
        // 获取所有系统分类list
        LambdaQueryWrapper<DynamicFormGroup> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DynamicFormGroup::getGroupType, "fireSystem");
        wrapper.eq(DynamicFormGroup::getParentId, 0);
        List<DynamicFormGroup> list = iEqDynamicFormGroupService.list(wrapper);
        List<Map<String, Object>> typeList = fireFightingSystemMapper.listByBizOrgCode(bizOrgCode);
        List<FireFightingSystemTypeTreeVo> childrenList = list.stream().map(item -> {
            FireFightingSystemTypeTreeVo vo = new FireFightingSystemTypeTreeVo();
            vo.setName(item.getGroupName());
            typeList.forEach(obj -> {
                if (item.getId().equals(Long.valueOf(obj.get("typeId").toString()))) {
                    vo.setTotal(obj.get("total").toString());
                }
            });
            vo.setType(item.getGroupType());
            vo.setId(String.valueOf(item.getId()));
            return vo;
        }).collect(Collectors.toList());
        // 计算总数
        long total = typeList.stream().mapToLong(o -> {
            if (!ObjectUtils.isEmpty(o.get("total"))) {
                return (long) o.get("total");
            }
            return 0;
        }).sum();
        // 自定义根节点返回树
        FireFightingSystemTypeTreeVo parentNode = new FireFightingSystemTypeTreeVo();
        parentNode.setType("all");
        parentNode.setName("全部分类");
        parentNode.setId("-1");
        parentNode.setParentId("-1");
        parentNode.setTotal(String.valueOf(total));
        parentNode.setChildren(childrenList);
        return Collections.singletonList(parentNode);
    }

    @Override
    public Object getEquipmentTypeAndCount(String bizOrgCode) {
//        if (redisUtils.hasKey(equipTypeAndCount + bizOrgCode)) {
//            return JSONArray.parseArray(
//                    JSONArray.toJSONString(redisUtils.get(equipTypeAndCount + bizOrgCode)), EquipmentCategory.class);
//        } else {
            return refreshEquipmentTypeAndCount(bizOrgCode);
       // }
    }

    @Override
    public Object refreshEquipmentTypeAndCount(String bizOrgCode) {
        List<EquipmentCategory> responseList = this.typeList();
        if (responseList == null || responseList.size() < 1) {
            return null;
        }
        List<EquipmentCategory> equipmentTypeList = responseList.stream()
                .filter(i -> !i.getCode().startsWith("2")  && "2".equals(i.getIndustryCode()))
                .filter(m->!m.getCode().startsWith("9306") && "2".equals(m.getIndustryCode()))
                .collect(Collectors.toList());
        List<EquipmentCategory> list = typeListTree(equipmentTypeList, bizOrgCode, SourceTypeEnum.EQUIPMENT);
        redisUtils.set(equipTypeAndCount + bizOrgCode, list, 86400);
        return list;
    }

    @Override
    public Object getCarTypeAndCount(String bizOrgCode) {
        if (redisUtils.hasKey(carTypeAndCount + bizOrgCode)) {
            return JSONArray.parseArray(
                    JSONArray.toJSONString(redisUtils.get(carTypeAndCount + bizOrgCode)), EquipmentCategory.class);
        } else {
            return refreshCarTypeAndCount(bizOrgCode);
        }
    }

    @Override
    public Object iotgetEquipmentTypeAndCount(String bizOrgCode) throws Exception {
        if (redisUtils.hasKey("iotTypeAndCount" + bizOrgCode)) {
            return JSONArray.parseArray(
                    JSONArray.toJSONString(redisUtils.get("iotTypeAndCount" + bizOrgCode)), EquipmentCategory.class);
        } else {
            return iotrefreshEquipmentTypeAndCount(bizOrgCode);
        }
    }

    public Object iotrefreshEquipmentTypeAndCount(String bizOrgCode) {
//        List<EquipmentCategory> responseList = this.typeList();
//        if (responseList == null || responseList.size() < 1) {
//            return null;
//        }
//        List<EquipmentCategory> list = typeListTree(responseList, bizOrgCode, SourceTypeEnum.IOT);


        List<EquipmentCategory> responseList = this.typeList();
        if (responseList == null || responseList.size() < 1) {
            return null;
        }
        List<EquipmentCategory> equipmentTypeList = responseList.stream()
                .filter(i -> !i.getCode().startsWith("2") && "2".equals(i.getIndustryCode()))
                .collect(Collectors.toList());
        List<EquipmentCategory> list = typeListTree(equipmentTypeList, bizOrgCode, SourceTypeEnum.IOT);
        redisUtils.set("iotTypeAndCount" + bizOrgCode, list, 86400);
        return list;
    }

    @Override
    public Object refreshCarTypeAndCount(String bizOrgCode) {
        List<EquipmentCategory> responseList = this.typeList();
        if (responseList == null || responseList.size() < 1) {
            return null;
        }
        List<EquipmentCategory> equipmentTypeList = responseList.stream()
                .filter(i -> i.getCode().startsWith("2") && "2".equals(i.getIndustryCode()))
                .collect(Collectors.toList());
        List<EquipmentCategory> list = typeListTree(equipmentTypeList, bizOrgCode, SourceTypeEnum.CAR);
        redisUtils.set(carTypeAndCount + bizOrgCode, list);
        return list;
    }


    public List<EquipmentCategory> typeList() {
        return this.iEquipmentCategoryService
                .getEquipmentCategoryList(Integer.valueOf(equipmentCategoryLeftTypeCode));
    }

    public List<EquipmentCategory> typeListTree(List<EquipmentCategory> equipmentCategorys, String bizOrgCode,
                                                SourceTypeEnum sourceTypeEnum) {
        List<EquipmentCategory> list = new ArrayList<>();
        Map<String, List<EquipmentCategory>> tmpMap = new HashMap<String, List<EquipmentCategory>>();
        equipmentCategorys.forEach(action -> {
            int num = sourceStatistics.equipCategoryStatistics(bizOrgCode, sourceTypeEnum, action.getCode());
            action.setCount(Double.parseDouble(num + ""));
            if (action.getParentId() == null) {
                list.add(action);
            } else {
                if (tmpMap.get(action.getParentId().toString()) == null) {
                    ArrayList<EquipmentCategory> tmplist = new ArrayList<EquipmentCategory>();
                    tmplist.add(action);
                    tmpMap.put(action.getParentId().toString(), tmplist);
                } else {
                    if (!tmpMap.get(action.getParentId().toString()).contains(action)) {
                        tmpMap.get(action.getParentId().toString()).add(action);
                    }
                }
            }
        });
        getChildren(list, tmpMap);
        return list;
    }

    private void getChildren(List<EquipmentCategory> list, Map<String, List<EquipmentCategory>> tmpMap) {
        for (EquipmentCategory equipmentCategory : list) {
            if (tmpMap.get(equipmentCategory.getId().toString()) != null
                    && tmpMap.get(equipmentCategory.getId().toString()).size() > 0) {
                List<EquipmentCategory> equipcliss = tmpMap.get(equipmentCategory.getId().toString());
                equipmentCategory.setHasLowerClassification(true);
                equipmentCategory.setChildren(equipcliss);
                getChildren(equipcliss, tmpMap);
            }
        }
    }

    @Override
    public List<FireFightingSystemEntity> systemListByBziOrgCode(String bizOrgCode) {
        LambdaQueryWrapper<FireFightingSystemEntity> wrapper = new LambdaQueryWrapper<>();
        if (StringUtil.isNotEmpty(bizOrgCode)) {
            wrapper.likeRight(FireFightingSystemEntity::getBizOrgCode, bizOrgCode);
        }
        return this.baseMapper.selectList(wrapper);
    }
}
