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.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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.systemctl.model.DictionarieValueModel;
import com.yeejoin.equipmanage.common.entity.Equipment;
import com.yeejoin.equipmanage.common.entity.EquipmentCategory;
import com.yeejoin.equipmanage.common.entity.EquipmentSpecificIndex;
import com.yeejoin.equipmanage.common.entity.RiskSourceScene;
import com.yeejoin.equipmanage.common.entity.publics.BaseEntity;
import com.yeejoin.equipmanage.common.entity.publics.CommonResponse;
import com.yeejoin.equipmanage.common.entity.vo.*;
import com.yeejoin.equipmanage.common.enums.EquipmentRiskTypeEnum;
import com.yeejoin.equipmanage.common.enums.TrueOrFalseEnum;
import com.yeejoin.equipmanage.common.exception.CommonException;
import com.yeejoin.equipmanage.common.exception.errorEnum.CommonErrorEnum;
import com.yeejoin.equipmanage.common.response.RiskSourceTreeResponse;
import com.yeejoin.equipmanage.common.utils.EquipmentStateUtil;
import com.yeejoin.equipmanage.common.utils.TreeUtil;
import com.yeejoin.equipmanage.mapper.BuildingMapper;
import com.yeejoin.equipmanage.mapper.EquipmentSpecificMapper;
import com.yeejoin.equipmanage.mapper.RiskSourceSceneMapper;
import com.yeejoin.equipmanage.remote.PrecontrolFeign;
import com.yeejoin.equipmanage.remote.RemoteSecurityService;
import com.yeejoin.equipmanage.remote.RiskModelFeign;
import com.yeejoin.equipmanage.service.IEquipmentCategoryService;
import com.yeejoin.equipmanage.service.IEquipmentDetailService;
import com.yeejoin.equipmanage.service.IEquipmentService;
import com.yeejoin.equipmanage.service.IRiskSourceSceneService;
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.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.foundation.utils.TreeBuilder;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author DELL
 */
@Service
public class RiskSourceSceneServiceImpl extends ServiceImpl<RiskSourceSceneMapper, RiskSourceScene> implements IRiskSourceSceneService {
    @Autowired
    private RiskModelFeign riskModelFeign;
    @Autowired
    private RemoteSecurityService securityService;
    @Autowired
    private IEquipmentCategoryService iEquipmentCategoryService;
    @Lazy
    @Autowired
    private IEquipmentService iEquipmentService;
    @Lazy
    @Autowired
    private IEquipmentDetailService iEquipmentDetailService;
    @Autowired
    private EquipmentSpecificMapper equipmentSpecificMapper;
    @Value("${morphic.projectSeq}")
    private Long projectSeq;
    private List<RiskSourceTreeVO> riskSourceTreeVOs;

    @Value("${equip.scene.detail.url}")
    private String url;

    @Value("${equip.point.equipmentdata.url}")
    private String equipmentdataUrl;

    @Value("${mqtt.scene.host}")
    private String sceneUrl;

    @Value("${equip.point.equipmentdata.topic}")
    private String wsTopic;

    @Autowired
    BuildingMapper buildingMapper;

    @Autowired
    PrecontrolFeign precontrolFeign;

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

    @Override
    public List<RiskSourceTreeResponse> getAreaTree(String orgCode) {
        CommonResponse se = riskModelFeign.getRiskSourceList(orgCode);
        List<Map<String, Object>> list = (List<Map<String, Object>>) se.getDataList();
        List<RiskSourceTreeResponse> responses = new ArrayList<>();
        list.forEach(m -> {
            RiskSourceTreeResponse r = new RiskSourceTreeResponse();
            mapToBean(m, r);
            responses.add(r);
        });
        return transferListToTree(responses);
    }

