package com.xjrsoft.module.workflow.service.impl;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.toolkit.MPJWrappers;
import com.xjrsoft.common.constant.GlobalConstant;
import com.xjrsoft.common.enums.EnabledMark;
import com.xjrsoft.common.enums.YesOrNoEnum;
import com.xjrsoft.common.exception.MyException;
import com.xjrsoft.common.page.ConventPage;
import com.xjrsoft.common.page.PageOutput;
import com.xjrsoft.common.utils.VoToColumnUtil;
import com.xjrsoft.module.organization.entity.Post;
import com.xjrsoft.module.system.entity.DictionaryDetail;
import com.xjrsoft.module.workflow.constant.WorkflowConstant;
import com.xjrsoft.module.workflow.dto.AddWorkflowSchemaDraftDto;
import com.xjrsoft.module.workflow.dto.AddWorkflowSchemaDto;
import com.xjrsoft.module.workflow.dto.UpdateWorkflowSchemaDto;
import com.xjrsoft.module.workflow.dto.WorkflowSchemaDraftPageDto;
import com.xjrsoft.module.workflow.dto.WorkflowSchemaPageDto;
import com.xjrsoft.module.workflow.entity.WorkflowSchema;
import com.xjrsoft.module.workflow.entity.WorkflowSchemaAuth;
import com.xjrsoft.module.workflow.entity.WorkflowSchemaDraft;
import com.xjrsoft.module.workflow.entity.WorkflowSchemaHistory;
import com.xjrsoft.module.workflow.mapper.WorkflowSchemaDraftMapper;
import com.xjrsoft.module.workflow.mapper.WorkflowSchemaHistoryMapper;
import com.xjrsoft.module.workflow.mapper.WorkflowSchemaMapper;
import com.xjrsoft.module.workflow.model.AuthConfig;
import com.xjrsoft.module.workflow.model.FormInitConfig;
import com.xjrsoft.module.workflow.model.MemberConfig;
import com.xjrsoft.module.workflow.model.WorkflowSchemaConfig;
import com.xjrsoft.module.workflow.service.IWorkflowSchemaAuthService;
import com.xjrsoft.module.workflow.service.IWorkflowSchemaService;
import com.xjrsoft.module.workflow.utils.WorkFlowUtil;
import com.xjrsoft.module.workflow.vo.WorkflowSchemaDraftPageVo;
import com.xjrsoft.module.workflow.vo.WorkflowSchemaPageVo;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.camunda.bpm.engine.RepositoryService;
import org.camunda.bpm.engine.TaskService;
import org.camunda.bpm.engine.repository.Deployment;
import org.camunda.bpm.engine.repository.ProcessDefinition;
import org.camunda.bpm.engine.spring.SpringProcessEngineConfiguration;
import org.camunda.commons.utils.IoUtil;
import org.checkerframework.checker.units.qual.A;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * <p>
 * 流程模板表 服务实现类
 * </p>
 *
 * @author tzx
 * @since 2022-07-04
 */
@Service
@AllArgsConstructor
public class WorkflowSchemaServiceImpl extends MPJBaseServiceImpl<WorkflowSchemaMapper, WorkflowSchema> implements IWorkflowSchemaService {

    private final RepositoryService repositoryService;

//    private final SpringProcessEngineConfiguration processEngineConfiguration;

    private final WorkflowSchemaDraftMapper workflowSchemaDraftMapper;

    private final WorkflowSchemaHistoryMapper workflowSchemaHistoryMapper;

    private final TaskService taskService;

    private final IWorkflowSchemaAuthService workflowSchemaAuthService;

