package com.persagy.proxy.relation.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.netflix.discovery.CommonConstants;
import com.persagy.dmp.basic.model.QueryCriteria;
import com.persagy.dmp.basic.model.QueryOperator;
import com.persagy.dmp.basic.utils.QueryCriteriaHelper;
import com.persagy.dmp.common.constant.CommonConstant;
import com.persagy.dmp.common.context.AppContext;
import com.persagy.dmp.common.helper.SpringHelper;
import com.persagy.dmp.common.model.response.CommonResult;
import com.persagy.dmp.digital.client.DigitalObjectFacade;
import com.persagy.dmp.digital.client.DigitalRelationFacade;
import com.persagy.dmp.digital.entity.ObjectDigital;
import com.persagy.dmp.digital.entity.ObjectRelation;
import com.persagy.proxy.adm.constant.AdmDictCategoryEnum;
import com.persagy.proxy.adm.constant.AdmRelationTypeEnum;
import com.persagy.proxy.adm.request.AdmCreateResponse;
import com.persagy.proxy.adm.request.AdmResponse;
import com.persagy.proxy.adm.service.IAdmRelationService;
import com.persagy.proxy.adm.utils.AdmContextUtil;
import com.persagy.proxy.common.entity.InstanceUrlParam;
import com.persagy.proxy.common.entity.RelationDTO;
import com.persagy.proxy.object.model.AdmEquipment;
import com.persagy.proxy.object.service.IAdmEquipmentService;
import com.persagy.proxy.relation.model.AdmBatchSyEqRequest;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @description:系统下的设备设施
 * @author:lgy
 * @data:2021/9/3 15:25
 */
@RestController
@RequestMapping("/rel/sy-in-eq")
public class RelationSyEqController {

    @Autowired
    private IAdmRelationService service;
    @Autowired
    private IAdmEquipmentService equipmentService;

    /**
     * 创建系统下的设备关系,数据叠加，不会覆盖以前的数据
     * 必填项：EquipID（设备id）、SysID(系统id)
     * @param param
     * @return
     * @throws Exception
     */
    @PostMapping(value = {"/link-sy-eq","/link"})
    public AdmResponse create(@RequestBody JSONObject param) throws Exception {
        //String equipId = param.getString("equipId");
        JSONArray equipIdList = param.getJSONArray("equipIdList");
        String sysID = param.getString("sysId");
        if(StringUtils.isEmpty(sysID) || CollUtil.isEmpty(equipIdList)) {
            return AdmResponse.failure("必填项：EquipIdList（设备id列表）、SysID(系统id)");
        }
        // 创建关系对象
        List<RelationDTO> voList = new ArrayList<>();
        equipIdList.forEach(item->{
            voList.add(new RelationDTO(null, "MechSubset", "Sy2Eq", null, sysID , item.toString()));
        });
        // 组装上下文条件
        InstanceUrlParam context = AdmContextUtil.toDmpContext();
        service.doSave(context, voList);
        return AdmResponse.success();
    }

    /**
     * 根据对象删除系统和设备的关系，只针对一个对象
     *必填项：EquipID（设备id）、SysID(系统id)
     * @param   param      对象
     * @return             删除的结果信息
     */

    @PostMapping("/unlink")
    public AdmResponse delete(@RequestBody JSONObject param) throws Exception {
        if(CollUtil.isEmpty(param)) {
            return AdmResponse.success();
        }
        // 组装上下文条件
        InstanceUrlParam context = AdmContextUtil.toDmpContext();
        // 组装条件
        QueryCriteria criteria = new QueryCriteria();
        String equipId = param.getString("equipId");
        String sysID = param.getString("sysId");
        if(!StrUtil.isAllNotEmpty(equipId,sysID)) {
            return AdmResponse.failure("必填项：EquipID（设备id）、SysID(系统id)");
        }
        ObjectNode node = JsonNodeFactory.instance.objectNode();
        node.put("graphCode", "MechSubset");
        node.put("relCode", "Sy2Eq");
        node.put("objFrom", sysID);
        node.put("objTo", equipId);
        criteria.setCriteria(node);
        service.doDelete(context, criteria);
        return AdmResponse.success();
    }

