package com.persagy.proxy.object.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.persagy.dmp.common.model.entity.BaseEntity;
import com.persagy.proxy.adm.request.AdmCreateRequest;
import com.persagy.proxy.adm.request.AdmCreateResponse;
import com.persagy.proxy.adm.request.AdmQueryCriteria;
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.adm.utils.ObjectNameUtil;
import com.persagy.proxy.common.entity.DmpResult;
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.model.AdmFloor;
import com.persagy.proxy.object.model.AdmISpace;
import com.persagy.proxy.object.model.AdmSpace;
import com.persagy.proxy.object.service.IAdmEquipmentService;
import com.persagy.proxy.object.service.IAdmFloorService;
import com.persagy.proxy.object.service.IAdmISpaceService;
import com.persagy.proxy.object.service.IAdmSpaceService;
import com.persagy.proxy.object.service.impl.AdmFloorServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
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 java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Adm 楼层 API
 * @author lvxy
 * @date 2021/8/16
 */

@RestController
@RequestMapping("/object/floor")
public class AdmFloorController {
    @Autowired
    private IAdmFloorService service;
    @Autowired
    private IAdmEquipmentService equipmentService;
    @Autowired
    private IAdmISpaceService iAdmISpaceService;
    @Autowired
    private IAdmSpaceService spaceService;
    @Autowired
    private IAdmRelationService relationService;

    /**
     * 创建
     * @param createRequest
     * @return
     * @throws Exception
     */
    @PostMapping("/create")
    public AdmCreateResponse create(@RequestBody AdmCreateRequest<AdmFloor> createRequest) throws Exception {
        List<AdmFloor> vos = createRequest.getContent();
        service.ensureSpecialValues(AdmContextUtil.toDmpContext(), vos, AdmFloorServiceImpl.CREAT_UPDATE);
        for(AdmFloor floor : vos){
            if(StrUtil.isEmpty(floor.getName())){
                floor.setName(ObjectNameUtil.objectName("楼层-"));
            }
            if(floor.getFloorSequenceID() == null){
                return AdmCreateResponse.failure("楼层顺序号不可以为空或类型错误");
            }
        }
        Map<String, AdmFloor> admFloorMap = CollUtil.fieldValueMap(vos, "buildingId");
        if (CollUtil.isNotEmpty(admFloorMap)){
            AdmQueryCriteria admQueryCriteria = new AdmQueryCriteria();
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("buildingId in [");
            admFloorMap.keySet().stream().forEach(buildingId -> {
                stringBuilder.append("'").append(buildingId).append("'").append(",");
            });
            String filters = StrUtil.sub(stringBuilder.toString(),0, -1);
            filters+= "]";
            admQueryCriteria.setFilters(filters);
            admQueryCriteria.setName("floor");
            AdmResponse admResponseF = service.doQuery(AdmContextUtil.toDmpContext(), admQueryCriteria, AdmFloor.class);
            if(DmpResult.SUCCESS.equals(admResponseF.getResult()) && admResponseF.getTotal() > 0){
                List<AdmFloor> vosOld = (List<AdmFloor>) admResponseF.getContent();
                for(AdmFloor admFloorOld : vosOld){
                    if(admFloorMap.containsKey(admFloorOld.getBuildingId())){
                        AdmFloor admFloorNew = admFloorMap.get(admFloorOld.getBuildingId());
                        //楼层序列号相同
                        if(admFloorOld.getFloorSequenceID() !=null && admFloorNew.getFloorSequenceID().equals(admFloorOld.getFloorSequenceID())){
                           return AdmCreateResponse.failure("楼层顺序号不可以重复");
                        }
                    }
                }
            }
        }
        List<AdmFloor> admFloors = service.doInsert(AdmContextUtil.toDmpContext(), AdmFloor.class, createRequest.getContent());
        //更新关系
        //楼层：新增楼层，添加floor和building的关系，如果后期关系计算支持，此部分去掉
        if(CollUtil.isNotEmpty(admFloors)){
            //建筑id一定存在
            String buildingId = vos.get(0).getBuildingId();
            List<RelationDTO> relationDTOS = new ArrayList<>(admFloors.size());
            admFloors.forEach(admFloor -> {
                String floorId = admFloor.getId();
                relationDTOS.add(new RelationDTO(null, "ArchSubset", "Bd2Fl", null, buildingId , floorId));
            });
            relationService.doSave(AdmContextUtil.toDmpContext(), relationDTOS);
        }

        return AdmCreateResponse.success(admFloors);
    }

