package com.engine.organization.service.impl;

import com.api.browser.bean.SearchConditionItem;
import com.engine.core.impl.Service;
import com.engine.organization.entity.DeleteParam;
import com.engine.organization.entity.company.bo.CompBO;
import com.engine.organization.entity.company.po.CompPO;
import com.engine.organization.entity.department.bo.DepartmentBO;
import com.engine.organization.entity.department.po.DepartmentPO;
import com.engine.organization.entity.hrmresource.bo.ResourceBO;
import com.engine.organization.entity.hrmresource.po.ResourcePO;
import com.engine.organization.entity.job.bo.JobBO;
import com.engine.organization.entity.job.po.JobPO;
import com.engine.organization.entity.resume.po.HrmFamilyInfoPO;
import com.engine.organization.entity.resume.po.PersonnelResumeColumn;
import com.engine.organization.entity.resume.po.PersonnelResumePO;
import com.engine.organization.entity.resume.po.PersonnelResumeTable;
import com.engine.organization.entity.searchtree.SearchTree;
import com.engine.organization.entity.searchtree.SearchTreeParams;
import com.engine.organization.enums.ModuleTypeEnum;
import com.engine.organization.mapper.comp.CompMapper;
import com.engine.organization.mapper.department.DepartmentMapper;
import com.engine.organization.mapper.job.JobMapper;
import com.engine.organization.mapper.resource.HrmResourceMapper;
import com.engine.organization.service.PersonnelResumeService;
import com.engine.organization.util.MenuBtn;
import com.engine.organization.util.OrganizationAssert;
import com.engine.organization.util.OrganizationFormItemUtil;
import com.engine.organization.util.db.MapperProxyFactory;
import com.engine.organization.util.detach.DetachUtil;
import com.engine.organization.util.page.PageUtil;
import com.engine.organization.util.tree.SearchTreeUtil;
import com.engine.organization.util.word.CustomXWPFDocument;
import com.engine.organization.util.word.WordUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import weaver.general.GCONST;
import weaver.general.StringUtil;
import weaver.general.Util;


import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author:dxfeng
 * @createTime: 2022/12/28
 * @version: 1.0
 */
public class PersonnelResumeServiceImpl extends Service implements PersonnelResumeService {


    private DepartmentMapper getDepartmentMapper() {
        return MapperProxyFactory.getProxy(DepartmentMapper.class);
    }

    private CompMapper getCompMapper() {
        return MapperProxyFactory.getProxy(CompMapper.class);
    }

    private JobMapper getJobMapper() {
        return MapperProxyFactory.getProxy(JobMapper.class);
    }

    private HrmResourceMapper getHrmResourceMapper() {
        return MapperProxyFactory.getProxy(HrmResourceMapper.class);
    }

    @Override
    public Map<String, Object> getSearchTree(SearchTreeParams params) {
        // 查询所有满足条件的人员ID、根据人员向上查找对应的组织架构
        List<ResourcePO> resourcePOList = null;
        if (CollectionUtils.isNotEmpty(params.getSubcompanyid1()) || CollectionUtils.isNotEmpty(params.getDepartmentid()) || CollectionUtils.isNotEmpty(params.getJobId()) || CollectionUtils.isNotEmpty(params.getResourceId())) {
            params.setPersonnelScreening(true);
            // 人员筛选
            resourcePOList = getHrmResourceMapper().getPersonnelScreening(params.getSubcompanyid1(), params.getDepartmentid(), params.getJobId(), params.getResourceId());
            resourcePOList.removeIf(item->!item.getLastName().contains(params.getKeyword()));
        }
        List<SearchTree> treeList = getFilterDatas(params, resourcePOList);
        return SearchTreeUtil.getSearchTree(Util.null2String(params.getType()), treeList);
    }

    @Override
    public Map<String, Object> getResumeList(Integer uId) {
        Map<String, Object> resultMap = new HashMap<>();
        // 根据ID查询用户信息
        PersonnelResumePO personnelResumePO = getHrmResourceMapper().getPersonnelResumeById(uId);
        OrganizationAssert.notNull(personnelResumePO, "未找到对应人员");
        resultMap.put("lastName", Util.null2String(personnelResumePO.getLastName()));
        resultMap.put("sex", Util.null2String(personnelResumePO.getSex()));
        resultMap.put("birthday", Util.null2String(personnelResumePO.getBirthday()));
        resultMap.put("image", Util.null2String(personnelResumePO.getImage()));
        resultMap.put("native", Util.null2String(personnelResumePO.getNativePlace()));
        resultMap.put("politics", Util.null2String(personnelResumePO.getPolitics()));
        resultMap.put("department", Util.null2String(personnelResumePO.getDepartment()));
        resultMap.put("marriage", Util.null2String(personnelResumePO.getMarriage()));
        resultMap.put("jobtitle", Util.null2String(personnelResumePO.getJobTitle()));
        resultMap.put("companystartdate", Util.null2String(personnelResumePO.getCompanyStartDate()));
        resultMap.put("workstartdate", Util.null2String(personnelResumePO.getWorkStartDate()));
        resultMap.put("idCard", Util.null2String(personnelResumePO.getIdCard()));
        resultMap.put("address", Util.null2String(personnelResumePO.getAddress()));
        resultMap.put("telephone", Util.null2String(personnelResumePO.getTelephone()));
        resultMap.put("email", Util.null2String(personnelResumePO.getEmail()));
        resultMap.put("selfStatement", "");

        // 简历相关表格，待拓展
        resultMap.put("tables", getPersonnelResumeTable(uId));

        return resultMap;
    }

