package com.persagy.adm.diagram.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.persagy.adm.diagram.core.ContentParser;
import com.persagy.adm.diagram.core.DataStrategy;
import com.persagy.adm.diagram.core.model.Diagram;
import com.persagy.adm.diagram.core.model.template.DiagramTemplate;
import com.persagy.adm.diagram.frame.BdtpRequest;
import com.persagy.adm.diagram.manage.DiagramManager;
import com.persagy.adm.diagram.service.IconService;
import com.persagy.dmp.common.constant.ResponseCode;
import com.persagy.dmp.common.exception.BusinessException;
import com.persagy.dmp.common.model.response.CommonResult;
import com.persagy.dmp.common.utils.ResultHelper;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 系统图相关接口
 *
 * @author liyang
 * @date 2022-01-04
 */
@RestController
@RequestMapping("/diagram")
public class DiagramController {

    @Autowired
    @Qualifier("dataStrategyImpl")
    private DataStrategy dataStrategy;
    @Autowired
    private DiagramManager diagramManager;
    @Autowired
    private ContentParser parser;
    @Autowired
    private IconService iconService;

    /**
     * 系统图列表接口
     *
     * @param diagram 请求参数
     * @return 系统图列表
     */
    @ApiOperation("系统图列表接口")
    @PostMapping("/getDiagrams")
    public String getDiagrams(@RequestBody Map<String, Object> diagram) {
        BdtpRequest current = BdtpRequest.getCurrent();
        String groupCode = current.getGroupCode();
        String projectId = current.getProjectId();

        List<Diagram> diagramList = dataStrategy.getDiagrams(null, projectId,
                (String) diagram.get("systemId"), groupCode, (String) diagram.get("name"), true);

        return diagramManager.json4Edit(ResultHelper.multi(diagramList));
    }

    /**
     * 提供给APM的系统图列表接口
     *
     * @param diagram 请求参数
     * @return 系统图列表
     */
    @ApiOperation("提供给APM的系统图列表接口")
    @PostMapping("/apm/getDiagrams")
    public String getDiagramsForApm(@RequestBody Map<String, Object> diagram) {
        BdtpRequest current = BdtpRequest.getCurrent();
        String groupCode = current.getGroupCode();
        String projectId = current.getProjectId();

        List<Diagram> diagramList = dataStrategy.getDiagrams(null, projectId,
                (String) diagram.get("systemId"), groupCode, null, false);
        //TODO 批量处理会导致接口响应慢，优化为列表和内容拆分的方式
        if (diagramList != null) {
            diagramList.forEach(d -> {
                diagramManager.buildDiagram(d);
                d.toAbsoluteLocation();

                //TODO 批量处理会导致接口响应慢，优化为列表和内容拆分的方式
                //没有nodes的话就不去查询了
                if (CollectionUtil.isNotEmpty(d.getNodes())) {
                    String[] legendIds = d.getLegendIds();
                    Map<String, String> map = iconService.getIconsByLegendIds(Arrays.asList(legendIds));
                    d.setExtraProp("legendIcons", map);
                }
            });
        }

        return diagramManager.json4View(ResultHelper.multi(diagramList));
    }

    /**
     * 新增或修改系统图
     *
     * @param params    参数集合
     * @param projectId 项目id
     * @param groupCode 集团code
     * @return 系统图信息
     */
    @ApiOperation("新增系统图")
    @PostMapping("/newDiagram")
    public CommonResult<Diagram> newDiagram(@RequestBody Map<String, Object> params,
                                            @RequestParam String projectId,
                                            @RequestParam String groupCode) {
        Diagram diagram = diagramManager.fromMapData(params);

        if (diagram.getName() == null || diagram.getName().length() < 3
                || diagram.getName().length() > 15) {
            throw new BusinessException(ResponseCode.A0400.getCode(), "名称长度不能小于3，不能超过15");
        }

        diagram.setGroupCode(groupCode);
        diagram.setProjectId(projectId);

        diagramManager.buildDiagram(diagram);

        return ResultHelper.single(dataStrategy.saveDiagram(diagram));
    }

    /**
     * 系统图删除功能
     *
     * @param diagramId 系统图id
     * @return 是否成功
     */
    @ApiOperation("删除系统图")
    @GetMapping("/deleteDiagram")
    public CommonResult<Boolean> deleteDiagram(String diagramId) {
        return ResultHelper.single(dataStrategy.deleteDiagram(diagramId));
    }

    /**
     * 根据系统图id获取系统图信息
     *
     * @param diagramId 系统图id
     * @return 系统图对象信息
     */
    @ApiOperation("根据系统图id获取系统图信息")
    @GetMapping("/getDiagram")
    public CommonResult<Diagram> getDiagram(String diagramId) {
        Diagram diagram = dataStrategy.getDiagram(diagramId);
        diagramManager.buildDiagram(diagram);
        return ResultHelper.single(diagram);
    }

    /**
     * 系统实例查询
     *
     * @return 系统实例
     */
    @ApiOperation("系统实例查询")
    @PostMapping("/system/instance")
    public CommonResult<List<ObjectNode>> loadSystemInstance() {
        BdtpRequest current = BdtpRequest.getCurrent();
        String groupCode = current.getGroupCode();
        String projectId = current.getProjectId();
        return ResultHelper.multi(dataStrategy.loadSystemInstance(projectId, groupCode));
    }

