/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.manager.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.springblade.common.utils.SnowFlakeUtil;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.log.logger.BladeLogger;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.node.ForestNodeMerger;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.manager.dto.FormElementDTO;
import org.springblade.manager.dto.WbsTreeBatchImportDTO;
import org.springblade.manager.dto.WbsTreeContractDTO;
import org.springblade.manager.dto.WbsTreeDTO2;
import org.springblade.manager.entity.*;
import org.springblade.manager.excel.WbsExcelBatchUtil;
import org.springblade.manager.excel.WbsExcelUtil;
import org.springblade.manager.mapper.*;
import org.springblade.manager.service.IWbsFormElementService;
import org.springblade.manager.service.IWbsTreeService;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.manager.vo.*;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * 服务实现类
 *
 * @author liuyc
 * @since 2022-04-25
 */
@Service
@AllArgsConstructor
public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree> implements IWbsTreeService {

    private final WbsTreeMapper wbsTreeMapper;
    private final IWbsFormElementService wbsFormElementService;
    private final WbsInfoMapper wbsInfoMapper;
    private final WbsTreeContractMapper wbsTreeContractMapper;
    private final WbsTreePrivateMapper wbsTreePrivateMapper;
    private final WbsTreePrivateServiceImpl wbsTreePrivateService;
    private final ProjectInfoMapper projectInfoMapper;


    @Override
    public IPage<WbsTreeVO> selectWbsTreePage(IPage<WbsTreeVO> page, WbsTreeVO wbsTree) {
        return page.setRecords(baseMapper.selectWbsTreePage(page, wbsTree));
    }

    @Override
    public List<WbsTreeVO> lazyTree(String wbsId, String tenantId, Long parentId) {
        if (AuthUtil.isAdministrator()) {
            tenantId = StringPool.EMPTY;
        }
        return ForestNodeMerger.merge(baseMapper.lazyTree(wbsId, tenantId, parentId));
    }

    @Override
    public List<WbsTreeVO> tree(String wbsId, String tenantId, String type) {
        return ForestNodeMerger.merge(baseMapper.tree(wbsId, tenantId, type));
    }

    @Override
    public boolean submit(WbsTree dept) {
        if (Func.isEmpty(dept.getParentId())) {
            dept.setTenantId(AuthUtil.getTenantId());
            dept.setParentId(BladeConstant.TOP_PARENT_ID);
            dept.setAncestors(String.valueOf(BladeConstant.TOP_PARENT_ID));
        }
        if (dept.getParentId() > 0) {
            WbsTree parent = getById(dept.getParentId());
            if (Func.toLong(dept.getParentId()) == Func.toLong(dept.getId())) {
                throw new ServiceException("父节点不可选择自身!");
            }
            dept.setTenantId(parent.getTenantId());
            String ancestors = parent.getAncestors() + StringPool.COMMA + dept.getParentId();
            dept.setAncestors(ancestors);
        }
        if (dept.getMajorDataType() == null) {
            dept.setMajorDataType(0);
        }
        dept.setStatus(1);
        dept.setIsDeleted(BladeConstant.DB_NOT_DELETED);
        return saveOrUpdate(dept);
    }

    public boolean submit2(FormElementDTO dept) {
        if (Func.isEmpty(dept.getParentId())) {
            dept.setTenantId(AuthUtil.getTenantId());
            dept.setParentId(BladeConstant.TOP_PARENT_ID);
            dept.setAncestors(String.valueOf(BladeConstant.TOP_PARENT_ID));
        }
        if (dept.getParentId() > 0) {
            WbsTree parent = getById(dept.getParentId());
            if (Func.toLong(dept.getParentId()) == Func.toLong(dept.getId())) {
                throw new ServiceException("父节点不可选择自身!");
            }
            dept.setTenantId(parent.getTenantId());
            String ancestors = parent.getAncestors() + StringPool.COMMA + dept.getParentId();
            dept.setAncestors(ancestors);
            //设置表示该父节点下存在表单
            baseMapper.updateIsExistFormById(parent.getId());
        }
        //设置类型默认值为 '2' 表单
        dept.setType(2);
        dept.setIsDeleted(BladeConstant.DB_NOT_DELETED);
        return saveOrUpdate(dept);

    }

    public boolean submit3(WbsTree dept) {
        if (Func.isEmpty(dept.getParentId())) {
            dept.setTenantId(AuthUtil.getTenantId());
            dept.setParentId(BladeConstant.TOP_PARENT_ID);
            dept.setAncestors(String.valueOf(BladeConstant.TOP_PARENT_ID));
        }
        if (dept.getParentId() > 0) {
            WbsTree parent = getById(dept.getParentId());
            if (Func.toLong(dept.getParentId()) == Func.toLong(dept.getId())) {
                throw new ServiceException("父节点不可选择自身!");
            }
            dept.setTenantId(parent.getTenantId());
            String ancestors = parent.getAncestors() + StringPool.COMMA + dept.getParentId();
            dept.setAncestors(ancestors);
            //设置表示该父节点下存在表单
            baseMapper.updateIsExistFormById(parent.getId());
        }
        //设置类型默认值为 '2' 表单
        dept.setType(2);
        dept.setIsDeleted(BladeConstant.DB_NOT_DELETED);
        return saveOrUpdate(dept);

    }

    /**
     * wbs元素表、元素批量导入
     * @param excelFile
     * @param wbsTree
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean importWbsTreeTableAndForm(MultipartFile excelFile, WbsTree wbsTree) {
        String canonicalPath = null;
        try {
            //解析excel
            File file = WbsExcelBatchUtil.convert(excelFile);
            canonicalPath = file.getCanonicalPath();
            WbsExcelBatchUtil excelUtil = new WbsExcelBatchUtil();
            ArrayList<Map<String, String>> result = excelUtil.readExcelToObj(canonicalPath);
            List<Map<String, String>> maps = WbsExcelBatchUtil.removeRepeatMapByKey(result, "表名");
            assert maps != null;
            //创建表单，获取Id、deptName、initTableName集合
            List<WbsTreeBatchImportDTO> list = new ArrayList<>();
            for (Map<String, String> map : maps) {
                String deptName = map.get("表名");
                if (deptName.length() > 100 || deptName.length() < 1) {
                    throw new ServiceException("表名长度错误,输入范围1-100个字符长度");
                }
                wbsTree.setWbsId(wbsTree.getWbsId());
                wbsTree.setDeptName(deptName);
                wbsTree.setTableType(getTableType(map.get("表类型")));
                //初始化实体表名
                Long id = SnowFlakeUtil.getId();
                wbsTree.setId(id);
                String initTableName = "m_wbs_form_" + DateUtil.time() + "_" + id.toString();
                wbsTree.setInitTableName(initTableName);
                //创建表单
                submit3(wbsTree);
                //创建对应实体表
                initTable(initTableName);
                //返回信息
                WbsTreeBatchImportDTO wbsTreeBatchImportDTO = new WbsTreeBatchImportDTO();
                wbsTreeBatchImportDTO.setId(id);
                wbsTreeBatchImportDTO.setTableName(deptName);
                wbsTreeBatchImportDTO.setInitTableName(initTableName);
                list.add(wbsTreeBatchImportDTO);
            }
            //创建元素、修改新增对应实体表字段
            list.forEach(i -> {
                for (Map<String, String> map : result) {
                    Long elementTableId = i.getId();
                    String tableName = i.getTableName();
                    String initTableName = i.getInitTableName();
                    int keyNumb = 0;
                    if (tableName.equals(map.get("表名"))) {
                        keyNumb++;
                        WbsFormElement wbsFormElement = new WbsFormElement();
                        wbsFormElement.setEName(map.get("字段名"));
                        String key = "key_" + keyNumb;
                        wbsFormElement.setEKey(key);
                        wbsFormElement.setFId(String.valueOf(elementTableId));
                        wbsFormElement.setELength(getElementLength(map.get("数据类型")));
                        wbsFormElement.setEType(getElementType(map.get("数据类型")));
                        wbsFormElement.setEInspectionMethod(map.get("计算公式、方法或数值"));
                        wbsFormElement.setEAllowDeviation(map.get("允许偏差范围"));
                        wbsFormElement.setRemark(map.get("备注"));
                        wbsFormElementService.save(wbsFormElement);
                        //初始化实体表字段
                        baseMapper.alterTableFiled(initTableName,
                                wbsFormElement.getEKey(),
                                getInitTableFiledType(wbsFormElement.getEType()),
                                wbsFormElement.getELength());
                    }
                }
            });
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            File file2 = new File(canonicalPath);
            if (file2.isFile() && file2.exists()) {
                file2.delete();
                System.gc();
            }
        }
        return false;
    }

    private Boolean initTable(String tableName) {
        //建表
        Integer row = baseMapper.createTable(tableName);
        if (row >= 0) {
            return true;
        }
        return false;
    }

    private String getInitTableFiledType(Integer type) {
        switch (type) {
            case 2:
                return "bigint"; //整数
            case 3:
                return "decimal"; //小数
            case 4:
                return "datetime"; //日期
            case 5:
                return "bigint";  //数值
            case 6:
                return "varchar"; //签名
            case 7:
                return "varchar"; //文件
            case 1:
            default:
                return "varchar"; //字符串
        }
    }

    private Integer getElementType(String type) {
        switch (type) {
            case "字符串":
                return 1;
            case "整数":
                return 2;
            case "小数":
                return 3;
            case "日期":
                return 4;
            case "数值":
                return 5;
            case "签名":
                return 6;
            case "文件":
                return 7;
            default:
                return 0;
        }
    }

    private Integer getElementLength(String type) {
        switch (type) {
            case "字符串":
            case "签名":
            case "文件":
                return 1000;
            case "整数":
            case "数值":
                return 255;
            case "小数":
                return 65;
            case "日期":
            default:
                return 0;
        }
    }

    private Integer getTableType(String tableType) {
        switch (tableType) {
            case "检验表":
                return 1;
            case "记录表":
                return 2;
            case "通用表":
                return 3;
            case "监表":
                return 4;
            case "评定表":
                return 5;
            case "测量表":
                return 6;
            case "竣工表":
                return 7;
            case "汇总表":
                return 8;
            case "试验记录表":
                return 9;
            case "试验报告表":
                return 10;
            default:
                return 0;
        }
    }


    @Override
    public List<WbsNodeTableVO> selectByNodeTable(String id) {
        //查询节点下的所有表单
        List<WbsNodeTableVO> wbsNodeTableVOS = wbsTreeMapper.selectByNodeTable(id);
        return wbsNodeTableVOS;
    }

    @Override
    public boolean removeTableById(String id) {
        Integer integer = wbsTreeMapper.removeTableById(id);
        if (integer > 0) {
            return true;
        }
        return false;
    }

    @Override
    public List<WbsFormElementVO> selectFormElements(String id) {
        List<WbsFormElementVO> wbsFormElements = wbsTreeMapper.selectFormElements(id);
        return wbsFormElements;
    }

    private String selectTableIdByTableName(String id) {
        QueryWrapper<WbsTree> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", id);
        WbsTree wbsTree = wbsTreeMapper.selectOne(queryWrapper);
        if (!("").equals(wbsTree) && wbsTree != null) {
            return "-1";

        }
        assert wbsTree != null;
        return String.valueOf(wbsTree.getId());
    }

    @Override
    public String importWbsTree(MultipartFile excelFile, WbsTree wbsTreeFu, WbsTree wbsTree1) throws IOException {
        //赋值
        wbsTreeFu.setAncestors("0");
        wbsTree1.setProjectNodeId(wbsTree1.getId());
        //获取文件路径
        File file = WbsExcelUtil.convert(excelFile);
        String canonicalPath = file.getCanonicalPath();
        try {
            //解析excel
            WbsExcelUtil excelUtil = new WbsExcelUtil();
            ArrayList<Map<String, String>> result = excelUtil.readExcelToObj(canonicalPath);
            for (Map<String, String> map : result) {
                map.forEach((nodeType, nodeName) -> {
                    WbsTree wbsTreeZi = new WbsTree();
                    if (StringUtils.isNotEmpty(nodeName)) {
                        //初始化默认值
                        wbsTreeZi.setTenantId(AuthUtil.getTenantId());
                        wbsTreeZi.setDeptName(nodeName);
                        wbsTreeZi.setDeptCategory(Integer.valueOf(nodeType));
                        wbsTreeZi.setWbsId(wbsTreeFu.getWbsId());
                        wbsTreeZi.setParentId(wbsTreeFu.getParentId());
                        wbsTreeZi.setAncestors(wbsTreeFu.getAncestors());
                        wbsTreeZi.setProjectNodeId(wbsTree1.getProjectNodeId());
                        //新增节点返回未创建成功查询出来的wbsTree对象、创建成功后的wbsTreeZi对象
                        WbsTree wbsTree = importTree(wbsTreeZi);
                        //后置初始化默认值
                        if (wbsTree == null) {
                            Long id = wbsTreeZi.getId();
                            //设置ancestors祖级id集合
                            StringBuilder stringBuffer = new StringBuilder();
                            StringBuilder appendStr = stringBuffer.append(",").append(wbsTreeZi.getParentId());
                            String ancestors = wbsTreeZi.getAncestors() + appendStr;
                            //修改ancestors的值
                            updateData(ancestors, id);
                            wbsTreeFu.setParentId(id);
                            wbsTreeFu.setAncestors(ancestors);
                        } else {
                            wbsTreeFu.setParentId(wbsTree.getId());
                            wbsTreeFu.setAncestors(wbsTree.getAncestors());
                        }
                    }
                });
            }
            //修改根节点ProjectNodeId
            baseMapper.updateById(wbsTree1);
            return "2";
        } catch (Exception e) {
            return "1";
        } finally {
            File file2 = new File(canonicalPath);
            if (file2.isFile() && file2.exists()) {
                file2.delete();
                System.gc();
            }
        }
    }

    private WbsTree importTree(WbsTree wbsTreeZi) {
        //查重
        QueryWrapper<WbsTree> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("wbs_id", wbsTreeZi.getWbsId());
        queryWrapper.eq("dept_name", wbsTreeZi.getDeptName());
        queryWrapper.eq("dept_category", wbsTreeZi.getDeptCategory());
        queryWrapper.eq("project_node_id", wbsTreeZi.getProjectNodeId());
        queryWrapper.ne("ancestors", wbsTreeZi.getAncestors());
        WbsTree wbsTrees = baseMapper.selectOne(queryWrapper);
        //去重
        if (wbsTrees == null) {
            //初始化默认值
            wbsTreeZi.setStatus(1);
            wbsTreeZi.setType(1);
            wbsTreeZi.setMajorDataType(0);
            if (wbsTreeZi.getDeptCategory() == 6) {
                wbsTreeZi.setIsConcrete(0);
                wbsTreeZi.setIsExpernode(0);
            }
            baseMapper.insert(wbsTreeZi);
        }
        //TODO 暂未处理重复条新增问题
        return wbsTrees;
    }

    @Override
    public int deleteBatchByProjectNodeId(Long projectNodeId) {
        return baseMapper.deleteBatchProjectNodeId(projectNodeId);
    }

    @Override
    public WbsTree selectGenNodeByWbsId(Long id) {
        return baseMapper.selectByWbsId(id);
    }

    @Override
    public List<WbsTree> findByWbsTreeNode(String ids) {
        return baseMapper.selectList(Wrappers.<WbsTree>query().lambda()
                .eq(WbsTree::getWbsId, ids)
                .ne(WbsTree::getParentId, 0)
                .eq(WbsTree::getStatus, 1)
                .eq(WbsTree::getIsDeleted, 0));
    }

    @Override
    public List<SaveUserInfoByProjectVO2> findProjectAndContractList(Long userId) {
        List<SaveUserInfoByProjectVO2> list = baseMapper.selectListByUserId(userId);
        return list;
    }

    @Override
    public List<WbsTreeDTO2> findWbsTreeSameLevel(String parentId) {
        List<WbsTreeDTO2> trees = baseMapper.selectWbsTreeListByParentId(parentId);
        return trees;
    }

    @Override
    public boolean wbsTreeSort(List<WbsTreeDTO2> wbsTreeList) {
        int number = 1;
        for (WbsTreeDTO2 wbsTree : wbsTreeList) {
            wbsTree.setSort(number);
            //修改sort
            baseMapper.updateSortById(wbsTree.getId(), wbsTree.getSort());
            number++;
        }
        return true;
    }

    @Override
    public int deleteLogicByWbsId(String ids) {
        return baseMapper.deleteLogicByWbsId(ids);
    }

    @Override
    public List<WbsTree> selectByWbsId(String id) {
        return baseMapper.selectList(Wrappers.<WbsTree>query().lambda()
                .eq(WbsTree::getParentId, id)
                .eq(WbsTree::getStatus, 1)
        );
    }

    private boolean updateData(String ancestors, Long id) {
        Integer row = baseMapper.updateById2(ancestors, id);
        if (row > 0) {
            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String submitWbsTreeInProject(WbsTreeContractDTO pawDTO) {
        String wbsTreeIds = pawDTO.getWbsTreeIds();
        /*if (StringUtils.isEmpty(wbsTreeIds)) {
            throw new ServiceException("请选择需要关联的节点树");
        }*/
        String[] ids = wbsTreeIds.split(",");
        List<String> idList1 = Arrays.asList(ids);
        List<String> idList2 = new ArrayList<>();
        //查询出当前私有库下所有的wbs节点
        List<WbsTreePrivate> wbsTreePrivates = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>query().lambda()
                .eq(WbsTreePrivate::getWbsId, pawDTO.getWbsId())
                .eq(WbsTreePrivate::getProjectId, pawDTO.getProjectId())
                .eq(WbsTreePrivate::getType, 1)
        );
        for (WbsTreePrivate wbsTreePrivate : wbsTreePrivates) {
            idList2.add(String.valueOf(wbsTreePrivate.getId()));
        }
        List<String> diffrent = WbsTreeContractServiceImpl.getDiffrent(idList1, idList2);
        if (diffrent.size() == 0) {
            List<String> tableId1 = new ArrayList<>();
            List<String> tableId2 = new ArrayList<>();
            //查找wbs总树节点下是否新增了元素表，进行同步更新到wbs私有树中
            List<WbsTree> allNodeList = findAllNodeList(wbsTreeIds);
            List<WbsTree> wbsTreeListAll = new ArrayList<>();
            for (WbsTree wbsTree : allNodeList) {
                List<WbsTree> wbsTreeList = wbsTreeMapper.selectList(Wrappers.<WbsTree>query().lambda()
                        .eq(WbsTree::getWbsId, pawDTO.getWbsId())
                        .eq(WbsTree::getType, 2)
                        .eq(WbsTree::getParentId, wbsTree.getId())
                );
                wbsTreeListAll.addAll(wbsTreeList);
            }
            for (WbsTree wbsTree : wbsTreeListAll) {
                tableId1.add(String.valueOf(wbsTree.getId()));
            }
            //获取项目私有树下所有的元素表
            List<WbsTreePrivate> wbsTreePrivates1 = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>query().lambda()
                    .eq(WbsTreePrivate::getWbsId, pawDTO.getWbsId())
                    .eq(WbsTreePrivate::getProjectId, pawDTO.getProjectId())
                    .eq(WbsTreePrivate::getType, 2)
            );
            for (WbsTreePrivate wbsTreePrivate : wbsTreePrivates1) {
                tableId2.add(String.valueOf(wbsTreePrivate.getId()));
            }
            List<String> diffrent1 = WbsTreeContractServiceImpl.getDiffrent(tableId1, tableId2);
            if (diffrent1.size() == 0) {
                throw new ServiceException("未进行任何操作");
            } else {
                if (tableId1.size() > tableId2.size()) {
                    //同步元素表
                    for (String tableId : diffrent1) {
                        WbsTree wbsTree = wbsTreeMapper.selectById(tableId);
                        Long snowId1 = SnowFlakeUtil.getId();
                        wbsTreePrivateMapper.insertCombination1(snowId1, wbsTree, pawDTO.getWbsType(), pawDTO.getProjectId());
                    }
                    return "1";
                }
                //TODO 是否要同步删除元素表
            }
        } else {
            if (idList1.size() > idList2.size()) {
                //新增前去删除当前项目已经引用的旧的私有节点，避免重复引用
                wbsTreePrivateMapper.delete(Wrappers.<WbsTreePrivate>query().lambda().eq(WbsTreePrivate::getProjectId, pawDTO.getProjectId()));

                for (String id : diffrent) {
                    //项目私有wbs节点库存在该节点且为删除状态,那么修改is_deleted=0,否则新增
                    WbsTreePrivate wbsTreePrivate = wbsTreePrivateMapper.selectByCondition2(id, pawDTO.getProjectId(), pawDTO.getWbsId());

                    if (wbsTreePrivate != null) {
                        //修改该节点
                        wbsTreePrivateMapper.updateByCondition(id, pawDTO.getProjectId(), pawDTO.getWbsId());
                        //修改该节点下元素表
                        wbsTreePrivateMapper.updateTableByCondition(id, pawDTO.getProjectId(), pawDTO.getWbsId());
                    } else {
                        //引用WBS公共库
                        if (pawDTO.getReferenceType().equals("public")) {
                            WbsTree wbsTree = wbsTreeMapper.selectById(id);
                            if (wbsTree != null) {
                                Long snowId = SnowFlakeUtil.getId();
                                wbsTreePrivateMapper.insertCombination1(snowId, wbsTree, pawDTO.getWbsType(), pawDTO.getProjectId());
                                //查询该节点下是否有元素表
                                Long tableParentId = wbsTree.getId();
                                List<WbsTree> wbsTreeTableList = wbsTreeMapper.selectIsTable(tableParentId);
                                if (wbsTreeTableList.size() > 0) {
                                    //新增元素表
                                    for (WbsTree tree : wbsTreeTableList) {
                                        //判重
                                        WbsTreePrivate wbsTreePrivates1 = wbsTreePrivateMapper.selectOne(Wrappers.<WbsTreePrivate>query().lambda()
                                                .eq(WbsTreePrivate::getId, tree.getId())
                                                .eq(WbsTreePrivate::getWbsId, pawDTO.getWbsId())
                                                .eq(WbsTreePrivate::getProjectId, pawDTO.getProjectId())
                                                .eq(WbsTreePrivate::getParentId, tree.getParentId())
                                                .eq(WbsTreePrivate::getDeptName, tree.getDeptName())
                                                .eq(WbsTreePrivate::getType, 2)
                                        );
                                        if (wbsTreePrivates1 == null) {
                                            Long snowId1 = SnowFlakeUtil.getId();
                                            wbsTreePrivateMapper.insertCombination1(snowId1, tree, pawDTO.getWbsType(), pawDTO.getProjectId());
                                        }
                                    }
                                }
                                //保存引用模板id、类型
                                projectInfoMapper.updateTemplateIdById(pawDTO.getProjectId(), pawDTO.getWbsId(), "public");
                            }
                        } else if (pawDTO.getReferenceType().equals("private")) {
                            //引用项目WBS私有库 通过referencePrivateWbsProjectId 查询引用的私有库
                            WbsTreePrivate wbsTreePrivate1 = wbsTreePrivateMapper.selectByCondition(id, pawDTO.getWbsId(), pawDTO.getReferencePrivateWbsProjectId());
                            //引用的私有库根节点primaryKeyId,赋值给新增的私有树wbsId字段
                            String wbsId = String.valueOf(pawDTO.getPrimaryKeyId());
                            if (wbsTreePrivate1 == null) {
                                throw new ServiceException("当前WBS私有树不存在,请重新选择");
                            }
                            wbsTreePrivate1.setWbsId(wbsId);
                            Long snowId = SnowFlakeUtil.getId();

                            //新增
                            wbsTreePrivateMapper.insertCombination2(snowId, wbsTreePrivate1, pawDTO.getProjectId());  //pawDTO.getProjectId() 为当前项目id
                            //查询该节点下是否有元素表
                            List<WbsTree> wbsTreeTableList = wbsTreePrivateMapper.selectIsTable(wbsTreePrivate1.getId(), pawDTO.getReferencePrivateWbsProjectId());
                            if (wbsTreeTableList.size() > 0) {
                                for (WbsTree tree : wbsTreeTableList) {
                                    //判重
                                    WbsTreePrivate wbsTreePrivates1 = wbsTreePrivateMapper.selectOne(Wrappers.<WbsTreePrivate>query().lambda()
                                            .eq(WbsTreePrivate::getId, tree.getId())
                                            .eq(WbsTreePrivate::getWbsId, pawDTO.getWbsId())
                                            .eq(WbsTreePrivate::getProjectId, pawDTO.getProjectId())
                                            .eq(WbsTreePrivate::getParentId, tree.getParentId())
                                            .eq(WbsTreePrivate::getDeptName, tree.getDeptName())
                                            .eq(WbsTreePrivate::getType, 2)
                                    );
                                    if (wbsTreePrivates1 == null) {
                                        Long snowId1 = SnowFlakeUtil.getId();
                                        tree.setWbsId(String.valueOf(pawDTO.getPrimaryKeyId()));
                                        wbsTreePrivateMapper.insertCombination1(snowId1, tree, pawDTO.getWbsType(), pawDTO.getProjectId());
                                    }
                                }
                            }
                            //保存引用模板id、类型
                            projectInfoMapper.updateTemplateIdById(pawDTO.getProjectId(), pawDTO.getPrimaryKeyId(), "private");
                        }
                    }
                }
            } else {
                for (String id : diffrent) {
                    //删除当前节点
                    wbsTreePrivateMapper.deleteByCondition(id, pawDTO.getWbsId(), pawDTO.getProjectId());
                    //删除节点下元素表 id = parentId
                    wbsTreePrivateMapper.deleteByCondition2(id, pawDTO.getWbsId(), pawDTO.getProjectId());
                }
            }
        }
        return "2";
    }

    public List<WbsTree> findAllNodeList(String wbsTreeIds) {
        String[] ids = wbsTreeIds.split(",");
        List<Long> idList = new ArrayList<>();
        for (String id : ids) {
            idList.add(Long.valueOf(id));
        }
        return baseMapper.selectBatchIds(idList);
    }

    @Override
    public WbsTreeAllListVO findWbsTreeList(Integer type) {
        WbsTreeAllListVO wbsTreeAllListVO = new WbsTreeAllListVO();
        //查询Wbs总树
        List<WbsInfo> wbsInfos = wbsInfoMapper.selectAll(type);
        wbsTreeAllListVO.setWbsInfos(wbsInfos);
        //查询项目私有树 默认type=1质检
        List<WbsTreePrivate> wbsTreePrivates = wbsTreePrivateMapper.selectAll(type);
        wbsTreeAllListVO.setWbsTreePrivates(wbsTreePrivates);
        return wbsTreeAllListVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R saveFormElement(FormElementDTO formElementDTO) {
        if (formElementDTO.getElementList().size() <= 0) {
            return R.fail("操作失败,请先添加表单元素");
        }
        String filedName = "";
        String filedType = "";
        String filedLength = "";
        for (WbsFormElement wbsFormElement : formElementDTO.getElementList()) {
            filedName = getPinyin(wbsFormElement.getEName(), "");
            filedType = String.valueOf(wbsFormElement.getEType());
            filedLength = String.valueOf(wbsFormElement.getELength());
        }
        if (StringUtils.isEmpty(filedName) || StringUtils.isEmpty(filedType) || StringUtils.isEmpty(filedLength)) {
            return R.fail("操作失败,请完整填写元素参数");
        }

        String deptName = formElementDTO.getDeptName();
        if (deptName.length() > 100 || deptName.length() < 1) {
            throw new ServiceException("表名长度错误,输入范围1-100个字符长度");
        }
        //初始化表名
        //String realName = getFirstSpell(deptName);
        Long id = SnowFlakeUtil.getId();
        String newTableName = "m_wbs_form_" + DateUtil.time() + "_" + id.toString();
        formElementDTO.setInitTableName(newTableName);

        //创建元素表
        boolean b1 = submit2(formElementDTO);

        List<WbsFormElement> elementList = formElementDTO.getElementList();
        int i = 1;
        for (WbsFormElement wbsFormElement : elementList) {
            if (wbsFormElement.getEType() == 1 && (wbsFormElement.getELength() > 1000 || wbsFormElement.getELength() < 10)) {
                throw new ServiceException("请输入正确的字符串长度,范围为10-1000");
            }
            if (wbsFormElement.getEType() == 2 && (wbsFormElement.getELength() > 255 || wbsFormElement.getELength() < 10)) {
                throw new ServiceException("请输入正确的整数长度,范围为10-255");
            }
            if (wbsFormElement.getEType() == 3 && (wbsFormElement.getELength() > 65 || wbsFormElement.getELength() < 10)) {
                throw new ServiceException("请输入正确的小数长度,范围为10-65");
            }
            //当前元素表中元素对应实体表唯一key值、fId
            wbsFormElement.setEKey("key_" + i++);
            wbsFormElement.setFId(String.valueOf(formElementDTO.getId()));
        }
        //新增元素
        boolean b2 = wbsFormElementService.saveBatch(elementList);

        //找到当前元素表中所有元素
        List<WbsFormElement> list = wbsFormElementService.selectElementListByFid(String.valueOf(formElementDTO.getId()));
        //初始化实体表
        Boolean b3 = wbsFormElementService.initTable(list, newTableName);
        if (b1 && b2 && b3) {
            return R.data(formElementDTO, "新增表单、元素、初始化实体表成功");
        } else {
            throw new ServiceException("操作失败");
        }
    }

    /**
     * 获取汉字串拼音首字母，英文字符不变
     *
     * @param chinese 汉字串
     * @return 汉语拼音首字母
     */
    public static String getFirstSpell(String chinese) {
        StringBuffer pybf = new StringBuffer();
        char[] arr = chinese.toCharArray();
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
        defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] > 128) {
                try {
                    String[] temp = PinyinHelper.toHanyuPinyinStringArray(arr[i], defaultFormat);
                    if (temp != null) {
                        pybf.append(temp[0].charAt(0));
                    }
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                    e.printStackTrace();
                }
            } else {
                pybf.append(arr[i]);
            }
        }
        return pybf.toString().replaceAll("\\W", "").trim();
    }

    /**
     * 汉字转拼音，英文字符不变
     *
     * @param text
     * @param separator
     * @return
     */
    public static String getPinyin(String text, String separator) {
        //text 文本, separator 转换后添加的分隔符
        char[] chars = text.toCharArray();
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        // 设置大小写
        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        // 设置声调表示方法
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        // 设置字母u表示方法
        format.setVCharType(HanyuPinyinVCharType.WITH_V);
        String[] s;
        String rs = "";
        try {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < chars.length; i++) {
                // 判断是否为汉字字符
                if (String.valueOf(chars[i]).matches("[\\u4E00-\\u9FA5]+")) {
                    s = PinyinHelper.toHanyuPinyinStringArray(chars[i], format);
                    if (s != null) {
                        sb.append(s[0]).append(separator);
                        continue;
                    }
                }
                sb.append(chars[i]);
                if ((i + 1 >= chars.length) || String.valueOf(chars[i + 1]).matches("[\\u4E00-\\u9FA5]+")) {
                    sb.append(separator);
                }
            }
            rs = sb.substring(0, sb.length());
        } catch (BadHanyuPinyinOutputFormatCombination e) {
            e.printStackTrace();
        }
        return rs;
    }

    public int updateByCondition(Long id, String wbsName, Integer status) {
        int row = baseMapper.updateByCondition(id, wbsName, status);
        return row;
    }
}