    @Override
    public Map<String, Object> hasRight() {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("hasRight", true);
        ArrayList<MenuBtn> topMenuList = new ArrayList<>();
        ArrayList<MenuBtn> rightMenuList = new ArrayList<>();
        // 新增
        topMenuList.add(MenuBtn.builder().isBatch("0").isTop("1").menuFun("screening").menuIcon("icon-coms-man").menuName("人员筛选").type("BTN_Screening").build());
        topMenuList.add(MenuBtn.builder().isBatch("0").isTop("1").menuFun("currentExport").menuIcon("icon-coms-export").menuName("导出当前").type("BTN_CurrentExport").build());
        topMenuList.add(MenuBtn.builder().isBatch("0").isTop("1").menuFun("mergeExport").menuIcon("icon-coms02-coms2-Batch-export").menuName("全部导出（合并）").type("BTN_MergeExport").build());
        topMenuList.add(MenuBtn.builder().isBatch("0").isTop("1").menuFun("allExport").menuIcon("icon-coms02-coms2-export").menuName("全部导出").type("BTN_AllExport").build());

        resultMap.put("topMenu", topMenuList);
        // 新增
        rightMenuList.add(MenuBtn.builder().isBatch("0").isTop("0").menuFun("screening").menuIcon("icon-coms-man").menuName("人员筛选").type("BTN_Screening").build());
        rightMenuList.add(MenuBtn.builder().isBatch("0").isTop("0").menuFun("currentExport").menuIcon("icon-coms-export").menuName("导出当前").type("BTN_CurrentExport").build());
        rightMenuList.add(MenuBtn.builder().isBatch("0").isTop("0").menuFun("mergeExport").menuIcon("icon-coms02-coms2-Batch-export").menuName("全部导出（合并）").type("BTN_MergeExport").build());
        rightMenuList.add(MenuBtn.builder().isBatch("0").isTop("0").menuFun("allExport").menuIcon("icon-coms02-coms2-export").menuName("全部导出").type("BTN_AllExport").build());

        resultMap.put("rightMenu", rightMenuList);
        return resultMap;
    }

    @Override
    public String downloadPerResume(Integer type, HttpServletResponse response) throws Exception {

        //首先定义一个XWPFDocument 集合 这个对象可以进行word 解析 合并 还有下载都离不开这个对象
        List<CustomXWPFDocument> xwpfDocuments = new ArrayList<>();
        //模板地址
        String outPutPath = GCONST.getRootPath() + "hrm" + File.separator + "import" + File.separator + "template" + File.separator;
        String filePath = outPutPath + "PerResume.docx";
        //创建压缩包位置
        File fileZip = new File(outPutPath + "wordZip");
        if (!fileZip.exists()) {
            fileZip.mkdirs();
        }
        // 处理赋值的数据
        List<Map<String, Object>> dataMapList = getAllResumeList();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
        String filesPath = outPutPath + "wordZip" + File.separator + "全部简历";
        String fileAllWordPath = outPutPath + "wordZip";
        String wordName = "全体人员简历(合并)";
        File files = new File(filesPath);
        if (!files.exists()) {
            files.mkdirs();
        } else {
            delFolder(files.getPath());
            files.mkdirs();
        }
        //处理所有数据
        for (int count = 0; count < dataMapList.size(); count++) {
            //处理单人数据
            Map<String, Object> paramMap = new HashMap<>();
            paramMap = dataMapList.get(count);
            WordUtil wordUtil = new WordUtil();
            //返回一个新的xwpfDocument对象
            File file = new File(filePath);
            CustomXWPFDocument doc = null;
            InputStream is = new FileInputStream(file);

            doc = new CustomXWPFDocument(is);
            wordUtil.replaceInPara(doc, paramMap);
            wordUtil.replaceInTable(doc, paramMap);
            xwpfDocuments.add(doc);
            is.close();

            String fileName = paramMap.get("${lastName}") + ".docx";
            System.out.println(fileName);
            FileOutputStream os = null;
            os = new FileOutputStream(filesPath + File.separator + new File(fileName));
            doc.write(os);
        }

        if (xwpfDocuments.size() > 0) {
            //这样第一步将所有word内容替换之后生成多个   xwpfDocument
            //现在将多个xwpfDocument 进行合并 追加 生成word文件
            CustomXWPFDocument xwpfDocument = xwpfDocuments.get(0);
            for (int i = 0; i < xwpfDocuments.size(); i++) {
                //每次的追加为了避免样式和格式混乱 加上分页符
                //当是只有一条数据的时候 直接输出
                if (i == 0) {
                    xwpfDocument = xwpfDocuments.get(0);
                    xwpfDocument.write(new FileOutputStream(fileAllWordPath + File.separator + new File(wordName + ".docx")));
                    continue;
                } else {
                    //当存在多条时候
                    xwpfDocument = mergeWord(xwpfDocument, xwpfDocuments.get(i));
                    xwpfDocument.write(new FileOutputStream(fileAllWordPath + File.separator + new File(wordName + ".docx")));
                }
            }
        }
        String resPath = fileAllWordPath + File.separator + new File(wordName + ".docx");
        if (type == 1) {
            compressFileToZip(filesPath);
            resPath = filesPath + ".zip";
        }
        return resPath;
    }

