package com.persagy.proxy.report.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.persagy.dmp.basic.model.QueryCriteria;
import com.persagy.proxy.adm.constant.AdmDictCategoryEnum;
import com.persagy.proxy.adm.request.AdmQueryCriteria;
import com.persagy.proxy.adm.request.AdmResponse;
import com.persagy.proxy.dictionary.service.impl.AbstractAdmDictBaseServiceImpl;
import com.persagy.proxy.common.entity.InstanceUrlParam;
import com.persagy.proxy.dictionary.model.AdmObjectType;
import com.persagy.proxy.object.model.AdmBuilding;
import com.persagy.proxy.object.model.AdmEquipment;
import com.persagy.proxy.object.model.AdmFloor;
import com.persagy.proxy.object.model.AdmObjectInfo;
import com.persagy.proxy.object.service.IAdmBuildingService;
import com.persagy.proxy.object.service.IAdmEquipmentService;
import com.persagy.proxy.report.service.IAdmLabslService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @ClassName AdmLabslServiceImpl
 * @Description: 蜡笔森林定制接口
 * @Author linhuili
 * @Date 2021/9/17 20:01
 * @Version V1.0
 **/
@Slf4j
@Service
public class AdmLabslServiceImpl<T> extends AbstractAdmDictBaseServiceImpl<T> implements IAdmLabslService<T> {

    @Autowired
    private IAdmBuildingService buildingService;

    @Autowired
    private IAdmEquipmentService equipmentService;

    /**
     * 查询项目下的设备类型
     * @return
     * @throws Exception
     */
    @Override
    public AdmResponse queryCategory(InstanceUrlParam context , Class<T> clazz) throws Exception {

        List<AdmObjectInfo> result = new ArrayList<>();
        QueryCriteria criteria = new QueryCriteria();
        ObjectNode node = JsonNodeFactory.instance.objectNode();
        //查询所有的专业
        node.put("type",AdmDictCategoryEnum.MAJOR.getValue());
        criteria.setCriteria(node);
        AdmResponse majorResonse = doQueryDictData(context, criteria, clazz);

        if(CollUtil.isNotEmpty(majorResonse.getContent())){
            List<AdmObjectInfo> content = (List<AdmObjectInfo>) majorResonse.getContent();
            result.addAll(content);
        }

        //查询所有的系统，设备类
        ArrayNode arrayNode = node.putObject("objType").putArray("$in");
        arrayNode.add(AdmDictCategoryEnum.SYSTEM.getValue());
        arrayNode.add(AdmDictCategoryEnum.EQUIPMENT.getValue());

        criteria.setCriteria(node);
        AdmResponse equipResponse = doQueryObjectType(context, criteria, clazz);

        if(CollUtil.isNotEmpty(equipResponse.getContent())){
            List<AdmObjectInfo> content = (List<AdmObjectInfo>) equipResponse.getContent();
            result.addAll(content);
        }
        return AdmResponse.success(result);
    }

    /**
     * 查询项目下的空间类型
     * @param context
     * @param clazz
     * @return
     * @throws Exception
     */
    @Override
    public AdmResponse queryZoneType(InstanceUrlParam context, Class<T> clazz) throws Exception {
        QueryCriteria criteria = new QueryCriteria();
        ObjectNode node = JsonNodeFactory.instance.objectNode();

        //查询所有的空间类型
        //List<String> objTypes = new ArrayList<>();
        //objTypes.add(AdmDictCategoryEnum.SPACE.getValue());
        node.put("objType",AdmDictCategoryEnum.SPACE.getValue());
        criteria.setCriteria(node);
        AdmResponse response = doQueryObjectType(context, criteria, clazz);

        List<AdmObjectInfo> content = (List<AdmObjectInfo>) response.getContent();
        response.setContent(content);
        return response;
    }