    @Override
    public PageOutput<WorkflowSchemaPageVo> getPage(WorkflowSchemaPageDto dto) {

        SaSession tokenSession = StpUtil.getTokenSession();
        List<Long> roleIds = tokenSession.get(GlobalConstant.LOGIN_USER_ROLE_ID_KEY, new ArrayList<>());
        Post post = tokenSession.get(GlobalConstant.LOGIN_USER_POST_INFO_KEY, new Post());

        List<Long> allSchemaId = new ArrayList<>();

        //是否需要管控权限
        if (dto.getIsAuth()) {
            LambdaQueryWrapper<WorkflowSchemaAuth> query = Wrappers.lambdaQuery(WorkflowSchemaAuth.class)
                    .eq(WorkflowSchemaAuth::getObjType, -1)
                    .or(x -> x.eq(WorkflowSchemaAuth::getObjType, 2).in(WorkflowSchemaAuth::getObjId, post.getId()))
                    .or(x -> x.eq(WorkflowSchemaAuth::getObjType, 1).in(WorkflowSchemaAuth::getObjId, roleIds))
                    .or(x -> x.eq(WorkflowSchemaAuth::getObjType, 0).in(WorkflowSchemaAuth::getObjId, StpUtil.getLoginIdAsLong())
                    );
            List<WorkflowSchemaAuth> authList = workflowSchemaAuthService.list(query);
            allSchemaId = authList.stream().map(WorkflowSchemaAuth::getSchemaId).collect(Collectors.toList());

            if (CollectionUtil.isEmpty(allSchemaId)) {
                //如果权限为空  返回空数组
                PageOutput<WorkflowSchemaPageVo> pageOutput = new PageOutput<>();
                pageOutput.setList(new ArrayList<>());
                pageOutput.setCurrentPage(0);
                pageOutput.setTotalPage(0);
                pageOutput.setPageSize(0);
                return pageOutput;
            }

        }


        //因为多表关联 会有多个表都使用了id字段，  所以必须专门指定主表的Id
        List<String> orderList = new ArrayList<>();
        orderList.add("category");orderList.add("id");
        IPage<WorkflowSchemaPageVo> page = selectJoinListPage(ConventPage.getPage(dto), WorkflowSchemaPageVo.class,
                MPJWrappers.<WorkflowSchema>lambdaJoin()
                        .disableSubLogicDel()
                        .orderByDescStr(orderList)
                        .eq(ObjectUtil.isNotNull(dto.getEnabledMark()), WorkflowSchema::getEnabledMark, dto.getEnabledMark())
                        .like(StrUtil.isNotBlank(dto.getKeyword()), WorkflowSchema::getName, dto.getKeyword())
                        .like(StrUtil.isNotBlank(dto.getName()), WorkflowSchema::getName, dto.getName())
                        .like(StrUtil.isNotBlank(dto.getCode()), WorkflowSchema::getCode, dto.getCode())
                        .eq(ObjectUtil.isNotNull(dto.getCategory()), WorkflowSchema::getCategory, dto.getCategory())
                        .in(dto.getIsAuth() && CollectionUtil.isNotEmpty(allSchemaId), WorkflowSchema::getId, allSchemaId)
                        .select(WorkflowSchema::getId)
                        .select(WorkflowSchema.class, x -> VoToColumnUtil.fieldsToColumns(WorkflowSchemaPageVo.class).contains(x.getProperty()))
                        .selectAs(DictionaryDetail::getName, WorkflowSchemaPageVo::getCategoryName)
                        .leftJoin(DictionaryDetail.class, DictionaryDetail::getId, WorkflowSchema::getCategory));

        return ConventPage.getPageOutput(page);
    }

