package com.zkqy.system.service.impl;

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

import com.zkqy.common.core.domain.AjaxResult;
import com.zkqy.common.utils.DateUtils;
import com.zkqy.common.utils.SecurityUtils;
import com.zkqy.common.utils.http.Sending;
import com.zkqy.system.entity.BpmNodeHandleUser;
import com.zkqy.system.entity.BpmNodeScriptRelevance;
import com.zkqy.system.entity.vo.NodeVo;
import com.zkqy.system.service.IBpmNodeHandleUserService;
import com.zkqy.system.service.IBpmNodeScriptRelevanceService;
import com.zkqy.system.service.ICommonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import com.zkqy.system.mapper.BpmProcessConfigurationMapper;
import com.zkqy.system.entity.BpmProcessConfiguration;
import com.zkqy.system.service.IBpmProcessConfigurationService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 流程配置Service业务层处理
 *
 * @author hzh
 * @date 2023-10-20
 */
@Service
public class BpmProcessConfigurationServiceImpl implements IBpmProcessConfigurationService {

    @Autowired  // 流程节点配置
    private BpmProcessConfigurationMapper bpmProcessConfigurationMapper;
    @Autowired  // 节点执行用户
    private IBpmNodeHandleUserService iBpmNodeHandleUserService;
    @Autowired  // 节点执行脚本
    private IBpmNodeScriptRelevanceService iBpmNodeScriptRelevanceService;

    @Autowired
    private ICommonService commonService;

    @Autowired
    private Sending sending;

    /**
     * 查询流程配置
     *
     * @param id 流程配置主键
     * @return 流程配置
     */
    @Override
    public BpmProcessConfiguration selectBpmProcessConfigurationById(Long id) {
        return bpmProcessConfigurationMapper.selectBpmProcessConfigurationById(id);
    }

    /**
     * 查询流程配置列表
     *
     * @param bpmProcessConfiguration 流程配置
     * @return 流程配置
     */
    @Override
    public List<BpmProcessConfiguration> selectBpmProcessConfigurationList(BpmProcessConfiguration bpmProcessConfiguration) {
        return bpmProcessConfigurationMapper.selectBpmProcessConfigurationList(bpmProcessConfiguration);
    }

    /**
     * 新增流程配置
     *
     * @param bpmProcessConfigurationList 流程配置
     * @return 结果
     */
    @Override
    public int insertBpmProcessConfiguration(List<BpmProcessConfiguration> bpmProcessConfigurationList) {
        return bpmProcessConfigurationMapper.insertBpmProcessConfiguration(bpmProcessConfigurationList);
    }

    /**
     * 修改流程配置
     *
     * @param bpmProcessConfigurationList 流程配置
     * @return 结果
     */
    @Override
    public int updateBpmProcessConfiguration(BpmProcessConfiguration bpmProcessConfigurationList) {
        //bpmProcessConfigurationList.forEach(node -> node.setUpdateTime(DateUtils.getNowDate()));
        return bpmProcessConfigurationMapper.updateBpmProcessConfiguration(bpmProcessConfigurationList);
    }

    /**
     * 批量删除流程配置
     *
     * @param ids 需要删除的流程配置主键
     * @return 结果
     */
    @Override
    public int deleteBpmProcessConfigurationByIds(Long[] ids) {
        return bpmProcessConfigurationMapper.deleteBpmProcessConfigurationByIds(ids);
    }