    /**
     * 查询项目下的建筑楼层
     * @param context
     * @param clazz
     * @return
     * @throws Exception
     */
    @Override
    public AdmResponse queryBuildFloor(InstanceUrlParam context, Class<T> clazz) throws Exception {
        List<AdmBuilding> admBuildings = new ArrayList<>();
        //添加未明确建筑
        AdmBuilding admBuilding = new AdmBuilding();
        admBuilding.setId("bisnull");
        admBuilding.setName("未明确建筑");
        admBuilding.setLocalName("未明确建筑");
        admBuildings.add(admBuilding);

        //添加未明确楼层
        ArrayList<AdmFloor> admFloors = new ArrayList<>();
        AdmFloor admFloor = new AdmFloor();
        admFloor.setId("fisnull");
        admFloor.setName("未明确楼层");
        admFloor.setLocalName("未明确楼层");
        admFloors.add(admFloor);

        //获取项目下的建筑，建筑下的楼层
        AdmQueryCriteria request = new AdmQueryCriteria();
        request.setName(AdmBuilding.OBJ_TYPE);

        //设置建筑->楼层级联查询参数
        AdmQueryCriteria cascade = new AdmQueryCriteria();
        cascade.setName(AdmFloor.OBJ_TYPE);
        List<AdmQueryCriteria> cascadeList = new ArrayList<>();
        cascadeList.add(cascade);
        request.setCascade(cascadeList);

        AdmResponse buildResponse = buildingService.doQuery(context, request, AdmBuilding.class);
        if(CollUtil.isEmpty(buildResponse.getContent())){
            return AdmResponse.success(admBuildings);
        }

        //建筑下的楼层添加默认"未明确楼层"
        List<AdmBuilding> buildContent = (List<AdmBuilding>)buildResponse.getContent();
        if(CollUtil.isNotEmpty(buildContent)){
            admBuildings.addAll(buildContent);
        }
        for (AdmBuilding building : admBuildings) {
            if("未明确建筑".equals(building.getName())){
                continue;
            }
            List<AdmFloor> floorList = new ArrayList<>();
            floorList.add(admFloor);
            List<AdmFloor> floor = building.getFloor();
            if(CollUtil.isNotEmpty(floor)){
                List<AdmFloor> sortFloor = floor.stream().sorted(Comparator.comparing(AdmFloor::getFloorSequenceID).reversed()).collect(Collectors.toList());
                floorList.addAll(sortFloor);
            }
            building.setFloor(floorList);
        }
        return AdmResponse.success(admBuildings);
    }

    /**
     * 根据设备id统计设备所属的专业
     * @param context
     * @param ids
     * @param clazz
     * @return
     * @throws Exception
     */
    @Override
    public AdmResponse queryMajorCategory(InstanceUrlParam context, List<String> ids, Class<T> clazz) throws Exception {

        //根据id查询对应的设备类型
        AdmQueryCriteria request = new AdmQueryCriteria();
        request.setName(AdmEquipment.OBJ_TYPE);

        StringBuilder stringBuilder = new StringBuilder();
        ids.stream().forEach(item -> {
            stringBuilder.append("'").append(item).append("'").append(",");
        });
        String filters = StrUtil.sub(stringBuilder.toString(),0, -1);
        request.setFilters("id in ["+filters+"]");
        AdmResponse equipResponse = equipmentService.query(request);
        if(CollUtil.isEmpty(equipResponse.getContent())){
            log.info("设备不存在");
            return AdmResponse.success(new ArrayList<>());

        }
        List<AdmEquipment> equipments = (List<AdmEquipment>)equipResponse.getContent();
        Set<String> classCodes = equipments.stream().map(k -> k.getClassCode()).collect(Collectors.toSet());

        //根据设备类型查询设备所属专业
        QueryCriteria dictCriteria = new QueryCriteria();
        ObjectNode node = JsonNodeFactory.instance.objectNode();
        ArrayNode array = node.putObject("code").putArray("$in");
        classCodes.forEach(code -> array.add(code));

        dictCriteria.setCriteria(node);
        AdmResponse dictResponse = doQueryObjectType(context, dictCriteria, clazz);
        if(CollUtil.isEmpty(dictResponse.getContent())){
            log.info("项目下没有设备类型");
            return AdmResponse.success(new ArrayList<>());
        }

        //获取设备类对应的专业编码
        List<AdmObjectType> classCodeList = (List<AdmObjectType>)dictResponse.getContent();
        Map<String, List<AdmObjectType>> classCodeMap = classCodeList.stream().collect(Collectors.groupingBy(k->k.getMajorCode()));

        Set<String> majors = classCodeList.stream().map(k -> k.getMajorCode()).collect(Collectors.toSet());
        if(CollUtil.isEmpty(majors)){
            return AdmResponse.success(new ArrayList<>());
        }

        //查询字典中的专业
        QueryCriteria criteria = new QueryCriteria();
        ObjectNode majorNode = JsonNodeFactory.instance.objectNode();
        majorNode.put("type",AdmDictCategoryEnum.MAJOR.getValue());
        criteria.setCriteria(majorNode);
        AdmResponse majorResonse = doQueryDictData(context, criteria, clazz);
        List<AdmObjectType> dictMajorList = (List<AdmObjectType>)majorResonse.getContent();
        Map<String, List<AdmObjectType>> dictMajorMap = dictMajorList.stream().collect(Collectors.groupingBy(k->k.getCode()));

        List<AdmObjectType> result = new ArrayList<>();
        //组装成专业-设备类返回结果
        for (String major : majors) {
            List<AdmObjectType> objectTypes = dictMajorMap.get(major);
            if(CollUtil.isNotEmpty(objectTypes)){
                AdmObjectType objectType = objectTypes.get(0);
                objectType.setChildren(classCodeMap.get(major));
                result.add(objectType);
            }
        }
        return AdmResponse.success(result);
    }

}