    /**
     * 创建系统下的设备关系
     *
     * @param   syEqList           系统和设备的关系对象
     * @return                  创建结果信息
     */
    @PostMapping("/link-eq")
    public AdmResponse createBatchWithDeleteOldsysIdRelation(@RequestBody JSONObject syEqList) throws Exception {
        JSONArray equipIdList = syEqList.getJSONArray("equipIdList");
        String sysId = syEqList.getString("sysId");
        if(StrUtil.isBlank(sysId) || CollUtil.isEmpty(equipIdList)) {
            return AdmResponse.failure("必填项：EquipIdList（设备id列表）、SysID(系统id)");
        }
        InstanceUrlParam context =AdmContextUtil.toDmpContext();
        QueryCriteria queryRequest = new QueryCriteria();
        ObjectNode node = JsonNodeFactory.instance.objectNode();
        node.put("graphCode", "MechSubset");
        node.put("relCode", "Sy2Eq");
        node.put("objFrom", sysId);
        queryRequest.setCriteria(node);
        service.doDelete(context,queryRequest);
        // 创建关系对象
        List<RelationDTO> voList = new ArrayList<>();
        for (int i = 0; i < equipIdList.size(); i++) {
            voList.add(new RelationDTO(null, "MechSubset", "Sy2Eq", null, sysId , equipIdList.getString(i)));
        }
        // 组装上下文条件
        service.doSave(context, voList);
        return AdmResponse.success();
    }

    /**
     * 创建系统下的设备关系
     *
     * @param   param           系统和设备的关系对象
     * @return                  创建结果信息
     */
    @PostMapping("/link-sy")
    public AdmResponse createDistinctEq(@RequestBody JSONObject param) throws Exception {
        String equipId = param.getString("equipId");
        JSONArray sysIdList = param.getJSONArray("sysIdList");
        if(StringUtils.isEmpty(equipId)) {
            return AdmResponse.failure("必填项：EquipId（设备id）");
        }
        InstanceUrlParam context = AdmContextUtil.toDmpContext();
        QueryCriteria queryRequest = new QueryCriteria();
        ObjectNode node = JsonNodeFactory.instance.objectNode();
        node.put("graphCode", "MechSubset");
        node.put("relCode", "Sy2Eq");
        node.put("objTo", equipId);
        //删除关系
        queryRequest.setCriteria(node);
        service.doDelete(context,queryRequest);
        if(!CollUtil.isEmpty(sysIdList)){
            // 创建关系对象
            List<RelationDTO> voList = new ArrayList<>();
            sysIdList.forEach(item->{
                voList.add(new RelationDTO(null, "MechSubset", "Sy2Eq", null, item.toString() , equipId));
            });
            // 组装上下文条件
            service.doSave(context, voList);
        }

        return AdmResponse.success();
    }