    /**
     * 删除流程配置信息
     *
     * @param id 流程配置主键
     * @return 结果
     */
    @Override
    public int deleteBpmProcessConfigurationById(Long id) {
        return bpmProcessConfigurationMapper.deleteBpmProcessConfigurationById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertBpmProcessNodeConfig(NodeVo nodeVo) {
        // 下发获取当前所有数据表
        ResponseEntity<AjaxResult> responseEntity = sending.sendQueryTemplateBaseTable();
        if(responseEntity.getStatusCodeValue() != 200){
            return 0;
        }
        AjaxResult ajaxResult = responseEntity.getBody();
        List<String> tableNameList = (List<String>) ajaxResult.get("data");
        nodeVo.getTableNameList().stream().filter(tableName -> !tableNameList.contains(tableName)).collect(Collectors.toList());
        String addField = ",task_key varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT '' COMMENT '任务编码'," +
                "task_node_key varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT '' COMMENT '任务节点编码') ENGINE=InnoDB";
        // 新建流程节点所需数据表
        for (String tableName : nodeVo.getTableNameList()){
            String createTableSql = commonService.selectTableSql(tableName).get("create table");
            createTableSql = createTableSql.replace("CREATE TABLE","CREATE TABLE IF NOT EXISTS {DBNAME}.");
            if(!createTableSql.contains("task_key") && !createTableSql.contains("task_node_key")){
                createTableSql = createTableSql.replace(") ENGINE=InnoDB",addField);
            }
            try {
                commonService.executeSql(createTableSql);
            }catch (Exception e){
                return 0;
            }
        }
        // 新增节点配置
        if (nodeVo.getBpmProcessConfigurationList().size() != 0)
            nodeVo.getBpmProcessConfigurationList().stream().forEach(e -> {
                e.setCreateById(SecurityUtils.getUserId());
                e.setCreateBy(SecurityUtils.getUsername());
                e.setCreateTime(DateUtils.getNowDate());
            });
        bpmProcessConfigurationMapper.insertBpmProcessConfiguration(nodeVo.getBpmProcessConfigurationList());
        // 新增节点执行用户
        if (nodeVo.getBpmNodeHandleUserList().size() != 0)
            iBpmNodeHandleUserService.insertBpmNodeHandleUser(nodeVo.getBpmNodeHandleUserList());
        // 新增节点脚本关系
        if (nodeVo.getBpmNodeScriptRelevanceList().size() != 0)
            iBpmNodeScriptRelevanceService.insertBpmNodeScriptRelevance(nodeVo.getBpmNodeScriptRelevanceList());
        return 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateBpmProcessNodeConfig(NodeVo nodeVo) {
        // 下发获取当前所有数据表
        ResponseEntity<AjaxResult> responseEntity = sending.sendQueryTemplateBaseTable();
        if(responseEntity.getStatusCodeValue() != 200){
            return 0;
        }
        AjaxResult ajaxResult = responseEntity.getBody();
        List<String> tableNameList = (List<String>) ajaxResult.get("data");
        nodeVo.getTableNameList().stream().filter(tableName -> !tableNameList.contains(tableName)).collect(Collectors.toList());
        String addField = ",task_key varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT '' COMMENT '任务编码'," +
                "task_node_key varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT '' COMMENT '任务节点编码') ENGINE=InnoDB";
        // 新建流程节点所需数据表
        for (String tableName : nodeVo.getTableNameList()){
            String createTableSql = commonService.selectTableSql(tableName).get("create table");
            createTableSql = createTableSql.replace("CREATE TABLE","CREATE TABLE IF NOT EXISTS {DBNAME}.");
            createTableSql = createTableSql.replace(") ENGINE=InnoDB",addField);
            try {
                commonService.executeSql(createTableSql);
            }catch (Exception e){
                return 0;
            }
        }
        // 修改节点配置
        if (nodeVo.getBpmProcessConfigurationList().size() != 0) {
            // 定义存储修改操作中新增节点，根据id为null来判断是否新增数据条
            List<BpmProcessConfiguration> addList = new ArrayList<>();
            // List<BpmProcessConfiguration> removeList = new ArrayList<>();
            nodeVo.getBpmProcessConfigurationList().forEach(item -> {
                if (item.getId() == null) {
                    // 把需要新增的数据添加到addList集合里边
                    addList.add(item);
                }
            });

            // 从大集合里边移除需要添加的节点
            nodeVo.getBpmProcessConfigurationList().removeAll(addList);

            //修改操作(一共四个节点、)
            nodeVo.getBpmProcessConfigurationList().forEach(item -> {
                item.setUpdateTime(DateUtils.getNowDate());
                item.setUpdateById(SecurityUtils.getUserId());
                item.setUpdateBy(SecurityUtils.getUsername());
                bpmProcessConfigurationMapper.updateBpmProcessConfiguration(item);
            });

            // 新增操作
            if (addList.size() != 0) {
//                addList.parallelStream().forEach(item->{
//                    item.setCreateTime(DateUtils.getNowDate());
//                    item.setCreateBy(SecurityUtils.getUsername());
//                    item.setCreateById(SecurityUtils.getUserId());
//                });
                bpmProcessConfigurationMapper.insertBpmProcessConfiguration(addList);
            }
        }

        // 修改节点执行用户
        if (nodeVo.getBpmNodeHandleUserList().size() != 0) {
            List<BpmNodeHandleUser> addList1 = new ArrayList<>();
            Iterator<BpmNodeHandleUser> iterator = nodeVo.getBpmNodeHandleUserList().iterator();
            while (iterator.hasNext()) {
                BpmNodeHandleUser item = iterator.next();
                if (item.getId() == null) {
                    addList1.add(item);
                    iterator.remove();
                }
            }
            iBpmNodeHandleUserService.updateBpmNodeHandleUser(nodeVo.getBpmNodeHandleUserList());
            if (addList1.size() != 0)
                iBpmNodeHandleUserService.insertBpmNodeHandleUser(addList1);
        }

        // 修改节点脚本关系
        if (nodeVo.getBpmNodeScriptRelevanceList().size() != 0) {
            //删除节点脚本关系
            List<String> nodeKeys = nodeVo.getBpmNodeScriptRelevanceList().stream().map(BpmNodeScriptRelevance::getNodeKey).collect(Collectors.toList());
            if (nodeVo.getRemoveNodeIds().length > 0) {
                nodeKeys.addAll(bpmProcessConfigurationMapper.selectNodeKeyByIds(Arrays.asList(nodeVo.getRemoveNodeIds())));
            }
            iBpmNodeScriptRelevanceService.deleteBpmNodeScriptRelevanceByNodeKeys(nodeKeys);
            //新增节点脚本关系
            iBpmNodeScriptRelevanceService.insertBpmNodeScriptRelevance(nodeVo.getBpmNodeScriptRelevanceList());
        }
        // 删除废弃的节点
        if (nodeVo.getRemoveNodeIds().length > 0) {
            //要删除的节点更新状态
            for (Long removeNodeId : nodeVo.getRemoveNodeIds()) {
                BpmProcessConfiguration bpmProcessConfiguration = new BpmProcessConfiguration();
                bpmProcessConfiguration.setUpdateBy(SecurityUtils.getUsername());
                bpmProcessConfiguration.setUpdateById(SecurityUtils.getUserId());
                bpmProcessConfiguration.setUpdateTime(DateUtils.getNowDate());
                bpmProcessConfiguration.setId(removeNodeId);
                bpmProcessConfiguration.setDelFlag("2");
                bpmProcessConfigurationMapper.updateBpmProcessConfiguration(bpmProcessConfiguration);
            }
            //bpmProcessConfigurationMapper.deleteBpmProcessConfigurationByIds(nodeVo.getRemoveNodeIds());
        }
        return 1;
    }

    @Override
    public NodeVo selectByProcessByKey(String nodeProcessKey) {
        // 根据流程别名的到所有节点信息
        List<BpmProcessConfiguration> bpmProcessConfigurationList = bpmProcessConfigurationMapper.selectBpmProcessConfigurationList(new BpmProcessConfiguration(nodeProcessKey));
        // 根据节点别名得到所有脚本信息
        List<BpmNodeScriptRelevance> bpmNodeScriptRelevanceList = new ArrayList<>();
        // 根据节点别名得到所有执行用户信息
        List<BpmNodeHandleUser> bpmNodeHandleUserList = new ArrayList<>();
        bpmProcessConfigurationList.forEach(item -> {
            if (item.getNodeKey() != null)
                bpmNodeScriptRelevanceList.addAll(iBpmNodeScriptRelevanceService.selectBpmNodeScriptRelevanceList(new BpmNodeScriptRelevance(item.getNodeKey())));
            if (item.getNodeRolePermission() != null)
                bpmNodeHandleUserList.addAll(iBpmNodeHandleUserService.selectBpmNodeHandleUserList(new BpmNodeHandleUser(item.getNodeRolePermission())));
        });
        NodeVo nodeVo = new NodeVo();
        nodeVo.setBpmNodeHandleUserList(bpmNodeHandleUserList);
        nodeVo.setBpmProcessConfigurationList(bpmProcessConfigurationList);
        nodeVo.setBpmNodeScriptRelevanceList(bpmNodeScriptRelevanceList);
        return nodeVo;
    }
}