    // 简历相关表格，待拓展
    public List<PersonnelResumeTable> getPersonnelResumeTable(Integer uId){
        List<PersonnelResumeTable> tables = new ArrayList<>();
        List<PersonnelResumeColumn> insurancesTitles = new ArrayList<>();
        List<PersonnelResumeColumn> familyInfoTitles = new ArrayList<>();

        List<PersonnelResumeColumn> insuranceDatas = new ArrayList<>();
        insurancesTitles.add(PersonnelResumeColumn.builder().name("首次参保时间").colspans(2).rowspans(1).build());
        insurancesTitles.add(PersonnelResumeColumn.builder().name("养老保险").colspans(1).rowspans(1).build());
        insurancesTitles.add(PersonnelResumeColumn.builder().name("医疗保险").colspans(1).rowspans(1).build());
        insurancesTitles.add(PersonnelResumeColumn.builder().name("失业保险").colspans(1).rowspans(1).build());
        insurancesTitles.add(PersonnelResumeColumn.builder().name("住房公积金").colspans(1).rowspans(1).build());
        insurancesTitles.add(PersonnelResumeColumn.builder().name("企业年金").colspans(1).rowspans(1).build());

        insuranceDatas.add(PersonnelResumeColumn.builder().value("2022-10-02").colspans(2).rowspans(1).build());
        insuranceDatas.add(PersonnelResumeColumn.builder().value("80").colspans(1).rowspans(1).build());
        insuranceDatas.add(PersonnelResumeColumn.builder().value("36").colspans(1).rowspans(1).build());
        insuranceDatas.add(PersonnelResumeColumn.builder().value("360").colspans(1).rowspans(1).build());
        insuranceDatas.add(PersonnelResumeColumn.builder().value("180").colspans(1).rowspans(1).build());
        insuranceDatas.add(PersonnelResumeColumn.builder().value("20000").colspans(1).rowspans(1).build());
        tables.add(PersonnelResumeTable.builder().title("二、社会保险及住房公积金缴纳情况（单位/元）").columns(insurancesTitles).datas(Collections.singletonList(insuranceDatas)).build());

        // 家庭情况
        familyInfoTitles.add(PersonnelResumeColumn.builder().name("关系").colspans(1).rowspans(1).build());
        familyInfoTitles.add(PersonnelResumeColumn.builder().name("姓名").colspans(1).rowspans(1).build());
        familyInfoTitles.add(PersonnelResumeColumn.builder().name("工作单位").colspans(2).rowspans(1).build());
        familyInfoTitles.add(PersonnelResumeColumn.builder().name("职务").colspans(1).rowspans(1).build());
        familyInfoTitles.add(PersonnelResumeColumn.builder().name("住址").colspans(2).rowspans(1).build());


        List<HrmFamilyInfoPO> hrmFamilyInfoByUser = getHrmResourceMapper().getHrmFamilyInfoByUser(uId);
        if (CollectionUtils.isEmpty(hrmFamilyInfoByUser)) {
            hrmFamilyInfoByUser.add(new HrmFamilyInfoPO());
        }
        List<List<PersonnelResumeColumn>> objects = new ArrayList<>();
        for (HrmFamilyInfoPO hrmFamilyInfoPO : hrmFamilyInfoByUser) {
            List<PersonnelResumeColumn> familyInfoDatas = new ArrayList<>();
            familyInfoDatas.add(PersonnelResumeColumn.builder().value(hrmFamilyInfoPO.getTitle()).colspans(1).rowspans(1).build());
            familyInfoDatas.add(PersonnelResumeColumn.builder().value(hrmFamilyInfoPO.getMember()).colspans(1).rowspans(1).build());
            familyInfoDatas.add(PersonnelResumeColumn.builder().value(hrmFamilyInfoPO.getCompany()).colspans(2).rowspans(1).build());
            familyInfoDatas.add(PersonnelResumeColumn.builder().value(hrmFamilyInfoPO.getJobTitle()).colspans(1).rowspans(1).build());
            familyInfoDatas.add(PersonnelResumeColumn.builder().value(hrmFamilyInfoPO.getAddress()).colspans(2).rowspans(1).build());
            objects.add(familyInfoDatas);
        }
        tables.add(PersonnelResumeTable.builder().title("三、家庭成员信息（包括父母、配偶、子女）").columns(familyInfoTitles).datas(objects).build());
        return tables;
    }

