package com.persagy.dmp.rwd.digital.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.persagy.dmp.basic.dto.RequestData;
import com.persagy.dmp.basic.model.QueryCriteria;
import com.persagy.dmp.basic.model.QueryOperator;
import com.persagy.dmp.basic.utils.JsonNodeUtils;
import com.persagy.dmp.basic.utils.QueryCriteriaHelper;
import com.persagy.dmp.basic.validations.QueryClassCodeVadition;
import com.persagy.dmp.basic.validations.QueryFloorIdVadition;
import com.persagy.dmp.basic.validations.QuerySpaceIdVadition;
import com.persagy.dmp.basic.validations.QuerySystemIdVadition;
import com.persagy.dmp.common.constant.CommonConstant;
import com.persagy.dmp.common.constant.ResponseCode;
import com.persagy.dmp.common.context.AppContext;
import com.persagy.dmp.common.exception.BusinessException;
import com.persagy.dmp.common.model.response.CommonResult;
import com.persagy.dmp.common.utils.JsonHelper;
import com.persagy.dmp.common.utils.ParamCheckUtil;
import com.persagy.dmp.common.utils.ResultHelper;
import com.persagy.dmp.digital.entity.ObjectDigital;
import com.persagy.dmp.digital.entity.ObjectRelation;
import com.persagy.dmp.rwd.basic.constant.DigitalObjectType;
import com.persagy.dmp.rwd.basic.constant.DigitalRelCode;
import com.persagy.dmp.rwd.digital.service.IObjectDigitalService;
import com.persagy.dmp.rwd.digital.service.ProjectBusinessService;
import com.persagy.dmp.rwd.digital.utils.ObjectDigitalCriteriaHelper;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 对象数据 Controller
 * @author Charlie Yu
 * @date 2021-07-08
 */
@RestController
@RequestMapping("/rwd/instance/object")
public class ObjectDigitalController{

    @Autowired
    private IObjectDigitalService service;
    @Autowired
    private ProjectBusinessService projectBusinessService;

    @PostMapping("/query")
    @Deprecated
    public CommonResult<List<ObjectNode>> query(@RequestBody QueryCriteria criteria) throws IOException {
        if(criteria == null) {
            throw new BusinessException(ResponseCode.A0400.getCode(), ResponseCode.A0400.getDesc());
        }
        //基础参数校验
        ParamCheckUtil.checkParam(CommonConstant.QUERY_GROUPCODE);
        // 增加判断传值项目id逻辑,2021年9月10日19:15:17
        JsonNode projectNode = criteria.getCriteria().get(RequestData.PROJECT_IDS_HUM);
        if (criteria.getCriteria().has(RequestData.PROJECT_IDS_HUM)){
            criteria.getCriteria().remove(RequestData.PROJECT_IDS_HUM);
        }
        QueryWrapper<ObjectDigital> wrapper = new QueryWrapper<>();
        // 添加所属项目条件
        // ConditionUtil.ensureProjectCriteriaDirectly(wrapper);
        String projectId = AppContext.getContext().getProjectId();
        if (null!=projectNode && projectNode.isArray()){
            wrapper.in(StrUtil.toUnderlineCase(AppContext.PROJECT_ID), JsonHelper.toMultiEntity(projectNode,String.class));
        }else {
            wrapper.eq(StrUtil.isNotBlank(projectId), StrUtil.toUnderlineCase(AppContext.PROJECT_ID), projectId);
        }
        // 处理扩展条件
        ObjectDigitalCriteriaHelper.presetDigitalCriteria(criteria);
        // 转换查询条件
        QueryCriteriaHelper.toWrapper(wrapper, criteria, ObjectDigital.class);
        Page page = QueryCriteriaHelper.toPage(criteria);
        if(criteria.isOnlyCount()) {
            Integer total = service.queryCount(wrapper);
            page.setTotal(total);
        } else {
            page = service.queryByCondition(QueryCriteriaHelper.toPage(criteria), wrapper);
        }
        // 处理扩展属性
        List<ObjectNode> records = JsonNodeUtils.toListNode(page.getRecords(), ObjectDigital.EXTRA_COLUMN, criteria.getWithColumns());
        return ResultHelper.multi(records, page.getTotal());
    }

    @PostMapping("/createOne")
    @Deprecated
    public CommonResult<ObjectDigital> create(@RequestBody ObjectNode node){
        //基础参数校验
        ParamCheckUtil.checkParam(CommonConstant.QUERY_GROUPCODE,CommonConstant.QUERY_PROJECTID);
        ObjectDigital vo = JsonNodeUtils.toEntity(node, ObjectDigital.class, ObjectDigital.EXTRA_COLUMN);
        List<ObjectDigital> voList = CollUtil.newArrayList(vo);
        //创建默认条件
        createDefaultValue(voList);
        //新增对象信息
        service.insert(voList);
        return ResultHelper.single(vo);
    }