    public List<WorkflowSchemaPageVo> getList(WorkflowSchemaPageDto dto) {

        SaSession tokenSession = StpUtil.getTokenSession();
        List<Long> roleIds = tokenSession.get(GlobalConstant.LOGIN_USER_ROLE_ID_KEY, new ArrayList<>());
        Post post = tokenSession.get(GlobalConstant.LOGIN_USER_POST_INFO_KEY, new Post());

        List<Long> allSchemaId = new ArrayList<>();

        //是否需要管控权限
        if (dto.getIsAuth()) {
            LambdaQueryWrapper<WorkflowSchemaAuth> query = Wrappers.lambdaQuery(WorkflowSchemaAuth.class)
                    .eq(WorkflowSchemaAuth::getObjType, -1)
                    .or(x -> x.eq(WorkflowSchemaAuth::getObjType, 2).in(WorkflowSchemaAuth::getObjId, post.getId()))
                    .or(x -> x.eq(WorkflowSchemaAuth::getObjType, 1).in(WorkflowSchemaAuth::getObjId, roleIds))
                    .or(x -> x.eq(WorkflowSchemaAuth::getObjType, 0).in(WorkflowSchemaAuth::getObjId, StpUtil.getLoginIdAsLong())
                    );
            List<WorkflowSchemaAuth> authList = workflowSchemaAuthService.list(query);
            allSchemaId = authList.stream().map(WorkflowSchemaAuth::getSchemaId).collect(Collectors.toList());

            if (CollectionUtil.isEmpty(allSchemaId)) {
                //如果权限为空  返回空数组
                PageOutput<WorkflowSchemaPageVo> pageOutput = new PageOutput<>();
                pageOutput.setList(new ArrayList<>());
                pageOutput.setCurrentPage(0);
                pageOutput.setTotalPage(0);
                pageOutput.setPageSize(0);
                return new ArrayList<>();
            }

        }


        //因为多表关联 会有多个表都使用了id字段，  所以必须专门指定主表的Id
        List<String> orderList = new ArrayList<>();
        orderList.add("category");orderList.add("id");
        List<WorkflowSchemaPageVo> workflowSchemaPageVos = selectJoinList(WorkflowSchemaPageVo.class,
                MPJWrappers.<WorkflowSchema>lambdaJoin()
                        .disableSubLogicDel()
                        .orderByDescStr(orderList)
                        .eq(ObjectUtil.isNotNull(dto.getEnabledMark()), WorkflowSchema::getEnabledMark, dto.getEnabledMark())
                        .like(StrUtil.isNotBlank(dto.getKeyword()), WorkflowSchema::getName, dto.getKeyword())
                        .like(StrUtil.isNotBlank(dto.getName()), WorkflowSchema::getName, dto.getName())
                        .like(StrUtil.isNotBlank(dto.getCode()), WorkflowSchema::getCode, dto.getCode())
                        .eq(ObjectUtil.isNotNull(dto.getCategory()), WorkflowSchema::getCategory, dto.getCategory())
                        .in(dto.getIsAuth() && CollectionUtil.isNotEmpty(allSchemaId), WorkflowSchema::getId, allSchemaId)
                        .select(WorkflowSchema::getId)
                        .select(WorkflowSchema.class, x -> VoToColumnUtil.fieldsToColumns(WorkflowSchemaPageVo.class).contains(x.getProperty()))
                        .selectAs(DictionaryDetail::getName, WorkflowSchemaPageVo::getCategoryName)
                        .leftJoin(DictionaryDetail.class, DictionaryDetail::getId, WorkflowSchema::getCategory));

        return workflowSchemaPageVos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    public boolean add(AddWorkflowSchemaDto dto) {
        LambdaQueryWrapper<WorkflowSchema> countQuery = Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getName, dto.getProcessConfig().getName()).or().eq(WorkflowSchema::getCode, dto.getProcessConfig().getCode());
        if (count(countQuery) > 0) {
            throw new MyException("当前模板名称和模板编号重复！");
        }

        WorkflowSchemaConfig workflowSchemaConfig = BeanUtil.toBean(dto, WorkflowSchemaConfig.class);
        WorkflowSchema workflowSchema = BeanUtil.toBean(dto.getProcessConfig(), WorkflowSchema.class);

        //表单发起流程
        FormInitConfig formInitConfig = workflowSchemaConfig.getProcessConfig().getFormInitConfig();
        if (formInitConfig.getEnabled()) {
            LambdaQueryWrapper<WorkflowSchema> select = Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getFormId, formInitConfig.getFormId()).select(WorkflowSchema::getId);

            if (count(select) > 0) {
                throw new MyException("当前表单已经绑定过流程，请重新选择！");
            }
            workflowSchema.setFormId(formInitConfig.getFormId());
        }