    @Override
    public List<PointTreeVo> getPointTree(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);
        });
        return transferListToPointTree(responses);
    }

    @Override
    public List<PointTreeVo> getImportantEquip(String orgCode) {
        List<PointTreeVo> allRiskSource = buildingMapper.getBuildList(null,null);

        List<PointTreeVo> treeList = new ArrayList<>();
        List<PointTreeVo> pointData = this.baseMapper.getAllImportantEquip();
        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;
    }

    @Override
    public RiskSourceScene createModel(RiskSourceScene model) {
        ResourceDTO resourceDTO = new ResourceDTO();
        resourceDTO.setSubjectId(projectSeq);
        resourceDTO.setSubjectid(projectSeq);
        resourceDTO.setName(model.getRiskSourceName());
        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);
        dataConfig.put("wsTopic", wsTopic);
        parse.put("dataConfig", dataConfig);
        content = JSONObject.toJSONString(parse);
        resourceDTO.setContent(content);
        ResourceDTO morphic = Morphic.morphicSubjectClient.create(resourceDTO).getResult();
        model.setSceneId(morphic.getId());
        this.save(model);
        return model;
    }

    @Override
    public ResourceDTO updateMorphic(ResourceDTO resourceDTO) {
        try {
            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));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BadRequest("保存画布失败");
        }
        return resourceDTO;
    }

    @Override
    public Object queryDictMap(String dictCode) {
        Map<String, String> dictMap;
        List<DictionarieValueModel> dictModels = securityService.listDictionaryByDictCode(dictCode);
        dictMap = dictModels.stream().collect(Collectors.toMap(DictionarieValueModel::getDictDataKey, DictionarieValueModel::getDictDataDesc));
        return dictMap;
    }

    @Override
    public IPage queryPartListPage(Page page, Long categoryId, String name, String code) {
        //1.查询categoryId对应所有的小类ids
        EquipmentCategory category = iEquipmentCategoryService.getById(categoryId);
        List<Long> ids = new ArrayList<>();
        this.getAllCategory(ids, Collections.singletonList(category));
        //2.按照ids、name及分页条件查询分类下的数据
        List<Equipment> equipmentList = this.getAllEquipment(ids);
        List<Long> equipmentIds = equipmentList.stream().map(BaseEntity::getId).collect(Collectors.toList());
        Map<String, Object> map = new HashMap();
        long size = page.getSize();
        long sPage = (page.getCurrent() - 1) * size;
        map.put("ids", equipmentIds);
        map.put("name", name);
        map.put("code", code);
        map.put("sPage", sPage);
        map.put("size", size);
        List<EquipmentSpecificVo> equipmentSpe = equipmentSpecificMapper.getEquipmentSpe(map);
        int equipmentSpeCount = equipmentSpecificMapper.getEquipmentSpeCount(map);
        page.setRecords(equipmentSpe);
        page.setTotal(equipmentSpeCount);
//        QueryWrapper<EquipmentDetail> wrapper = new QueryWrapper<>();
//        wrapper.in("equipment_id",equipmentIds);
//        if(StringUtil.isNotEmpty(name)){
//            wrapper.like("name",name);
//        }
//        if(StringUtil.isNotEmpty(code)){
//            wrapper.like("code",code);
//        }
//        return iEquipmentDetailService.page(page, wrapper);
        return page;
    }

    @Override
    public List queryPartType() {
        String categoryUrl = url;
        List<EquipmentCategory> list = iEquipmentCategoryService.list();
        List<Map> returnList;
        returnList = list.stream().filter(e -> e.getParentId() == null).map(equipmentCategory -> {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("key", equipmentCategory.getId());
            map.put("label", equipmentCategory.getName());
            map.put("url", String.format(categoryUrl, equipmentCategory.getId()));
            return map;
        }).collect(Collectors.toList());
        return returnList;
    }

    @Override
    public RiskSourceScene getOneByUniqueKey(Long riskSourceId, String orgCode) {
        LambdaQueryWrapper<RiskSourceScene> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RiskSourceScene::getRiskSourceId, riskSourceId);
        wrapper.eq(RiskSourceScene::getOrgCode, orgCode);
        RiskSourceScene scene = new RiskSourceScene();
        return this.getOne(wrapper) == null ? scene : this.getOne(wrapper);
    }

    @Override
    public List<RiskSourceTreeVO> findRiskSourceTrees(String compCode) {
        return getRiskSourcesTree(this.baseMapper.getRiskSources(compCode));
    }

    @Override
    public List getPersonInfo() {
        FeignClientResult<Page<PersonVo>> pageResult = precontrolFeign.peopleList();
        if(pageResult.getResult() != null){
            return pageResult.getResult().getRecords();
        }
        return new ArrayList();
    }

    @Override
    public List<RiskSourceTreeVO> getFourVideo() {
        return riskSourceTreeVOs;
    }

    @Override
    public Map<String, Object> getSceneData(PointTreeVo vo, String orgCode) {
        Map<String, Object> res = new HashMap<>();
        Long sort = vo.getSort();
        if (sort == null) {
            return res;
        }
        if (sort == 0) {
            this.getSceneList(res, orgCode, vo.getSceneId());
        } else {
            this.getSystemEquList(res, orgCode, vo.getSequenceNbr());
        }
        return res;
    }

    @Override
    public Map<String, Object> getFirstCanvas(String orgCode) {
        String firstCanvas = equipmentSpecificMapper.getFirstCanvas(orgCode);
        List<Long> ids = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        map.put("firstId", firstCanvas);
        map.put("ids", ids);
        return map;
    }

    @Override
    public String getSceneName(String id) {
        return equipmentSpecificMapper.getSceneName(id);
    }

    @Override
    public List<PointTreeVo> getSystemmeanLsit() {
        return equipmentSpecificMapper.getSystemmeanLsit();
    }

    @Override
    public List<Map> getstatus(String sceneId) {
        List<Map> data = new ArrayList<>();
        List<EquipmentSpecificIndex> equipIndexLatestStatus = new ArrayList<>();
        if(ObjectUtils.isEmpty(sceneId)){
        	equipIndexLatestStatus = equipmentSpecificMapper.getEquipIndexLatestStatus();
        }else{
        	equipIndexLatestStatus = equipmentSpecificMapper.getEquipLatestStatusBySceneId(sceneId);
        }

        equipIndexLatestStatus.forEach(action->{
        	 Map<String, String> map = new HashMap<>();
        	 map.put("equipCode", action.getQrCode());
             map.put("color", EquipmentStateUtil.judgeEquipState(action));
            data.add(map);
        });
        return data;
    }
    @Override
    public  List<Map<String, Object>> getStatusAll(String sceneId) {
        List<Map<String, Object>> data = new ArrayList<>();
        data = equipmentSpecificMapper.getStatusAll(sceneId);

        return data;
    }

    private Map<String, Object> getSystemEquList(Map<String, Object> res, String orgCode, Long id) {
        List<PointTreeVo> list = equipmentSpecificMapper.getSystemEquList(orgCode, id);
        String firstCanvas = equipmentSpecificMapper.getFirstCanvas(orgCode);
        res.put("logicSceneId", firstCanvas);
        res.put("systemSceneId", firstCanvas);
        res.put("filterData", list);
        return res;
    }

    private Map<String, Object> getSceneList(Map<String, Object> res, String orgCode, Long sceneId) {
        List<RiskSourceScene> oneList = new ArrayList<>();
        RiskSourceScene riskSourceScene = new RiskSourceScene();
        riskSourceScene.setSceneId(sceneId);
        riskSourceScene.setRiskSourceName("报警系统逻辑图");
        oneList.add(riskSourceScene);
        QueryWrapper<RiskSourceScene> wrapper = new QueryWrapper<>();
        wrapper.eq("org_code", orgCode);
        wrapper.orderByAsc("risk_source_id");
        List<RiskSourceScene> list = this.list(wrapper);
        oneList.addAll(list);
        res.put("data", oneList);
        return res;
    }

    private List<RiskSourceTreeVO> getRiskSourcesTree(List<RiskSourceTreeVO> list) {
        List<RiskSourceTreeVO> treeList = new ArrayList<>();
        for (RiskSourceTreeVO tree : list) {
            if (tree.getParentId() != null && tree.getParentId() == 0) {
                treeList.add(tree);
            }
            for (RiskSourceTreeVO treeNode : list) {
                if (treeNode.getParentId().longValue() == tree.getId()) {
                    if (tree.getChildren() == null) {
                        tree.setChildren(new ArrayList<>());
                    }
                    tree.getChildren().add(treeNode);
                }
            }
        }
        riskSourceTreeVOs = null;
        for (RiskSourceTreeVO x : treeList) {
            if (x.getChildren() != null) {
                for (RiskSourceTreeVO y : x.getChildren()) {
                    if (y.getChildren() != null) {
                        for (RiskSourceTreeVO z : y.getChildren()) {
                            if (z.getChildren() != null) {
                                for (RiskSourceTreeVO m : z.getChildren()) {
                                    List<RiskSourceTreeVO> list1 = this.baseMapper.getVideo(m.getId());
                                    m.setChildren(this.baseMapper.getVideo(m.getId()));
                                    if (riskSourceTreeVOs == null && list1.size() > 0) {
                                        riskSourceTreeVOs = list1;
                                    }
                                    if (riskSourceTreeVOs.size() < 4 && list1.size() > 0) {
                                        riskSourceTreeVOs.addAll(list1);
                                    }
                                }
                            } else {
                                z.setChildren(this.baseMapper.getVideo(z.getId()));
                            }
                        }
                    } else {
                        y.setChildren(this.baseMapper.getVideo(y.getId()));
                    }
                }
            } else {
                x.setChildren(this.baseMapper.getVideo(x.getId()));
            }
        }
        return treeList;
    }

    private List<RiskSourceTreeResponse> transferListToTree(List<RiskSourceTreeResponse> allRiskSource) {
        List<RiskSourceTreeResponse> treeList = new ArrayList<>();
        List<RiskSourceTreeResponse> regionList = allRiskSource.stream().filter(r -> "TRUE".equals(r.getIsRegion())).collect(Collectors.toList());
        for (RiskSourceTreeResponse tree : regionList) {
            if (tree.getParentId() == 0 || tree.getParentId() == null) {
                treeList.add(tree);
            }
            for (RiskSourceTreeResponse treeNode : regionList) {
                if (treeNode.getParentId().longValue() == tree.getId()) {
                    if (tree.getChildren() == null) {
                        tree.setChildren(new ArrayList<>());
                    }
                    tree.getChildren().add(treeNode);
                }
            }
        }
        return treeList;
    }

    private List<PointTreeVo> transferListToPointTree(List<PointTreeVo> allRiskSource) {
        List<PointTreeVo> treeList = new ArrayList<>();
        List<PointTreeVo> pointData = equipmentSpecificMapper.getPointData();
        if (pointData != null) {
            Map map = null;
            for (PointTreeVo p : pointData) {
                map = new HashMap();
                map.put("imgPath",  p.getImgPath());
                map.put("equipCode", p.getEquipCode());
                map.put("detailApi", equipmentdataUrl + p.getSequenceNbr());
                map.put("equipSyetemId", p.getEquipSyetemId());
                map.put("equipTypeId", p.getEquipId());
                p.setDataConfig(map);
            }
        }
        List<PointTreeVo> regionList = allRiskSource.stream().filter(r -> "TRUE".equals(r.getIsRegion())).collect(Collectors.toList());
        regionList.addAll(pointData);
        for (PointTreeVo tree : regionList) {
            if (tree.getParentId() == null || tree.getParentId() == 0) {
                treeList.add(tree);
            }
            for (PointTreeVo treeNode : regionList) {
                if (tree.getSequenceNbr().equals(treeNode.getParentId())) {
                    if (tree.getChildren() == null) {
                        tree.setChildren(new ArrayList<>());
                    }
                    tree.getChildren().add(treeNode);
                }
            }
        }
        String s = JSONArray.toJSONString(treeList);

        return treeList;
    }

    /**
     * 获取本级及下级分类id
     *
     * @param ids                   返回分类ids
     * @param equipmentCategoryList 分类对象list
     */
    private void getAllCategory(List<Long> ids, List<EquipmentCategory> equipmentCategoryList) {
        //TODO 递归
        for (EquipmentCategory equipmentCategory : equipmentCategoryList) {
            QueryWrapper<EquipmentCategory> wrapper = new QueryWrapper<>();
            wrapper.eq("parent_id", equipmentCategory.getId());
            List<EquipmentCategory> childrenList = iEquipmentCategoryService.list(wrapper);
            ids.add(equipmentCategory.getId());
            if (!CollectionUtils.isEmpty(childrenList)) {
                this.getAllCategory(ids, childrenList);
            }
        }
    }

    private List<Equipment> getAllEquipment(List<Long> ids) {
        QueryWrapper<Equipment> wrapper = new QueryWrapper<>();
        wrapper.in("category_id", ids);
        return iEquipmentService.list(wrapper);
    }

    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<>();

    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Map<String, Object>> queryRiskSourceSecondLevel() {
        // TODO Auto-generated method stub
        return (List<Map<String, Object>>) riskModelFeign.querySecondLevelRiskSource().getDataList();
    }

    @SuppressWarnings("unchecked")
    @Override
    public Map<String, Object> getSafetyIndexInfoByDate() {
        // TODO Auto-generated method stub
        return (Map<String, Object>) riskModelFeign.getSafetyIndexInfoByDate(null).getDataList();
    }

    @Override
    public IPage getEquipBySourceId(Page page, String sourceId, String categoryId, String equipCode, String equipName,String companyId) {
        // 获取sourceId下所有子项
        Long root = 0L;
        if (!ValidationUtil.isEmpty(sourceId) && !"null".equals(sourceId)) {
            try {
                root = Long.valueOf(sourceId);
            } catch (Exception e) {
                throw new CommonException(CommonErrorEnum.PARAM_INVALID);
            }
        }
        List<PageSecurityVideoVO> all = equipmentSpecificMapper.findAllMenuChildren();
        Collection<PageSecurityVideoVO> tree = TreeBuilder.bulid(all, root);
        List<PageSecurityVideoVO> children = TreeUtil.getAllChildren(tree);
        List<Long> idsList = children.stream().map(child -> child.getId()).collect(Collectors.toList());
        idsList.add(root);
        // 获取categoryId下所有子项
        Long categoryRoot = null;
        List<Long> categoryIdList = new ArrayList<>();
        if (!ValidationUtil.isEmpty(categoryId) && !"null".equals(categoryId) && !"null".equals(sourceId)) {
            try {
                categoryRoot = Long.valueOf(categoryId);
            } catch (Exception e) {
                throw new CommonException(CommonErrorEnum.PARAM_INVALID);
            }
            List<EquipmentCategory> categoryList = equipmentCategoryService.getEquipmentCategoryList(Integer.valueOf(equipmentCategoryLeftTypeCode));
            Collection<EquipmentCategory> categorieTree = TreeBuilder.buildByRecursive(categoryList, categoryRoot);
            List<EquipmentCategory> categorieChildren = TreeUtil.getAllChildren(categorieTree);
            categoryIdList = categorieChildren.stream().map(category -> category.getId()).collect(Collectors.toList());
            categoryIdList.add(categoryRoot);
        }
        List<HashMap<String,Object>> equipmentList = equipmentSpecificMapper.getEquipBySourceId(idsList, categoryIdList,equipCode == null ?equipCode:equipCode.replace(" ", ""), equipName == null ? equipName:  equipName .replace(" ", ""),companyId,(page.getCurrent()-1)*page.getSize(),page.getSize());
        int total = equipmentSpecificMapper.getEquipBySourceIdCount(idsList, categoryIdList,equipCode == null ?equipCode:equipCode.replace(" ", ""), equipName == null ? equipName:  equipName .replace(" ", ""),companyId);
        page.setTotal(total);
        page.setRecords(equipmentList);
        return page;
    }
}