    @PostMapping("/create")
    @Deprecated
    public CommonResult<List<ObjectDigital>> createBatch(@RequestBody ArrayNode array){
        //基础参数校验
        ParamCheckUtil.checkParam(CommonConstant.QUERY_GROUPCODE,CommonConstant.QUERY_PROJECTID);
        //创建对象入参校验
        createInstanceParamVerify(array);

        List<ObjectDigital> voList = JsonNodeUtils.toEntity(array, ObjectDigital.class, ObjectDigital.EXTRA_COLUMN);
        //创建默认条件
        createDefaultValue(voList);
        //批量新增对象信息
        voList = service.insert(voList);
        return ResultHelper.multi(voList);
    }

    @PostMapping("/updateOne")
    @Deprecated
    public CommonResult<ObjectDigital> update(@Valid @RequestBody ObjectNode node){
        //基础参数校验
        ParamCheckUtil.checkParam(CommonConstant.QUERY_GROUPCODE,CommonConstant.QUERY_PROJECTID);
        ObjectDigital vo = JsonNodeUtils.toEntity(node, ObjectDigital.class, ObjectDigital.EXTRA_COLUMN);
        List<ObjectDigital> voList = CollUtil.newArrayList(vo);
        //创建默认条件
        createDefaultValue(voList);
        //修改对象信息
        service.update(voList);
        return ResultHelper.single(vo);
    }

    @PostMapping("/update")
    @Deprecated
    public CommonResult<List<ObjectDigital>> updateBatch(@Valid @RequestBody ArrayNode array){
        //基础参数校验
        ParamCheckUtil.checkParam(CommonConstant.QUERY_GROUPCODE,CommonConstant.QUERY_PROJECTID);
        //修改对象入参校验
        updateInstanceParamVerify(array);

        List<ObjectDigital> voList = JsonNodeUtils.toEntity(array, ObjectDigital.class, ObjectDigital.EXTRA_COLUMN);
        //创建默认条件
        createDefaultValue(voList);
        //批量修改对象信息
        voList = service.update(voList);
        return ResultHelper.multi(voList);
    }
    /***
     * Description: 根据对象id批量更新对象的classCode
     * @param objectDigitals : 对象数组
     * @return : com.persagy.dmp.common.model.response.CommonResult<java.util.List<com.persagy.dmp.digital.entity.ObjectDigital>>
     * @author : lijie
     * @date :2021/9/27 17:46
     * Update By lijie 2021/9/27 17:46
     */
    @PostMapping("/batchUpdateClassCodesByIds")
    @Deprecated
    public CommonResult<List<ObjectDigital>> batchUpdateClassCodesByIds(@Valid @RequestBody List<ObjectDigital> objectDigitals){
        // 1.基础参数校验
        ParamCheckUtil.checkParam(CommonConstant.QUERY_GROUPCODE);
        if (CollUtil.isEmpty(objectDigitals)){
            return ResultHelper.multi(new ArrayList<>());
        }
        return service.batchUpdateClassCodesByIds(objectDigitals);
    }

    @PostMapping("/deleteOne")
    @Deprecated
    public CommonResult delete(@RequestBody String id){
        if(StringUtils.isEmpty(id)){
            throw new BusinessException(ResponseCode.A0400.getCode(), "id不能为空");
        }
        service.delete(CollUtil.newArrayList(id));
        return ResultHelper.success();
    }