        Deployment deploy = repositoryService.createDeployment()
                .addInputStream(workflowSchemaConfig.getProcessConfig().getName() + StringPool.DOT + WorkflowConstant.WORKFLOW_SUFFIX, IoUtil.stringAsInputStream(workflowSchemaConfig.getProcessConfig().getXmlContent())).name(workflowSchemaConfig.getProcessConfig().getName()).deploy();

        //存储流程部署id
        workflowSchema.setDeploymentId(deploy.getId());

        //获取流程定义id
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
        //存储流程定义key
        workflowSchema.setDefinitionKey(processDefinition.getKey());

        //存储流程定义id
        workflowSchema.setDefinitionId(processDefinition.getId());

        //把配置json存储  (清除掉xml)
        workflowSchemaConfig.getProcessConfig().setXmlContent("");

        ObjectMapper mapper = new ObjectMapper();
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        mapper.registerModule(simpleModule);

        String jsonContent = mapper.writeValueAsString(workflowSchemaConfig);

        workflowSchema.setJsonContent(jsonContent);

        save(workflowSchema);

        AuthConfig authConfig = workflowSchemaConfig.getProcessConfig().getAuthConfig();

        //如果是指定人员
        if (authConfig.getAuthType() == 1) {
            List<WorkflowSchemaAuth> authList = new ArrayList<>();
            List<MemberConfig> authMemberConfigs = authConfig.getAuthMemberConfigs();
            for (MemberConfig authMemberConfig : authMemberConfigs) {
                WorkflowSchemaAuth auth = new WorkflowSchemaAuth();
                auth.setSchemaId(workflowSchema.getId());
                auth.setObjId(Long.parseLong(authMemberConfig.getId()));
                auth.setObjName(authMemberConfig.getName());
                auth.setObjType(authMemberConfig.getMemberType());
                authList.add(auth);
            }
            workflowSchemaAuthService.saveBatch(authList);
        }
        //如果所有人
        else {
            WorkflowSchemaAuth auth = new WorkflowSchemaAuth();
            auth.setSchemaId(workflowSchema.getId());
            auth.setObjType(-1);
            workflowSchemaAuthService.save(auth);
        }


        //将新增的数据 记录模板历史记录
        WorkflowSchemaHistory history = new WorkflowSchemaHistory();
        history.setSchemaId(workflowSchema.getId());
        history.setVersion(1);
        history.setActivityFlag(EnabledMark.ENABLED.getCode());
        history.setXmlContent(workflowSchema.getXmlContent());
        history.setJsonContent(workflowSchema.getJsonContent());
        history.setDefinitionKey(workflowSchema.getDefinitionKey());
        history.setDeploymentId(workflowSchema.getDeploymentId());
        history.setDefinitionId(workflowSchema.getDefinitionId());


        //缓存节点监听器数据
        CompletableFuture.runAsync(() -> {
            WorkFlowUtil.cacheNodeListener(deploy.getId(), workflowSchemaConfig.getChildNodeConfig());
        });