    /**
     * 根据ID删除
     * @param vos
     * @return
     * @throws Exception
     */
    @PostMapping("/delete")
    public AdmResponse delete( @RequestBody List<AdmFloor> vos) throws Exception {
        String msg = "楼层下包含其他对象实例，请解除关系后删除";
        Map<String, AdmFloor> admFloorMap = CollUtil.fieldValueMap(vos, BaseEntity.PROP_ID);

        AdmQueryCriteria admQueryCriteria = new AdmQueryCriteria();
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("floorId in [");
        admFloorMap.keySet().stream().forEach(buildingId -> {
            stringBuilder.append("'").append(buildingId).append("'").append(",");
        });
        String filters = StrUtil.sub(stringBuilder.toString(),0, -1);
        filters+= "]";

        admQueryCriteria.setFilters(filters);
        admQueryCriteria.setOnlyCount(true);

        admQueryCriteria.setName(AdmSpace.OBJ_TYPE);
        AdmResponse admResponseSpace = spaceService.query(admQueryCriteria);
        if(admResponseSpace.getResult().equals(DmpResult.SUCCESS) && admResponseSpace.getCount() > 0){
            return AdmResponse.failure(msg);
        }
        admQueryCriteria.setName(AdmISpace.OBJ_TYPE);
        AdmResponse admResponseISpace = iAdmISpaceService.doQuery(AdmContextUtil.toDmpContext(), admQueryCriteria, AdmISpace.class);
        if(admResponseISpace.getResult().equals(DmpResult.SUCCESS) && admResponseISpace.getCount() > 0){
            return AdmResponse.failure(msg);
        }
        admQueryCriteria.setName(AdmEquipment.OBJ_TYPE);
        AdmResponse admResponseEuip = equipmentService.query(admQueryCriteria);
        if(admResponseEuip.getResult().equals(DmpResult.SUCCESS) && admResponseEuip.getCount() > 0){
            return AdmResponse.failure(msg);
        }
        service.doDelete(AdmContextUtil.toDmpContext(), vos);
        return AdmResponse.success();
    }

    /**
     * 根据ID删除 - 单条删除
     * @param vos
     * @return
     * @throws Exception
     */
    @PostMapping("/single/delete")
    public AdmResponse deleteSingle( @RequestBody List<AdmFloor> vos) throws Exception {

       return delete(vos);
    }

    /**
     * 更新
     * @param admFloor
     * @return
     * @throws Exception
     */
    @PostMapping("/update")
    public AdmResponse update(@RequestBody AdmCreateRequest<AdmFloor> admFloor) throws Exception {
        List<AdmFloor> vos = CollUtil.newArrayList(admFloor.getContent());
        service.ensureSpecialValues(AdmContextUtil.toDmpContext(), vos, AdmFloorServiceImpl.CREAT_UPDATE);
        /** 遍历楼层列表 */
        Map<String, AdmFloor> admFloorBdMap = CollUtil.fieldValueMap(vos, "buildingId");
        if (CollUtil.isNotEmpty(admFloorBdMap)){
            AdmQueryCriteria admQueryCriteria = new AdmQueryCriteria();
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("buildingId in [");
            admFloorBdMap.keySet().stream().forEach(buildingId -> {
                stringBuilder.append("'").append(buildingId).append("'").append(",");
            });
            String filters = StrUtil.sub(stringBuilder.toString(),0, -1);
            filters+= "]";
            admQueryCriteria.setFilters(filters);
            admQueryCriteria.setName("floor");
            AdmResponse admResponseF = service.query(admQueryCriteria);
            if(DmpResult.SUCCESS.equals(admResponseF.getResult()) && admResponseF.getTotal() > 0 && CollUtil.isNotEmpty(admResponseF.getContent())){
                List<AdmFloor> vosOld = (List<AdmFloor>) admResponseF.getContent();
                for(AdmFloor admFloorOld : vosOld){
                    if(admFloorBdMap.containsKey(admFloorOld.getBuildingId())){
                        AdmFloor admFloorNew = admFloorBdMap.get(admFloorOld.getBuildingId());
                        //楼层序列号相同
                        if(admFloorOld.getFloorSequenceID()!=null && admFloorNew.getFloorSequenceID()!= null && !admFloorOld.getId().equals(admFloorNew.getId()) && admFloorNew.getFloorSequenceID().equals(admFloorOld.getFloorSequenceID())){
                            return AdmResponse.failure("楼层顺序号不可以重复");
                        }
                    }
                }
            }
        }
        vos = service.doUpdate(AdmContextUtil.toDmpContext(), AdmFloor.class, vos);
        return AdmResponse.success(vos);
    }

    /**
     * 更新 outline
     * TODO 暂时不知道具体的参数，先做所有字段的更新，之后有具体场景再做细化
     * @param admFloor
     * @return
     * @throws Exception
     */
    @PostMapping("/update-outline")
    public AdmResponse updateOutline(@RequestBody AdmCreateRequest<AdmFloor> admFloor) throws Exception {
        // 组装上下文条件
        AdmResponse admResponse = update(admFloor);

        InstanceUrlParam context = AdmContextUtil.toDmpContext();

        /** 处理关系标记 */
        service.processRelationType(context,(List<AdmFloor>) admResponse.getContent());
        return admResponse;
    }


    /**
     * 查询
     * 
     * @param request
     * @return
     * @throws Exception
     */
    @PostMapping("/query")
    public AdmResponse query(@RequestBody AdmQueryCriteria request) throws Exception {
        request.setName(AdmFloor.OBJ_TYPE);
        return service.query(request);
    }


    /**
     * 查询
     * 
     * @param request
     * @return
     * @throws Exception
     */
    @PostMapping("/query-outline")
    public AdmResponse queryOutline(@RequestBody AdmQueryCriteria request) throws Exception {
        request.setName(AdmFloor.OBJ_TYPE);
        return service.doQueryOutLine(AdmContextUtil.toDmpContext(), request, AdmFloor.class);
    }

}