    @PostMapping("/delete")
    @Deprecated
    public CommonResult deleteBatch(@RequestBody List<String> ids){
        if(ids == null || ids.size()<=0){
            throw new BusinessException(ResponseCode.A0400.getCode(), "id不能为空");
        }
        service.delete(ids);
        return ResultHelper.success();
    }
    /***
     * Description: 根据项目id集合批量查询项目信息
     * @param idList : 项目id集合
     * @return : com.persagy.dmp.common.model.response.CommonResult<com.fasterxml.jackson.databind.node.ObjectNode>
     * @author : lijie
     * @date :2021/8/18 15:55
     * Update By lijie 2021/8/18 15:55
     */
    @PostMapping("/batchQueryProjectByIds")
    public CommonResult<List<ObjectDigital>> batchQueryProjectByIds(@RequestBody List<String> idList) {
        //基础参数校验
        ParamCheckUtil.checkParam(CommonConstant.QUERY_GROUPCODE);
        return projectBusinessService.batchQueryProjectByIds(idList);
    }
    /***
     * Description: 根据管理分区id批量查询项目信息
     * @param requestData : 请求参数
     * @return : com.persagy.dmp.common.model.response.CommonResult<com.fasterxml.jackson.databind.node.ObjectNode>
     * @author : lijie
     * @date :2021/8/18 15:55
     * Update By lijie 2021/8/18 15:55
     */
    @PostMapping("/batchQueryProjectByGroupManageZoneIds")
    public CommonResult<List<ObjectDigital>> batchQueryProjectByGroupManageZoneIds(@RequestBody RequestData requestData) {
        //基础参数校验
        ParamCheckUtil.checkParam(CommonConstant.QUERY_GROUPCODE);
        return projectBusinessService.batchQueryProjectByGroupManageZoneIds(requestData.getGroupManageZoneIds());
    }
    /***
     * Description: 根据上级id查询下级关联对象
     * @param requestData : 请求参数
     * @return : com.persagy.dmp.common.model.response.CommonResult<com.fasterxml.jackson.databind.node.ObjectNode>
     * @author : lijie
     * @date :2021/8/18 15:55
     * Update By lijie 2021/8/18 15:55
     */
    @PostMapping("/queryObjectListSuperiorId")
    public CommonResult<List<ObjectDigital>> queryObjectListSuperiorId(@RequestBody RequestData requestData) {
        //基础参数校验
        ParamCheckUtil.checkParam(CommonConstant.QUERY_GROUPCODE);
        return service.queryObjectListSuperiorId(requestData);
    }