        return workflowSchemaHistoryMapper.insert(history) > 0;
    }

    @Override
    public boolean addDraft(AddWorkflowSchemaDraftDto dto) {
        WorkflowSchemaConfig workflowSchemaConfig = BeanUtil.toBean(dto, WorkflowSchemaConfig.class);
        WorkflowSchemaDraft workflowSchemaDraft = BeanUtil.toBean(dto.getProcessConfig(), WorkflowSchemaDraft.class);

        //把配置json存储
        workflowSchemaDraft.setJsonContent(JSONUtil.toJsonStr(workflowSchemaConfig));

        return workflowSchemaDraftMapper.insert(workflowSchemaDraft) > 0;
    }

    @Override
    public PageOutput<WorkflowSchemaDraftPageVo> getDraftPage(WorkflowSchemaDraftPageDto dto) {

        LambdaQueryWrapper<WorkflowSchemaDraft> queryWrapper = Wrappers.lambdaQuery(WorkflowSchemaDraft.class)
                .like(StrUtil.isNotBlank(dto.getKeyword()), WorkflowSchemaDraft::getName, dto.getKeyword())
                .between(ObjectUtil.isNotNull(dto.getStartTime()) && ObjectUtil.isNotNull(dto.getEndTime()), WorkflowSchemaDraft::getCreateDate, dto.getStartTime(), dto.getEndTime())
                .select(WorkflowSchemaDraft.class, x -> VoToColumnUtil.fieldsToColumns(WorkflowSchemaPageVo.class).contains(x.getProperty()));

        IPage<WorkflowSchemaDraft> workflowSchemaDraftPage = workflowSchemaDraftMapper.selectPage(ConventPage.getPage(dto), queryWrapper);

        return ConventPage.getPageOutput(workflowSchemaDraftPage, WorkflowSchemaDraftPageVo.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    public boolean update(UpdateWorkflowSchemaDto dto) {
        LambdaQueryWrapper<WorkflowSchema> countQuery = Wrappers.lambdaQuery(WorkflowSchema.class).ne(WorkflowSchema::getId, dto.getId()).and(x -> x.eq(WorkflowSchema::getName, dto.getProcessConfig().getName()).or().eq(WorkflowSchema::getCode, dto.getProcessConfig().getCode()));
        if (count(countQuery) > 0) {
            throw new MyException("当前模板名称和模板编号重复！");
        }


        WorkflowSchema workflowSchema = getById(dto.getId());

        if (workflowSchema == null) {
            throw new MyException("找不到此模板！");
        }

        workflowSchema.setName(dto.getProcessConfig().getName());
        workflowSchema.setCode(dto.getProcessConfig().getCode());
        workflowSchema.setStyleType(dto.getStyleType());
        workflowSchema.setRemark(dto.getProcessConfig().getRemark());
        workflowSchema.setXmlContent(dto.getProcessConfig().getXmlContent());
        workflowSchema.setWorkflowChat(dto.getProcessConfig().getWorkflowChat());
        workflowSchema.setCategory(Long.valueOf(dto.getProcessConfig().getCategory()));

        WorkflowSchemaConfig workflowSchemaConfig = BeanUtil.toBean(dto, WorkflowSchemaConfig.class);


        //表单发起流程
        FormInitConfig formInitConfig = workflowSchemaConfig.getProcessConfig().getFormInitConfig();
        if (formInitConfig.getEnabled()) {
            LambdaQueryWrapper<WorkflowSchema> select = Wrappers.lambdaQuery(WorkflowSchema.class).ne(WorkflowSchema::getId, dto.getId()).eq(WorkflowSchema::getFormId, formInitConfig.getFormId()).select(WorkflowSchema::getId);

            if (count(select) > 0) {
                throw new MyException("当前表单已经绑定过流程，请重新选择！");
            }
            workflowSchema.setFormId(formInitConfig.getFormId());
        } else {
            workflowSchema.setFormId(0L);
        }


//        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(workflowSchema.getDeploymentId()).singleResult();
//
//
//        //如果需要级联删除  把第二个参数设置为true
//        //级联删除 会删除所有关联数据 包括 历史记录
//        repositoryService.deleteProcessDefinition(processDefinition.getId());
//
//        //如果需要级联删除  把第二个参数设置为true
//        //级联删除 会删除所有关联数据 包括 历史记录
//        repositoryService.deleteDeployment(workflowSchema.getDeploymentId());


        //因为流程图会被缓存  如果修改了流程图 缓存会没变。 需要清理本地缓存
//        processEngineConfiguration.getDeploymentCache().removeDeployment(workflowSchema.getDeploymentId());

        //更新的流程重新部署
        Deployment deploy = repositoryService.createDeployment()
                .addInputStream(dto.getProcessConfig().getName() + StringPool.DOT + WorkflowConstant.WORKFLOW_SUFFIX, IoUtil.stringAsInputStream(dto.getProcessConfig().getXmlContent())).name(dto.getProcessConfig().getName()).deploy();

        //获取流程定义id
        ProcessDefinition newProcessDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
        //存储流程定义key
        workflowSchema.setDefinitionKey(newProcessDefinition.getKey());
        //存储流程定义id
        workflowSchema.setDefinitionId(newProcessDefinition.getId());
        workflowSchema.setDeploymentId(deploy.getId());

        AuthConfig authConfig = workflowSchemaConfig.getProcessConfig().getAuthConfig();
        //如果是指定人员
        if (authConfig.getAuthType() == 1) {
            workflowSchemaAuthService.remove(Wrappers.lambdaQuery(WorkflowSchemaAuth.class).eq(WorkflowSchemaAuth::getSchemaId, workflowSchema.getId()));
            List<WorkflowSchemaAuth> authList = new ArrayList<>();
            List<MemberConfig> authMemberConfigs = authConfig.getAuthMemberConfigs();
            for (MemberConfig authMemberConfig : authMemberConfigs) {
                WorkflowSchemaAuth auth = new WorkflowSchemaAuth();
                auth.setSchemaId(workflowSchema.getId());
                auth.setObjId(Long.parseLong(authMemberConfig.getId()));
                auth.setObjName(authMemberConfig.getName());
                auth.setObjType(authMemberConfig.getMemberType());
                authList.add(auth);
            }
            workflowSchemaAuthService.saveBatch(authList);
        }
        //如果所有人
        else {
            workflowSchemaAuthService.remove(Wrappers.lambdaQuery(WorkflowSchemaAuth.class).eq(WorkflowSchemaAuth::getSchemaId, workflowSchema.getId()));
            WorkflowSchemaAuth auth = new WorkflowSchemaAuth();
            auth.setSchemaId(workflowSchema.getId());
            auth.setObjType(-1);
            workflowSchemaAuthService.save(auth);
        }


        //找到上一个版本号 只需要版本号 以及 id
        LambdaQueryWrapper<WorkflowSchemaHistory> queryWrapper = Wrappers.lambdaQuery(WorkflowSchemaHistory.class)
                .eq(WorkflowSchemaHistory::getSchemaId, workflowSchema.getId())
                .eq(WorkflowSchemaHistory::getActivityFlag, YesOrNoEnum.YES.getCode())
                .select(WorkflowSchemaHistory::getVersion, WorkflowSchemaHistory::getId)
                .orderByDesc(WorkflowSchemaHistory::getVersion);
        WorkflowSchemaHistory oldHistory = workflowSchemaHistoryMapper.selectOne(queryWrapper);
        Integer version = oldHistory.getVersion();

        //把配置json存储  (清除掉xml)
        workflowSchemaConfig.getProcessConfig().setXmlContent("");

        ObjectMapper mapper = new ObjectMapper();
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        mapper.registerModule(simpleModule);

        String jsonContent = mapper.writeValueAsString(workflowSchemaConfig);

        workflowSchema.setJsonContent(jsonContent);

        //将修改后的数据 记录模板历史记录
        WorkflowSchemaHistory history = new WorkflowSchemaHistory();
        history.setSchemaId(workflowSchema.getId());
        history.setVersion(version + 1);
        history.setActivityFlag(EnabledMark.ENABLED.getCode());
        history.setXmlContent(workflowSchema.getXmlContent());
        history.setJsonContent(workflowSchema.getJsonContent());
        history.setWorkflowChat(workflowSchema.getWorkflowChat());
        history.setDefinitionId(workflowSchema.getDefinitionId());
        history.setDefinitionKey(workflowSchema.getDefinitionKey());
        workflowSchemaHistoryMapper.insert(history);
        //将上一个版本的 历史数据 flag  改为 非活动版本
        oldHistory.setActivityFlag(EnabledMark.DISABLED.getCode());
        workflowSchemaHistoryMapper.updateById(oldHistory);

        //缓存节点监听器数据
        CompletableFuture.runAsync(() -> {
            WorkFlowUtil.cacheNodeListener(deploy.getId(), workflowSchemaConfig.getChildNodeConfig());
        });


        return updateById(workflowSchema);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(List<Long> ids) {

        for (Long id : ids) {
            long count = taskService.createTaskQuery().processVariableValueEquals(WorkflowConstant.PROCESS_SCHEMA_ID_KEY, id).count();
            if (count > 0) {
                throw new MyException("有流程正在执行 无法删除！");
            }
        }
        QueryWrapper<WorkflowSchema> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .in(WorkflowSchema::getId, ids)
                .select(WorkflowSchema::getDeploymentId, WorkflowSchema::getDefinitionId);

        List<WorkflowSchema> workflowSchemas = list(queryWrapper);

        //获取到所有流程定义id
        List<String> definitionIds = workflowSchemas.stream().map(WorkflowSchema::getDefinitionId).collect(Collectors.toList());
        //获取到所有deployIds
        List<String> deploymentIds = workflowSchemas.stream().map(WorkflowSchema::getDeploymentId).collect(Collectors.toList());

        try {
            repositoryService.deleteProcessDefinitions().byIds(StrUtil.join(",", definitionIds)).delete();
        } catch (Exception e) {
            if (e.getMessage().contains("since there exists")) {
                throw new MyException("有流程正在执行 无法删除！");//避免有外部任务正在执行的流程删除时，提示引擎删除错误。
            }
        }
        for (String deploymentId : deploymentIds) {
            repositoryService.deleteDeployment(deploymentId);
        }

        //缓存节点监听器数据
        CompletableFuture.runAsync(() -> {
            for (String deploymentId : deploymentIds) {
                WorkFlowUtil.removeNodeListener(deploymentId);
            }
        });

        return removeBatchByIds(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    public boolean importSchema(MultipartFile multipartFile) {

        //用流读取文件
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(multipartFile.getInputStream()));
        String line;
        StringBuilder content = new StringBuilder();
        // 读取想定文件
        while ((line = bufferedReader.readLine()) != null) {
            content.append(line);
        }

        WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(content.toString(), WorkflowSchemaConfig.class);

        WorkflowSchema workflowSchema = BeanUtil.toBean(workflowSchemaConfig.getProcessConfig(), WorkflowSchema.class);
        if (StrUtil.isNotBlank(workflowSchemaConfig.getId())) {
            workflowSchema.setId(Convert.toLong(workflowSchemaConfig.getId()));
        }

        Deployment deploy = repositoryService.createDeployment()
                .addInputStream(workflowSchemaConfig.getProcessConfig().getName() + StringPool.DOT + WorkflowConstant.WORKFLOW_SUFFIX, IoUtil.stringAsInputStream(workflowSchemaConfig.getProcessConfig().getXmlContent())).name(workflowSchemaConfig.getProcessConfig().getName()).deploy();

        //存储流程部署id
        workflowSchema.setDeploymentId(deploy.getId());

        //获取流程定义id
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
        //存储流程定义key
        workflowSchema.setDefinitionKey(processDefinition.getKey());

        //存储流程定义id
        workflowSchema.setDefinitionId(processDefinition.getId());

        //把配置json存储  (清除掉xml)
        workflowSchemaConfig.getProcessConfig().setXmlContent("");
        workflowSchema.setJsonContent(JSONUtil.toJsonStr(workflowSchemaConfig));

        save(workflowSchema);

        //将新增的数据 记录模板历史记录
        WorkflowSchemaHistory history = new WorkflowSchemaHistory();
        history.setSchemaId(workflowSchema.getId());
        history.setVersion(1);
        history.setActivityFlag(EnabledMark.ENABLED.getCode());
        history.setXmlContent(workflowSchema.getXmlContent());
        history.setJsonContent(workflowSchema.getJsonContent());

        //缓存节点监听器数据
        CompletableFuture.runAsync(() -> {
            WorkFlowUtil.cacheNodeListener(deploy.getId(), workflowSchemaConfig.getChildNodeConfig());
        });


        return workflowSchemaHistoryMapper.insert(history) > 0;
    }


}