    /**
     * 根据对象删除系统和设备的关系
     *
     * @param   entytyList           根据对象删除系统和设备的关系
     * @return                  创建结果信息
     */
    @PostMapping("/unlinks-sy-eq")
    public AdmResponse deleteBatch(@RequestBody JSONArray entytyList) {
        if(CollUtil.isEmpty(entytyList)) {
            return AdmResponse.success();
        }
        // 组装上下文条件
        InstanceUrlParam context = AdmContextUtil.toDmpContext();
        // 2021年11月25日14:53:16 优化:by lijie
        Set<String> objFromIds = CollUtil.newHashSet();
        Set<String> objToIds = CollUtil.newHashSet();
        for (int i = 0; i < entytyList.size(); i++) {
            JSONObject entity = entytyList.getJSONObject(i);
            // 组装条件
            String equipId = entity.getString("equipId");
            String sysID = entity.getString("sysId");
            if(!StrUtil.isAllNotEmpty(equipId,sysID)) {
                continue;
            }
            objFromIds.add(sysID);
            objToIds.add(equipId);
        }
        // 2.批量删除关系
        if (CollUtil.isNotEmpty(objFromIds) && CollUtil.isNotEmpty(objToIds)){
            QueryCriteria criteria = new QueryCriteria();
            ObjectNode node = JsonNodeFactory.instance.objectNode();
            node.put(ObjectRelation.GRAPH_CODE_HUM, AdmRelationTypeEnum.EQ2SY.getGraphCode());
            node.put(ObjectRelation.REL_CODE_HUM, AdmRelationTypeEnum.EQ2SY.getRelCode());
            node.putPOJO(ObjectRelation.OBJ_FROM_HUM, objFromIds);
            node.putPOJO(ObjectRelation.OBJ_TO_HUM, objToIds);
            criteria.setCriteria(node);
            service.doDelete(context, criteria);
        }
        return AdmResponse.success();
    }
    /**
     * 根据条件筛选 批量添加关系
     * 建筑和楼层 未明确使用 isnull
     * @param   admBatchSyEqRequest  批量添加系统和设备的关系
     * @return                  创建结果信息
     */
    @PostMapping("/batch/equip")
    public AdmResponse batchAddRels(@RequestBody AdmBatchSyEqRequest admBatchSyEqRequest) {
        if (StrUtil.isBlank(admBatchSyEqRequest.getClassCode())){
            return AdmCreateResponse.failure("设备类型不可以为空");
        }
        if (StrUtil.isBlank(admBatchSyEqRequest.getSysId())){
            return AdmCreateResponse.failure("系统id不可以为空");
        }
        // 1.组装查询条件
        QueryCriteria queryCriteria = new QueryCriteria();
        ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
        ObjectNode objectNode = objectMapper.createObjectNode();
        handleBuildAndFloorQueryParam(objectMapper,objectNode,admBatchSyEqRequest.getBuildingId(),admBatchSyEqRequest.getFloorId());
        objectNode.put(ObjectDigital.CLASS_CODE_HUM,admBatchSyEqRequest.getClassCode());
        objectNode.put(CommonConstant.QUERY_PROJECTID, AppContext.getContext().getProjectId());
        String name = admBatchSyEqRequest.getVague();
        if (StrUtil.isNotBlank(name)){
            ObjectNode localObj = objectMapper.createObjectNode();
            ObjectNode localNameLikeObj = objectMapper.createObjectNode();
            ObjectNode localIdLikeObj = objectMapper.createObjectNode();
            ObjectNode nameLikeObj = objectMapper.createObjectNode();
            ObjectNode digitalDeliveryIdLikeObj = objectMapper.createObjectNode();
            localIdLikeObj.put(QueryOperator.LIKE.getIndex(),name);
            localNameLikeObj.put(QueryOperator.LIKE.getIndex(),name);
            nameLikeObj.put(QueryOperator.LIKE.getIndex(),name);
            digitalDeliveryIdLikeObj.put(QueryOperator.LIKE.getIndex(),name);
            localObj.set("localId",localIdLikeObj);
            localObj.set("localName",localNameLikeObj);
            localObj.set("name",nameLikeObj);
            localObj.set("digitalDeliveryID",digitalDeliveryIdLikeObj);
            objectNode.put(QueryOperator.AND_OR.getIndex(),localObj);
        }
        objectNode.put(ObjectDigital.OBJ_TYPE_HUM, AdmDictCategoryEnum.EQUIPMENT.getValue());
        objectNode.put(ObjectDigital.PROP_VALID,Boolean.TRUE);
        queryCriteria.setCriteria(objectNode);
        // 2.查询设备
        AdmResponse admResponse = equipmentService.doQuery(AdmContextUtil.toDmpContext(), queryCriteria, AdmEquipment.class);
        if (!CommonConstant.QUERY_SUCCESS.equals(admResponse.getResult())){
            return admResponse;
        }
        if (CollUtil.isEmpty(admResponse.getContent())){
            return admResponse;
        }
        List<AdmEquipment> content = (List<AdmEquipment>) admResponse.getContent();
        CommonResult<List<ObjectRelation>> commonResult = queryRelationBySysId(objectMapper, admBatchSyEqRequest.getSysId());
        if (!CommonConstant.QUERY_SUCCESS.equals(commonResult.getResult())){
            return AdmCreateResponse.success(new ArrayList<>());
        }
        List<ObjectRelation> relations = commonResult.getData();
        Set<String> equipIds = CollUtil.newHashSet();
        if (CollUtil.isNotEmpty(relations)){
            equipIds.addAll(relations.stream().map(ObjectRelation::getObjTo).collect(Collectors.toSet()));
        }
        List<ObjectNode> relationList = new ArrayList<>();
        for (AdmEquipment admEquipment : content) {
            if (equipIds.contains(admEquipment.getId())){
                continue;
            }
            ObjectRelation objectRelation = new ObjectRelation();
            objectRelation.setGroupCode(AppContext.getContext().getGroupCode());
            objectRelation.setProjectId(AppContext.getContext().getProjectId());
            objectRelation.setGraphId(StrUtil.format(CommonConstant.DEFAULT_GRAPH_ID_FORMAT,AppContext.getContext().getGroupCode()));
            objectRelation.setGraphCode(AdmRelationTypeEnum.EQ2SY.getGraphCode());
            objectRelation.setRelCode(AdmRelationTypeEnum.EQ2SY.getRelCode());
            objectRelation.setObjFrom(admBatchSyEqRequest.getSysId());
            objectRelation.setObjTo(admEquipment.getId());
            objectRelation.setCreateApp(AppContext.getContext().getAppId());
            objectRelation.setUpdateApp(AppContext.getContext().getAppId());
            objectRelation.setCreator(AppContext.getContext().getAccountId());
            objectRelation.setModifier(AppContext.getContext().getAccountId());
            objectRelation.setValid(1);
            relationList.add(objectMapper.convertValue(objectRelation,ObjectNode.class));
        }
        if (CollUtil.isNotEmpty(relationList)){
            DigitalRelationFacade.create(AppContext.getContext().getGroupCode(),AppContext.getContext().getProjectId(),
                    AppContext.getContext().getAppId(),AppContext.getContext().getAccountId(),relationList);
        }
        return AdmCreateResponse.success(new ArrayList<>());
    }
    /***
     * Description: 查询系统已关联的设备id
     * @param sysId : 系统id
     * @return : java.util.Set<java.lang.String>
     * @author : lijie
     * @date :2021/11/25 12:27
     * Update By lijie 2021/11/25 12:27
     */
    private CommonResult<List<ObjectRelation>> queryRelationBySysId(ObjectMapper objectMapper,String sysId) {
        QueryCriteria queryCriteria = new QueryCriteria();
        ObjectNode objectNode = objectMapper.createObjectNode();
        objectNode.put(ObjectRelation.PROP_VALID,Boolean.TRUE);
        objectNode.put(ObjectRelation.GRAPH_CODE_HUM, AdmRelationTypeEnum.EQ2SY.getGraphCode());
        objectNode.put(ObjectRelation.REL_CODE_HUM, AdmRelationTypeEnum.EQ2SY.getRelCode());
        objectNode.put(ObjectRelation.OBJ_FROM_HUM, sysId);
        queryCriteria.setCriteria(objectNode);
        return DigitalRelationFacade
                .queryPrototype(AppContext.getContext().getGroupCode(), AppContext.getContext().getProjectId(),
                        AppContext.getContext().getAppId(), AppContext.getContext().getAccountId(), queryCriteria);
    }