    /**
     * 项目下的专业 -> 系统 ->系统实例 的树状结构数据
     *
     * @return 列表
     */
    @ApiOperation("项目下的专业 -> 系统 ->系统实例 的树状结构数据")
    @PostMapping("/major/system/instance")
    public CommonResult<List<ObjectNode>> loadMajorSystemInstance() {
        return ResultHelper.multi(dataStrategy.loadMajorSystemInstance());
    }

    /**
     * 根据系统类获取系统类型下的模板列表  以树状结构数据返回
     *
     * @param diagram diagram.getSystem() 参数
     * @return 列表
     */
    @ApiOperation("据系统类获取系统类型下的模板列表")
    @PostMapping("/systemType/template")
    public CommonResult<List<ObjectNode>> loadSystemTypeTemplate(@RequestBody Diagram diagram) {
        return ResultHelper.multi(dataStrategy.loadSystemTypeTemplate(diagram));
    }

    /**
     * 根据系统图类型获取模板列表
     *
     * @param diagramType 系统图类型
     * @return 模板列表
     */
    @ApiOperation("根据系统图类型获取模板列表")
    @GetMapping("/getTemplates/ByType")
    public CommonResult<List<DiagramTemplate>> getTemplatesByType(String diagramType) {
        return ResultHelper.multi(dataStrategy.getTemplates(diagramType));
    }

    /**
     * 根据模板id获取系统模板信息
     *
     * @param templateId 模板id
     * @return 模板信息
     */
    @ApiOperation("根据模板id获取系统模板信息")
    @GetMapping("/getTemplate/ById")
    public CommonResult<DiagramTemplate> getTemplateById(String templateId) {
        return ResultHelper.single(dataStrategy.getTemplate(templateId));
    }

    /**
     * 获取所有的系统模板
     *
     * @return 模板列表
     */
    @ApiOperation("获取所有的系统模板")
    @GetMapping("/getTemplates")
    public CommonResult<List<DiagramTemplate>> getTemplates() {
        return ResultHelper.multi(dataStrategy.getTemplates());
    }

    /**
     * 加载数据
     *
     * @return 模板列表
     */
    @ApiOperation("加载数据")
    @PostMapping("/loadData")
    public CommonResult<Diagram> loadData(@RequestBody Diagram diagram) {
        if (diagram == null || StrUtil.isBlank(diagram.getId())) {
            throw new BusinessException(ResponseCode.A0400.getCode(), "系统图id不存在");
        }
        diagram = dataStrategy.getDiagram(diagram.getId());
        if (diagram == null) {
            throw new BusinessException(ResponseCode.A0400.getCode(), "数据不存在");
        }
        return ResultHelper.single(diagramManager.loadData(diagram));
    }

    /**
     * 重置模板、图数据
     *
     * @return 重置后的系统图数据
     */
    @ApiOperation("重置模板、图数据")
    @PostMapping("/reset")
    public CommonResult<Diagram> reset(@RequestBody Diagram diagram) {
        if (diagram == null || StrUtil.isBlank(diagram.getId())) {
            throw new BusinessException(ResponseCode.A0400.getCode(), "系统图id不存在");
        }
        diagram = dataStrategy.getDiagram(diagram.getId());
        if (diagram == null) {
            throw new BusinessException(ResponseCode.A0400.getCode(), "数据不存在");
        }
        diagramManager.resetDiagram(diagram);
        return ResultHelper.single(diagramManager.loadData(diagram));
    }

    /**
     * 系统图状态变更
     *
     * @return 是否成功
     */
    @ApiOperation("系统图状态变更")
    @PostMapping("/update/state")
    public CommonResult<Boolean> updateState(@RequestBody Map<String, String> params) {
        return ResultHelper.single(dataStrategy.updateState(params.get("state"), params.get("id")));
    }

    /**
     * 系统图名称变更
     *
     * @return 是否成功
     */
    @ApiOperation("系统图状态变更")
    @PostMapping("/update/name")
    public CommonResult<Boolean> updateName(@RequestBody Map<String, String> params) {
        if (params == null) {
            throw new BusinessException(ResponseCode.A0400.getCode(), "请求参数为空");
        }
        String name = params.get("name");
        if (StrUtil.isBlank(name) || name.length() < 3 || name.length() > 15) {
            throw new BusinessException(ResponseCode.A0400.getCode(), "名称长度不能小于3，不能超过15");
        }
        return ResultHelper.single(dataStrategy.updateName(params.get("name"), params.get("id")));
    }

    /**
     * 查看系统实例是否有发布状态的系统图
     *
     * @return 是否成功
     */
    @ApiOperation("查看系统实例是否有发布状态的系统图")
    @PostMapping("/system/instance/diagram/list")
    public CommonResult<Map<String, Boolean>> querySystemInstanceDiagramList() {
        return ResultHelper.single(dataStrategy.querySystemInstanceDiagramList());
    }

    /**
     * 判断系统图名称是否重复  true:重复，false:不重复
     *
     * @return 是否成功
     */
    @ApiOperation("判断系统图名称是否重复")
    @PostMapping("/judge/name/duplicate")
    public CommonResult<Boolean> judgeNameDuplicate(@RequestBody Map<String, String> params) {
        return ResultHelper.single(dataStrategy.judgeNameDuplicate(params.get("name")));
    }
}