    /***
     * Description: 查询指定楼层下所有指定空间类型的空间
     * @param requestData : 请求参数
     * @return : com.persagy.dmp.common.model.response.CommonResult<java.util.List<com.persagy.dmp.digital.entity.ObjectDigital>>  
     * @author : lijie
     * @date :2021/8/30 9:41
     * Update By lijie 2021/8/30 9:41
     */
    @PostMapping("/querySpaceListByFloorIdAndRoomFuncType")
    public CommonResult<List<ObjectDigital>> querySpaceListByFloorIdAndRoomFuncType(@Validated({QueryFloorIdVadition.class})
                                                                                    @RequestBody RequestData requestData) {
        //基础参数校验
        ParamCheckUtil.checkParam(CommonConstant.QUERY_GROUPCODE);
        requestData.setProjectId(AppContext.getContext().getProjectId());
        requestData.setGroupCode(AppContext.getContext().getGroupCode());
        return service.querySpaceListByFloorIdAndRoomFuncType(requestData);
    }
    /***
     * Description: 查询指定楼层下所有指定空间类型的空间
     * @param requestData : 请求参数
     * @return : com.persagy.dmp.common.model.response.CommonResult<java.util.List<com.persagy.dmp.digital.entity.ObjectDigital>>
     * @author : lijie
     * @date :2021/8/30 9:41
     * Update By lijie 2021/8/30 9:41
     */
    @PostMapping("/queryEquipListBySpaceIdAndClassCode")
    public CommonResult<List<ObjectDigital>> queryEquipListBySpaceIdAndClassCode(@Validated({QuerySpaceIdVadition.class})
                                                                                    @RequestBody RequestData requestData) {
        //基础参数校验
        ParamCheckUtil.checkParam(CommonConstant.QUERY_GROUPCODE);
        requestData.setProjectId(AppContext.getContext().getProjectId());
        requestData.setGroupCode(AppContext.getContext().getGroupCode());
        return service.queryEquipListBySpaceIdAndClassCode(requestData);
    }
    /***
     * Description: 按类型编码查询所有设备
     * @param requestData : 请求参数
     * @return : com.persagy.dmp.common.model.response.CommonResult<java.util.List<com.persagy.dmp.digital.entity.ObjectDigital>>
     * @author : lijie
     * @date :2021/8/30 9:41
     * Update By lijie 2021/8/30 9:41
     */
    @PostMapping("/queryEquipListByClassCode")
    public CommonResult<List<ObjectDigital>> queryEquipListByClassCode(@Validated({QueryClassCodeVadition.class})
                                                                                    @RequestBody RequestData requestData) {
        //基础参数校验
        ParamCheckUtil.checkParam(CommonConstant.QUERY_GROUPCODE);
        requestData.setProjectId(AppContext.getContext().getProjectId());
        requestData.setGroupCode(AppContext.getContext().getGroupCode());
        return service.queryEquipListByClassCode(requestData);
    }
    /***
     * Description: 按系统查询系统下所有设备
     * @param requestData : 请求参数
     * @return : com.persagy.dmp.common.model.response.CommonResult<java.util.List<com.persagy.dmp.digital.entity.ObjectDigital>>
     * @author : lijie
     * @date :2021/8/30 9:41
     * Update By lijie 2021/8/30 9:41
     */
    @PostMapping("/queryEquipListBySystemId")
    public CommonResult<List<ObjectDigital>> queryEquipListBySystemId(@Validated({QuerySystemIdVadition.class})
                                                                                    @RequestBody RequestData requestData) {
        //基础参数校验
        ParamCheckUtil.checkParam(CommonConstant.QUERY_GROUPCODE);
        requestData.setProjectId(AppContext.getContext().getProjectId());
        requestData.setGroupCode(AppContext.getContext().getGroupCode());
        return service.queryEquipListBySystemId(requestData);
    }
    /***
     * Description: 按系统查询系统下所有设备
     * @param requestData : 请求参数
     * @return : com.persagy.dmp.common.model.response.CommonResult<java.util.List<com.persagy.dmp.digital.entity.ObjectDigital>>
     * @author : lijie
     * @date :2021/8/30 9:41
     * Update By lijie 2021/8/30 9:41
     */
    @PostMapping("/queryEquipListByConditions")
    public CommonResult<List<ObjectNode>> queryEquipListByConditions(@RequestBody RequestData requestData) throws IOException {
        // 暂时先拼接query接口参数进行查询,后续视情况再单独写逻辑
        ObjectMapper objectMapper = JsonHelper.objectMapper;
        QueryCriteria queryCriteria = new QueryCriteria();
        queryCriteria.setOrders(requestData.getOrders());
        queryCriteria.setPage(requestData.getPage());
        queryCriteria.setSize(requestData.getSize());
        ObjectNode objectNode = objectMapper.createObjectNode();
        // 专业,系统类,设备类
        if (StrUtil.isNotBlank(requestData.getClassCode())){
            ObjectNode classCodeObj = objectMapper.createObjectNode();
            classCodeObj.put(QueryOperator.LIKE_RIGHT.getIndex(),requestData.getClassCode());
            objectNode.set(ObjectDigital.CLASS_CODE_HUM,classCodeObj);
        }
        // 楼层id
        if (StrUtil.isNotBlank(requestData.getFloorId())){
            // criteria条件
            ObjectNode criteriaObj = objectMapper.createObjectNode();
            criteriaObj.put(ObjectRelation.REL_CODE_HUM, DigitalRelCode.EQ_2_FL.getIndex());
            criteriaObj.put(ObjectRelation.OBJ_TO_HUM, requestData.getFloorId());
            objectNode.set(ObjectRelation.RELATION_FROM_HUM,criteriaObj);
        }
        // 系统id
        if (StrUtil.isNotBlank(requestData.getSystemId())){
            // criteria条件
            ObjectNode criteriaObj = objectMapper.createObjectNode();
            criteriaObj.put(ObjectRelation.REL_CODE_HUM, DigitalRelCode.SY_2_EQ.getIndex());
            criteriaObj.put(ObjectRelation.OBJ_FROM_HUM, requestData.getFloorId());
            objectNode.set(ObjectRelation.RELATION_TO_HUM,criteriaObj);
        }
        // installLocation安装位置
        if (StrUtil.isNotBlank(requestData.getInstallLocation())){
            objectNode.put(RequestData.INSTALL_LOCATION_HUM,requestData.getInstallLocation());
        }
        // manufacturer生产厂家
        if (StrUtil.isNotBlank(requestData.getManufacturer())){
            objectNode.put(RequestData.MANUFACTURER,requestData.getManufacturer());
        }
        // equipStatus设备状态
        if (StrUtil.isNotBlank(requestData.getEquipStatus())){
            objectNode.put(RequestData.EQUIP_STATUS_HUM,requestData.getEquipStatus());
        }
        // warranter维保单位名称
        if (StrUtil.isNotBlank(requestData.getWarranter())){
            objectNode.put(RequestData.WARRANTER,requestData.getWarranter());
        }
        // keyword关键字
        if (StrUtil.isNotBlank(requestData.getKeyword())){
            ObjectNode keywordObj = objectMapper.createObjectNode();
            keywordObj.put(QueryOperator.LIKE.getIndex(),requestData.getKeyword());
            objectNode.set(ObjectDigital.LOCAL_NAME_HUM,keywordObj);
        }
        // 传值数组
        if (CollUtil.isNotEmpty(requestData.getProjectIds())){
            ArrayNode projectIdsNode = objectNode.putArray(RequestData.PROJECT_IDS_HUM);
            requestData.getProjectIds().forEach(projectIdsNode::add);
        }
        objectNode.put(ObjectDigital.OBJ_TYPE_HUM, DigitalObjectType.EQUIPMENT.getIndex());
        objectNode.put(ObjectDigital.PROP_VALID,Boolean.TRUE);
        queryCriteria.setCriteria(objectNode);
        return query(queryCriteria);
    }
    /***
     * Description: 支持按指定空间功能类型查询此空间类型及其下级类型的所有空间列表
     * @param requestData : 请求参数
     * @return : com.persagy.dmp.common.model.response.CommonResult<java.util.List<com.persagy.dmp.digital.entity.ObjectDigital>>
     * @author : lijie
     * @date :2021/8/30 9:41
     * Update By lijie 2021/8/30 9:41
     */
    @PostMapping("/querySpaceListByRoomFuncType")
    public CommonResult<List<ObjectDigital>> querySpaceListByRoomFuncType(@RequestBody RequestData requestData) {
        //基础参数校验
        if (StrUtil.isBlank(requestData.getRoomFuncType())){
            throw new BusinessException(ResponseCode.A0402.getCode(),ResponseCode.A0402.getDesc());
        }
        ParamCheckUtil.checkParam(CommonConstant.QUERY_GROUPCODE);
        requestData.setProjectId(AppContext.getContext().getProjectId());
        requestData.setGroupCode(AppContext.getContext().getGroupCode());
        return service.querySpaceListByRoomFuncType(requestData);
    }
    /***
     * Description: 根据图类型编码及关系类型编码查询对象及其关联对象
     * @param requestData : 请求参数
     * @return : com.persagy.dmp.common.model.response.CommonResult<java.util.List<com.persagy.dmp.digital.entity.ObjectDigital>>
     * @author : lijie
     * @date :2021/8/30 9:41
     * Update By lijie 2021/8/30 9:41
     */
    @PostMapping("/queryObjectListByGraphCodeAndRelCode")
    public CommonResult<List<ObjectDigital>> queryObjectListByGraphCodeAndRelCode(@RequestBody RequestData requestData) {
        //基础参数校验
        if (StrUtil.isBlank(requestData.getGraphCode())
                || StrUtil.isBlank(requestData.getRelCode())){
            throw new BusinessException(ResponseCode.A0402.getCode(),ResponseCode.A0402.getDesc());
        }
        ParamCheckUtil.checkParam(CommonConstant.QUERY_GROUPCODE);
        requestData.setProjectId(AppContext.getContext().getProjectId());
        requestData.setGroupCode(AppContext.getContext().getGroupCode());
        return service.queryObjectListByGraphCodeAndRelCode(requestData);
    }