    public List<Map<String, Object>> getAllResumeList() {
        List<PersonnelResumePO> personnelResumeList = getHrmResourceMapper().getPersonnelResumeList();
        OrganizationAssert.notNull(personnelResumeList, "未找到对应人员");
        List<Map<String, Object>> dataMapList = new ArrayList<>();
        for (PersonnelResumePO personnelResumePO : personnelResumeList) {
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("${lastName}", Util.null2String(personnelResumePO.getLastName()));
            resultMap.put("${sex}", Util.null2String(personnelResumePO.getSex()));
            resultMap.put("${birthday}", Util.null2String(personnelResumePO.getBirthday()));
            resultMap.put("${@image}", Util.null2String(personnelResumePO.getImageId()));
            resultMap.put("${native}", Util.null2String(personnelResumePO.getNativePlace()));
            resultMap.put("${politics}", Util.null2String(personnelResumePO.getPolitics()));
            resultMap.put("${department}", Util.null2String(personnelResumePO.getDepartment()));
            resultMap.put("${marriage}", Util.null2String(personnelResumePO.getMarriage()));
            resultMap.put("${jobtitle}", Util.null2String(personnelResumePO.getJobTitle()));
            resultMap.put("${companystartdate}", Util.null2String(personnelResumePO.getCompanyStartDate()));
            resultMap.put("${workstartdate}", Util.null2String(personnelResumePO.getWorkStartDate()));
            resultMap.put("${idCard}", Util.null2String(personnelResumePO.getIdCard()));
            resultMap.put("${address}", Util.null2String(personnelResumePO.getAddress()));
            resultMap.put("${telephone}", Util.null2String(personnelResumePO.getTelephone()));
            resultMap.put("${email}", Util.null2String(personnelResumePO.getEmail()));
            resultMap.put("${selfStatement}", "");
            List<PersonnelResumeTable> tables = getPersonnelResumeTable(personnelResumePO.getId());
            for (int t = 0; t < tables.size(); t++) {
                PersonnelResumeTable personnelResumeTable = tables.get(t);
                int length = personnelResumeTable.getColumns().size();
                if (personnelResumeTable.getDatas().size() > 0) {
                    List<List<PersonnelResumeColumn>> datas = personnelResumeTable.getDatas();
                    if (datas.size() > 0) {
                        List<PersonnelResumeColumn> dataList = datas.get(0);
                        for (int i = 0; i < length; i++) {
                            resultMap.put("${col" + t + i + "}", Util.null2String(dataList.get(i).getValue()));
                        }
                    }
                }
            }
            dataMapList.add(resultMap);
        }

        return dataMapList;
    }

