package com.persagy.proxy.object.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.persagy.dmp.common.constant.CommonConstant;
import com.persagy.dmp.common.helper.SpringHelper;
import com.persagy.dmp.digital.client.DigitalRelationFacade;
import com.persagy.proxy.adm.constant.AdmCommonConstant;
import com.persagy.proxy.adm.constant.AdmDictCategoryEnum;
import com.persagy.proxy.adm.constant.GraphCodeEnum;
import com.persagy.proxy.adm.constant.RelCodeEnum;
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.utils.AdmContextUtil;
import com.persagy.proxy.adm.utils.ObjectNameUtil;
import com.persagy.proxy.common.entity.InstanceUrlParam;
import com.persagy.proxy.dictionary.model.AdmDict;
import com.persagy.proxy.dictionary.model.AdmObjectType;
import com.persagy.proxy.dictionary.service.IAdmDictService;
import com.persagy.proxy.object.model.AdmComponent;
import com.persagy.proxy.object.service.IAdmComponentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Adm 部件 API
 * @author lvxy
 * @date 2021/8/16
 */
@Slf4j
@RestController
@RequestMapping("/object/component")
public class AdmComponentController {
    @Autowired
    private IAdmComponentService service;
    @Autowired
    private IAdmDictService dictService;

    /**
     * 统计
     * @param request
     * @return
     * @throws Exception
     */
    @PostMapping("/count")
    public AdmResponse count(@RequestBody AdmQueryCriteria request) throws Exception {
        request.setName(AdmComponent.OBJ_TYPE);
        request.setOnlyCount(true);
        return service.doQuery(AdmContextUtil.toDmpContext(), request, AdmComponent.class);
    }
    /**
     * 创建
     * @param createRequest
     * @return
     * @throws Exception
     */
    @PostMapping("/create")
    public AdmCreateResponse create(@RequestBody AdmCreateRequest<AdmComponent> createRequest,
                                    @RequestParam(value = "projectId",required = false) String projectId) throws Exception {
        List<AdmComponent> vos = CollUtil.newArrayList(createRequest.getContent());
        if(CollUtil.isEmpty(vos)){
            return AdmCreateResponse.success();
        }
        // 查询所有设备类型
        AdmDict dictCond = AdmDict.builder().type(AdmDictCategoryEnum.COMPONENT.getValue()).build();
        AdmResponse dictResponse = dictService.queryCategory(AdmContextUtil.toDmpContext(), dictCond, AdmObjectType.class);
        List<AdmObjectType> dicts = (List<AdmObjectType>) dictResponse.getContent();
        // 转换为Map，key为编码后4位。用于适配旧类型编码
        Map<String, AdmObjectType> shortDictMap = new HashMap<>();
        Map<String, AdmObjectType> fullDictMap = new HashMap<>();
        for(int i = 0,j = CollUtil.size(dicts);i < j;i++) {
            AdmObjectType dict = dicts.get(i);
            shortDictMap.put(StrUtil.subSufByLength(dict.getCode(), 6), dict);
            fullDictMap.put(dict.getCode(), dict);
        }
        // 设备属性调整
        List<AdmComponent> filterVOs = new ArrayList<>();
        List<ObjectNode> relations = new ArrayList<>();
        ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
        InstanceUrlParam context = AdmContextUtil.toDmpContext();
        for(AdmComponent component:vos) {
            // 如果不是Eq开头，则重新生成ID
            if(!StrUtil.startWith(component.getId(), "Ec")) {
                component.setId("Ec"+context.getProjectId().substring(2)+ IdUtil.simpleUUID());
            }
            // 类型编码适配
            String classCode = component.getClassCode();
            // 如果编码为空，或在4位、6位里都不存在，则报错
            if(StrUtil.isBlank(classCode) ||
                    (shortDictMap.get(classCode) == null && fullDictMap.get(classCode) == null)) {
                log.error(StrUtil.format("没有找到对象类型【{}】！", component.getClassCode()));
                continue;
            }
            filterVOs.add(component);
            // 如果少于6位，则需要适配新编码
            if(classCode.length() < 8) {
                AdmObjectType dict = MapUtil.get(shortDictMap, classCode, AdmObjectType.class);
                component.setClassCode(dict.getCode());
            }
            // 如果名称为空，则提供默认名称
            if (StrUtil.isEmpty(component.getName())){
                AdmObjectType dict = MapUtil.get(fullDictMap, component.getClassCode(), AdmObjectType.class);
                String preName = dict == null ? "部件" : dict.getName();
                component.setName(ObjectNameUtil.objectName(preName + "-"));
            }
            // 处理设备与部件的关系
            if (StrUtil.isNotBlank(component.getParentId())
                    && component.getParentId().startsWith("Eq")){
                ObjectNode node = objectMapper.createObjectNode();
                node.putPOJO("groupCode",context.getGroupCode());
                node.putPOJO("projectId",context.getProjectId());
                node.putPOJO("createApp",AdmCommonConstant.APP_ID);
                node.putPOJO("creator",context.getUserId());
                node.putPOJO("updateApp",AdmCommonConstant.APP_ID);
                node.putPOJO("modifier",context.getUserId());
                node.putPOJO("graphCode",GraphCodeEnum.MechSubset.name());
                node.putPOJO("relCode",RelCodeEnum.Eq2Ec.name());
                node.putPOJO("graphId",StrUtil.format(CommonConstant.DEFAULT_GRAPH_ID_FORMAT,GraphCodeEnum.MechSubset.name()));
                node.putPOJO("valid",1);
                node.putPOJO("objFrom",component.getParentId());
                node.putPOJO("objTo",component.getId());
                relations.add(node);
            }

        }
        if(CollUtil.isEmpty(filterVOs)){
            return AdmCreateResponse.success();
        }
        filterVOs = service.doInsert(context, AdmComponent.class, filterVOs);
        if (CollUtil.isNotEmpty(relations)){
            DigitalRelationFacade.create(context.getGroupCode(),context.getProjectId(),AdmCommonConstant.APP_ID,context.getUserId(),relations);
        }
        return AdmCreateResponse.success(filterVOs);
    }

    /**
     * 根据ID删除
     * @param vos
     * @return
     * @throws Exception
     */
    @PostMapping("/delete")
    public AdmResponse delete( @RequestBody List<AdmComponent> vos) throws Exception {
        service.doDelete(AdmContextUtil.toDmpContext(), vos);
        return AdmResponse.success();
    }

    /**
     * 更新
     * @param createRequest
     * @return
     * @throws Exception
     */
    @PostMapping("/update")
    public AdmResponse update(@RequestBody AdmCreateRequest<AdmComponent> createRequest,
                              @RequestParam(value = "projectId",required = false) String projectId) throws Exception {
        List<AdmComponent> vos = CollUtil.newArrayList(createRequest.getContent());
        vos = service.doUpdate(AdmContextUtil.toDmpContext(), AdmComponent.class, vos);
        return AdmResponse.success(vos);
    }

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