    /**
     * 创建默认条件
     * @param voList
     */
    private void createDefaultValue(List<ObjectDigital> voList){
        String groupCode = AppContext.getContext().getGroupCode();
        if(StringUtils.isEmpty(groupCode)){
            //默认集团
            groupCode = CommonConstant.DEFAULT_ID;
        }
        String projectId = AppContext.getContext().getProjectId();
        if(StringUtils.isEmpty(projectId)){
            //默认项目
            projectId = CommonConstant.DEFAULT_ID;
        }
        for (ObjectDigital vo : voList) {
            vo.setGroupCode(groupCode);
            vo.setProjectId(projectId);
        }
    }

    /**
     * 创建实例入参校验
     * @param array
     */
    private void createInstanceParamVerify(ArrayNode array){
        if(array == null || array.size()<=0){
            throw new BusinessException(ResponseCode.A0400.getCode(),ResponseCode.A0400.getCode());
        }
        for (JsonNode jsonNode : array) {
            JsonNode name = jsonNode.get("name");
            if(name == null){
                throw new BusinessException(ResponseCode.A0400.getCode(),"对象名称不能为空");
            }
            JsonNode classCode = jsonNode.get("classCode");
            if(classCode == null){
                throw new BusinessException(ResponseCode.A0400.getCode(),"类型编码不能为空");
            }
        }
    }

    /**
     * 修改实例入参校验
     * @param array
     */
    private void updateInstanceParamVerify(ArrayNode array){
        if(array == null || array.size()<=0){
            throw new BusinessException(ResponseCode.A0400.getCode(),ResponseCode.A0400.getCode());
        }
        for (JsonNode jsonNode : array) {
            JsonNode id = jsonNode.get("id");
            if(id == null){
                throw new BusinessException(ResponseCode.A0400.getCode(),"id不能为空");
            }
        }
    }
}