    //两个对象进行追加
    public CustomXWPFDocument mergeWord(CustomXWPFDocument document, CustomXWPFDocument doucDocument2) throws Exception {
        CustomXWPFDocument src1Document = document;
        XWPFParagraph p = src1Document.createParagraph();
        //设置分页符
        p.setPageBreak(true);
        CTBody src1Body = src1Document.getDocument().getBody();
        CustomXWPFDocument src2Document = doucDocument2;
        CTBody src2Body = src2Document.getDocument().getBody();
        XWPFParagraph p2 = src2Document.createParagraph();

        //处理合并后文档图片冲突
        List<XWPFPictureData> allPictures = src2Document.getAllPictures();
        Map<String, String> map = new HashMap();
        for (XWPFPictureData picture : allPictures) {
            String before = src2Document.getRelationId(picture);
            //将原文档中的图片加入到目标文档中
            String after = src1Document.addPictureData(picture.getData(), Document.PICTURE_TYPE_JPEG);
            map.put(before, after);
        }

        XmlOptions optionsOuter = new XmlOptions();
        optionsOuter.setSaveOuter();
        String appendString = src2Body.xmlText(optionsOuter);
        String srcString = src1Body.xmlText();
        String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
        String mainPart = srcString.substring(srcString.indexOf(">") + 1, srcString.lastIndexOf("<"));
        String sufix = srcString.substring(srcString.lastIndexOf("<"));
        String addPart = appendString.substring(appendString.indexOf(">") + 1, appendString.lastIndexOf("<"));
        if (map != null && !map.isEmpty()) {
            ListIterator<Map.Entry<String, String>> i = new ArrayList<>(map.entrySet()).listIterator(map.size());
            LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<String, String>();
            while (i.hasPrevious()) {
                Map.Entry<String, String> entry = i.previous();
                linkedHashMap.put(entry.getKey(), entry.getValue());
            }
            Iterator it1 = linkedHashMap.entrySet().iterator();
            while (it1.hasNext()) {
                Map.Entry<String, String> entry = (Map.Entry<String, String>) it1.next();
                addPart = addPart.replace("<a:blip r:embed=\"" + entry.getKey(), "<a:blip r:embed=\"" + entry.getValue());
            }
        }
        CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart + sufix);
        src1Body.set(makeBody);
        return src1Document;
    }

    /**
     * @Title: compressAllFileZip
     * @Description: 传递文件路径压缩文件，传递文件夹路径压缩文件夹，注：空的文件夹不会出现在压缩包内
     * @param @param compresspath 需要压缩的文件夹的目录
     * @return void    返回类型
     * @throws
     */
    public static boolean compressFileToZip(String compresspath) {
        boolean bool = false;
        try {
            ZipOutputStream zipOutput = null;
            File file = new File(compresspath);
            if (file.isDirectory()) {
                zipOutput = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(compresspath + ".zip")));
                compressZip(zipOutput, file, "");
            } else {
                zipOutput = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(compresspath.substring(0, compresspath.lastIndexOf(".")) + ".zip")));
            }
            zipOutput.closeEntry();
            zipOutput.close();
            bool = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bool;
    }

    /**
     * @Title: compressZip
     * @Description: 子文件夹中可能还有文件夹，进行递归
     * @param @param zipOutput
     * @param @param file
     * @param @param suffixpath
     * @param @throws IOException
     * @return void    返回类型
     * @throws
     */
    private static void compressZip(ZipOutputStream zipOutput, File file, String suffixpath) {
        File[] listFiles = file.listFiles();// 列出所有的文件
        for (File fi : listFiles) {
            if (fi.isDirectory()) {
                if (suffixpath.equals("")) {
                    compressZip(zipOutput, fi, fi.getName());
                } else {
                    compressZip(zipOutput, fi, suffixpath + File.separator + fi.getName());
                }
            } else {
                zip(zipOutput, fi, suffixpath);
            }
        }
    }

    public static void zip(ZipOutputStream zipOutput, File file, String suffixpath) {
        try {
            ZipEntry zEntry = null;
            if (suffixpath.equals("")) {
                zEntry = new ZipEntry(file.getName());
            } else {
                zEntry = new ZipEntry(suffixpath + File.separator + file.getName());
            }
            zipOutput.putNextEntry(zEntry);
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            byte[] buffer = new byte[1024];
            int read = 0;
            while ((read = bis.read(buffer)) != -1) {
                zipOutput.write(buffer, 0, read);
            }
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /***
     * 删除文件夹
     *
     * @param folderPath 文件夹完整绝对路径
     */
    public static void delFolder(String folderPath) {
        try {
            delAllFile(folderPath); // 删除完里面所有内容
            String filePath = folderPath;
            filePath = filePath.toString();
            java.io.File myFilePath = new java.io.File(filePath);
            myFilePath.delete(); // 删除空文件夹
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /***
     * 删除指定文件夹下所有文件
     *
     * @param path 文件夹完整绝对路径
     * @return
     */
    public static boolean delAllFile(String path) {
        boolean flag = false;
        File file = new File(path);
        if (!file.exists()) {
            return flag;
        }
        if (!file.isDirectory()) {
            return flag;
        }
        String[] tempList = file.list();
        File temp = null;
        for (int i = 0; i < tempList.length; i++) {
            if (path.endsWith(File.separator)) {
                temp = new File(path + tempList[i]);
            } else {
                temp = new File(path + File.separator + tempList[i]);
            }
            if (temp.isFile()) {
                temp.delete();
            }
            if (temp.isDirectory()) {
                delAllFile(path + "/" + tempList[i]);// 先删除文件夹里面的文件
                delFolder(path + "/" + tempList[i]);// 再删除空文件夹
                flag = true;
            }
        }
        return flag;
    }

    @Override
    public List<SearchConditionItem> personnelScreening() {
        List<SearchConditionItem> items = new ArrayList<>();
        // 所属分部
        SearchConditionItem companyItem = OrganizationFormItemUtil.browserItem(user, 2, 16, 2, false, "分部", "194", "subcompanyid1", "");
        // 所属部门
        SearchConditionItem departmentItem = OrganizationFormItemUtil.browserItem(user, 2, 16, 2, false, "部门", "57", "departmentid", "");

        SearchConditionItem jobItem = OrganizationFormItemUtil.browserItem(user, 2, 16, 2, false, "岗位", "666", "jobId", "");

        SearchConditionItem resourceItem = OrganizationFormItemUtil.browserItem(user, 2, 16, 2, false, "人员", "17", "resourceId", "");
        items.add(companyItem);
        items.add(departmentItem);
        items.add(jobItem);
        items.add(resourceItem);
        return items;
    }

    public List<SearchTree> getFilterDatas(SearchTreeParams params, List<ResourcePO> resourcePOList) {
        String keyword = params.getKeyword();
        String id = params.getId();
        String type = Util.null2String(params.getType());

        List<SearchTree> searchTree = new ArrayList<>();
        // 通过分部、公司 组装数据
        if (StringUtil.isEmpty(id) || ModuleTypeEnum.subcompanyfielddefined.getValue().toString().equals(type)) {
            Integer subCompanyId1 = StringUtil.isEmpty(id) ? null : Integer.parseInt(id);
            if (params.isPersonnelScreening()) {
                new DetachUtil(user).filterResourceList(resourcePOList);
                if (null != subCompanyId1) {
                    resourcePOList.removeIf(item -> !subCompanyId1.equals(item.getSubcompanyid1()));
                }
            }
            DepartmentPO departmentBuild = DepartmentPO.builder().departmentName(keyword).subCompanyId1(subCompanyId1).canceled(0).build();
            CompPO compBuild = CompPO.builder().subCompanyName(keyword).supSubComId(subCompanyId1).canceled(0).build();
            // 所属分部下的岗位
            JobPO jobBuild = JobPO.builder().jobTitleName(keyword).ecCompany(subCompanyId1).forbiddenTag(0).build();
            ResourcePO resourcePO = ResourcePO.builder().lastName(keyword).subcompanyid1(subCompanyId1).build();
            searchTree = buildTreeByCompAndDept(params, resourcePOList, departmentBuild, compBuild, jobBuild, resourcePO);
        } else if (ModuleTypeEnum.departmentfielddefined.getValue().toString().equals(type)) {
            Integer departmentId = Integer.parseInt(id);
            if (null != resourcePOList) {
                new DetachUtil(user).filterResourceList(resourcePOList);
                resourcePOList.removeIf(item -> !departmentId.equals(item.getDepartmentid()));
            }
            DepartmentPO departmentBuild = DepartmentPO.builder().departmentName(keyword).supDepId(departmentId).canceled(0).build();
            // 所属分部下的岗位
            JobPO jobBuild = JobPO.builder().jobTitleName(keyword).ecDepartment(departmentId).forbiddenTag(0).build();
            ResourcePO resourcePO = ResourcePO.builder().lastName(keyword).departmentid(departmentId).build();

            searchTree = buildTreeByDeptAndJob(params, resourcePOList, departmentBuild, jobBuild, resourcePO);

        } else if (ModuleTypeEnum.jobfielddefined.getValue().toString().equals(type)) {
            Long jobId = Long.parseLong(id);
            JobPO jobById = getJobMapper().getJobById(jobId);
            if (null != resourcePOList) {
                new DetachUtil(user).filterResourceList(resourcePOList);
                resourcePOList.removeIf(item -> !(jobById.getEcCompany().equals(item.getSubcompanyid1()) && jobById.getEcDepartment().equals(item.getDepartmentid())) && jobById.getEcJobTitle().equals(item.getJobtitle()));
                return SearchTreeUtil.builderTreeMode(ResourceBO.buildSetToSearchTree(resourcePOList));
            }
            ResourcePO resourcePO = ResourcePO.builder().lastName(keyword).subcompanyid1(jobById.getEcCompany()).departmentid(jobById.getEcDepartment()).jobtitle(jobById.getEcJobTitle()).build();
            List<ResourcePO> resourcePOS = getHrmResourceMapper().listByFilter(resourcePO);
            searchTree = SearchTreeUtil.builderTreeMode(ResourceBO.buildSetToSearchTree(resourcePOS));
        }
        return searchTree;
    }

    /**
     * 分部、部门 组装左侧树
     *
     * @param departmentBuild
     * @param compBuild
     * @param jobBuild
     * @return
     */
    private List<SearchTree> buildTreeByCompAndDept(SearchTreeParams params, List<ResourcePO> resourcePOList, DepartmentPO departmentBuild, CompPO compBuild, JobPO jobBuild, ResourcePO resourcePO) {
        // 查询人员数据
        List<ResourcePO> resourcePOS;
        if (params.isPersonnelScreening()) {
            resourcePOS = resourcePOList;
        } else {
            resourcePOS = getHrmResourceMapper().listByFilter(resourcePO);
        }
        Set<JobPO> builderJobs = new HashSet<>();

        // 补充人员所有岗位,关联人员及聚才林岗位
        for (ResourcePO resource : resourcePOS) {
            JobPO jobByResource = getJobMapper().getJobByResource(resource);
            if (null != jobByResource) {
                resource.setJobId(jobByResource.getId());
                builderJobs.add(jobByResource);
            }
        }
        List<SearchTree> resourceTrees = SearchTreeUtil.builderTreeMode(ResourceBO.buildSetToSearchTree(resourcePOS));


        List<JobPO> jobPOS = getJobMapper().listPOsByFilter(jobBuild);
        if (params.isPersonnelScreening()) {
            jobPOS.removeIf(item -> !params.getJobId().contains(item.getId()));
        }

        new DetachUtil(user).filterJobList(jobPOS);
        List<DepartmentPO> filterDeparts = getDepartmentMapper().listByFilter(departmentBuild, "showorder");
        if (params.isPersonnelScreening()) {
            filterDeparts.removeIf(item -> !params.getDepartmentid().contains(item.getId()));
        }
        new DetachUtil(user).filterDepartmentList(filterDeparts);
        // 添加父级岗位
        builderJobs.addAll(jobPOS);
        // 添加岗位的上级部门或分部
        List<SearchTree> jobTrees = SearchTreeUtil.builderTreeMode(JobBO.buildSetToSearchTree(builderJobs), resourceTrees);
        String parentDeptS = jobTrees.stream().map(SearchTree::getParentComp).collect(Collectors.joining(","));
        if (!StringUtil.isEmpty(parentDeptS)) {
            // 兼容SQLServer每次最多in,2100条数据
            List<Long> ids = DeleteParam.builder().ids(parentDeptS).build().getIds();
            int ceilCount = (int) Math.ceil((double) ids.size() / 1000);
            List<DepartmentPO> departmentsByIds = new ArrayList<>();
            for (int i = 1; i < ceilCount + 1; i++) {
                List<Long> longs = PageUtil.subList(i, 1000, ids);
                List<DepartmentPO> departmentsById = getDepartmentMapper().getDeptsByIds(longs);
                if (CollectionUtils.isNotEmpty(departmentsById)) {
                    departmentsByIds.addAll(departmentsById);
                }
            }

            if (CollectionUtils.isNotEmpty(departmentsByIds)) {
                departmentsByIds.removeIf(item -> item.getCanceled() != null && item.getCanceled() != 0);
                filterDeparts.addAll(departmentsByIds);
            }
        }

        // 查询分部信息
        List<CompPO> filterComps = getCompMapper().listByFilter(compBuild, "showorder");
        if (params.isPersonnelScreening()) {
            filterComps.removeIf(item -> !params.getSubcompanyid1().contains(item.getId()));
        }

        new DetachUtil(user).filterCompanyList(filterComps);
        Set<DepartmentPO> builderDeparts = new HashSet<>();
        for (DepartmentPO departmentPO : filterDeparts) {
            buildParentDepts(departmentPO, builderDeparts);
        }
        List<SearchTree> departmentList = DepartmentBO.buildSetToSearchTree(builderDeparts);
        List<SearchTree> deptTrees = SearchTreeUtil.builderTreeMode(departmentList);
        List<SearchTree> searchTrees = SearchTreeUtil.builderTreeMode(departmentList, jobTrees);
        // 添加部门的上级分部
        String parentCompS = deptTrees.stream().map(SearchTree::getParentComp).collect(Collectors.joining(","));
        if (!StringUtil.isEmpty(parentCompS)) {
            List<CompPO> compsByIds = getCompMapper().getCompsByIds(DeleteParam.builder().ids(parentCompS).build().getIds());
            if (CollectionUtils.isNotEmpty(compsByIds)) {
                filterComps.addAll(compsByIds);
            }
        }
        List<CompPO> allCompanys = getCompMapper().listAll("showorder");
        new DetachUtil(user).filterCompanyList(allCompanys);
        Map<Integer, CompPO> allMaps = allCompanys.stream().collect(Collectors.toMap(CompPO::getId, item -> item, (k1, k2) -> k1));
        Set<CompPO> builderComps = new HashSet<>();
        for (CompPO compPO : filterComps) {
            buildParentComps(compPO, builderComps, allMaps);
        }
        return SearchTreeUtil.builderTreeMode(CompBO.buildSetToSearchTree(builderComps), searchTrees);
    }

    private List<SearchTree> buildTreeByDeptAndJob(SearchTreeParams params, List<ResourcePO> resourcePOList, DepartmentPO departmentBuild, JobPO jobBuild, ResourcePO resourcePO) {
        // 查询人员数据
        List<ResourcePO> resourcePOS;
        if (params.isPersonnelScreening()) {
            resourcePOS = resourcePOList;
        } else {
            resourcePOS = getHrmResourceMapper().listByFilter(resourcePO);
        }
        Set<JobPO> builderJobs = new HashSet<>();

        // 补充人员所有岗位,关联人员及聚才林岗位
        for (ResourcePO resource : resourcePOS) {
            JobPO jobByResource = getJobMapper().getJobByResource(resource);
            if (null != jobByResource) {
                resource.setJobId(jobByResource.getId());
                builderJobs.add(jobByResource);
            }
        }
        List<SearchTree> resourceTrees = SearchTreeUtil.builderTreeMode(ResourceBO.buildSetToSearchTree(resourcePOS));

        List<JobPO> jobPOS = getJobMapper().listPOsByFilter(jobBuild);
        if (params.isPersonnelScreening()) {
            jobPOS.removeIf(item -> !params.getJobId().contains(item.getId()));
        }

        List<DepartmentPO> filterDeparts = getDepartmentMapper().listByFilter(departmentBuild, "showorder");
        if (params.isPersonnelScreening()) {
            filterDeparts.removeIf(item -> !params.getDepartmentid().contains(item.getId()));
        }
        // 添加父级岗位
        builderJobs.addAll(jobPOS);
        // 添加岗位的上级部门或分部
        List<SearchTree> jobTrees = SearchTreeUtil.builderTreeMode(JobBO.buildSetToSearchTree(builderJobs), resourceTrees);
        String parentDeptS = jobTrees.stream().map(SearchTree::getParentComp).collect(Collectors.joining(","));
        if (!StringUtil.isEmpty(parentDeptS)) {
            // 兼容SQLServer每次最多in,2100条数据
            List<Long> ids = DeleteParam.builder().ids(parentDeptS).build().getIds();
            int ceilCount = (int) Math.ceil((double) ids.size() / 1000);
            List<DepartmentPO> departmentsByIds = new ArrayList<>();
            for (int i = 0; i < ceilCount - 1; i++) {
                List<DepartmentPO> departmentsById = getDepartmentMapper().getDeptsByIds(PageUtil.subList(i, 1000, ids));
                if (CollectionUtils.isNotEmpty(departmentsById)) {
                    departmentsByIds.addAll(departmentsById);
                }
            }

            if (CollectionUtils.isNotEmpty(departmentsByIds)) {
                departmentsByIds.removeIf(item -> item.getCanceled() != null && item.getCanceled() != 0);
                filterDeparts.addAll(departmentsByIds);
            }
        }

        // 查询分部信息
        Set<DepartmentPO> builderDeparts = new HashSet<>();
        for (DepartmentPO departmentPO : filterDeparts) {
            buildParentDepts(departmentPO, builderDeparts);
        }
        return SearchTreeUtil.builderTreeMode(DepartmentBO.buildSetToSearchTree(builderDeparts), jobTrees);
    }


    /**
     * 添加查询元素的父级元素
     *
     * @param departmentPO
     * @param builderDeparts
     */
    private void buildParentDepts(DepartmentPO departmentPO, Set<DepartmentPO> builderDeparts) {
        builderDeparts.add(departmentPO);
        if (SearchTreeUtil.isTop(departmentPO.getSupDepId())) {
            return;
        }
        DepartmentPO parentDept = getDepartmentMapper().getDeptById(departmentPO.getSupDepId());
        if (null != parentDept) {
            buildParentDepts(parentDept, builderDeparts);
        }
    }

    /**
     * 添加查询元素的父级元素
     *
     * @param compPO
     * @param builderComps
     */
    private void buildParentComps(CompPO compPO, Set<CompPO> builderComps, Map<Integer, CompPO> allMaps) {
        if (null != compPO.getCanceled() && 0 != compPO.getCanceled()) {
            return;
        }
        builderComps.add(compPO);
        CompPO parentComp = allMaps.get(compPO.getSupSubComId());
        if (null != parentComp) {
            buildParentComps(parentComp, builderComps, allMaps);
        }
    }
}