    /***
     * Description: 处理查询条件
     * @param objectNode : 查询参数
     * @param buildingId : 建筑id
     * @param floorId : 楼层id
     * @return : void
     * @author : lijie
     * @date :2021/11/25 11:44
     * Update By lijie 2021/11/25 11:44
     */
    private void handleBuildAndFloorQueryParam(ObjectMapper objectMapper,ObjectNode objectNode,
                                               String buildingId, String floorId) {
        if (StrUtil.isBlank(buildingId) && StrUtil.isBlank(floorId)){
            return;
        }
        if (StrUtil.isNotBlank(floorId) && !"isnull".equals(floorId)){
            objectNode.put("floorId",floorId);
        }
        if (StrUtil.isNotBlank(buildingId) && !"isnull".equals(buildingId)){
            objectNode.put("buildingId",buildingId);
        }
        if (StrUtil.isNotBlank(buildingId) && "isnull".equals(buildingId)){
            ObjectNode buildObj = objectMapper.createObjectNode();
            buildObj.put(QueryOperator.NULL.getIndex(),Boolean.TRUE);
            objectNode.set("buildingId",buildObj);
        }
        if (StrUtil.isNotBlank(floorId) && "isnull".equals(floorId)){
            ObjectNode floorObj = objectMapper.createObjectNode();
            floorObj.put(QueryOperator.NULL.getIndex(),Boolean.TRUE);
            objectNode.set("floorId",floorObj);
        }
    }

}
