package jnpf.personnels.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.seata.spring.annotation.GlobalTransactional;
import jnpf.base.entity.SuperBaseEntity;
import jnpf.model.personnels.bo.FtbRosterImportConstants;
import jnpf.model.personnels.bo.FtbRosterImportRedisBO;
import jnpf.model.personnels.bo.FtbRosterImportTemplateBO;
import jnpf.model.personnels.po.FtbPersonnelsRegistrationFormField;
import jnpf.model.personnels.po.FtbPersonnelsRegistrationFormType;
import jnpf.model.personnels.vo.employeetype.FtbPersonnelsEmployeeTypeVO;
import jnpf.model.personnels.vo.roster.*;
import jnpf.personnels.listeners.DynamicHeadAnalysisEventListener;
import jnpf.personnels.listeners.DynamicHeadAnalysisNewEventListener;
import jnpf.personnels.mapper.FtbPersonnelsRegistrationFormFieldMapper;
import jnpf.personnels.mapper.FtbPersonnelsRegistrationFormTypeMapper;
import jnpf.personnels.service.FtbPersonnelsEmployeeTypeService;
import jnpf.personnels.service.FtbPersonnelsRosterValidService;
import jnpf.personnels.service.FtbPersonnelsStaffRosterImportService;
import jnpf.personnels.utils.CacheExcelUtils;
import jnpf.personnels.utils.StaffRosterImportSaveUtils;
import jnpf.util.RedisUtil;
import jnpf.util.UserProvider;
import jnpf.util.excel.EasyExcelUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Service
@Slf4j
public class FtbPersonnelsStaffRosterImportServiceImpl implements FtbPersonnelsStaffRosterImportService {

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private FtbPersonnelsRegistrationFormTypeMapper ftbPersonnelsRegistrationFormTypeMapper;

    @Resource
    private FtbPersonnelsRegistrationFormFieldMapper ftbPersonnelsRegistrationFormFieldMapper;

    @Resource
    private FtbPersonnelsEmployeeTypeService employeeTypeService;

    @Resource(name = "FtbPersonnelsRosterValidServiceOld")
    private FtbPersonnelsRosterValidService ftbPersonnelsRosterValidService;

    @Resource(name = "FtbPersonnelsRosterValidServiceNew")
    private FtbPersonnelsRosterValidService ftbPersonnelsRosterValidServiceNew;

    @Autowired
    private CacheExcelUtils cacheExcelUtils;
    @Resource
    private StaffRosterImportSaveUtils staffRosterImportSaveUtils;


    @Override
    public FtbRosterImportVO rosterImport(InputStream inputStream) {
        String loginUserId = UserProvider.getLoginUserId();
        String redisKey = String.format(FtbRosterImportConstants.ROSTER_IMPORT_SHEET_REDIS_VARIABLES, loginUserId);
        redisUtil.remove(redisKey);
        long totalStart = System.currentTimeMillis();
        try (ExcelReader excelReader = EasyExcel
                .read(inputStream, new DynamicHeadAnalysisEventListener(ftbPersonnelsRosterValidService))
                .build()) {
            long excelInitEnd = System.currentTimeMillis();
            log.error("花名册导入(rosterImport) ExcelReader初始化耗时：{}ms", excelInitEnd - totalStart);
            cacheExcelUtils.init();
            // 获取所有sheet列表,跳过第一个sheet
            List<ReadSheet> sheets = excelReader.excelExecutor().sheetList()
                    .stream()
                    .filter(sheet -> sheet.getSheetNo() > 0 && !"导入须知".equals(sheet.getSheetName()))
                    .collect(Collectors.toList());
            long sheetsPreparedEnd = System.currentTimeMillis();
            log.error("花名册导入(rosterImport) 准备sheet列表耗时：{}ms", sheetsPreparedEnd - excelInitEnd);
            // 校验sheet是否匹配
            if (!verifySheetMatches(sheets)) {
                throw new RuntimeException("excel导入模板有变更,请重新下载最新模板导入。");
            }
            long excelReadStart = System.currentTimeMillis();
            for (ReadSheet readSheet : sheets) {
                excelReader.read(readSheet);
            }
            long excelReadEnd = System.currentTimeMillis();
            log.error("花名册导入(rosterImport) 读取所有sheet耗时：{}ms", excelReadEnd - excelReadStart);
            String idStr = IdWorker.getIdStr();
            FtbRosterImportVO ftbRosterImportVO = new FtbRosterImportVO();
            ftbRosterImportVO.setUniqueId(idStr);
            String rediskey = String.format(FtbRosterImportConstants.ROSTER_IMPORT_SHEET_REDIS_VARIABLES, UserProvider.getLoginUserId());
            for (ReadSheet readSheet : sheets) {
                String sheetName = readSheet.getSheetName();
                String hashValues = redisUtil.getHashValues(rediskey, sheetName);
                FtbRosterImportRedisBO ftbRosterImportRedisBO = JSON.parseObject(hashValues, FtbRosterImportRedisBO.class);
                ftbRosterImportVO.getNormalRosterCategoryVOS().add(ftbRosterImportRedisBO.getNormalData());
                ftbRosterImportVO.getErrorRosterCategoryVOS().add(ftbRosterImportRedisBO.getErrorData());
            }
            long redisDataAssembleEnd = System.currentTimeMillis();
            log.error("花名册导入(rosterImport) 从Redis组装sheet数据耗时：{}ms", redisDataAssembleEnd - excelReadEnd);
            long errorOfAbnormalDataItems = ftbRosterImportVO.getErrorRosterCategoryVOS()
                    .stream().mapToLong(ftbRosterCategoryVO -> ftbRosterCategoryVO.getFtbRosterPageVOS().size()).sum();
            long dataEncapsulationStart = System.currentTimeMillis();
            List<FtbRosterInsertNomalVO> data = rosterDataEncapsulation(ftbRosterImportVO.getNormalRosterCategoryVOS(),
                    ftbRosterImportVO.getErrorRosterCategoryVOS());
            long dataEncapsulationEnd = System.currentTimeMillis();
            log.error("花名册导入(rosterImport) 正常数据封装(rosterDataEncapsulation)耗时：{}ms", dataEncapsulationEnd - dataEncapsulationStart);
            ftbRosterImportVO.setNormalNumberOfDataItems((long) data.size());
            ftbRosterImportVO.setErrorOfAbnormalDataItems(errorOfAbnormalDataItems);
            ftbRosterImportVO.setData(data);
            redisUtil.remove(rediskey);
            long redisWriteStart = System.currentTimeMillis();
            redisUtil.insert(String.format(FtbRosterImportConstants.ROSTER_IMPORT_REDIS_VARIABLES, idStr)
                    , ftbRosterImportVO, 30 * 60);
            long redisWriteEnd = System.currentTimeMillis();
            log.error("花名册导入(rosterImport) 结果写入Redis耗时：{}ms", redisWriteEnd - redisWriteStart);
            // 防止大数据导入时正常数据将nginx缓存打满及skywalking减少采集数据量
            ftbRosterImportVO.getNormalRosterCategoryVOS().clear();
            ftbRosterImportVO.getData().clear();
            long totalEnd = System.currentTimeMillis();
            log.error("花名册导入(rosterImport) 总体耗时：{}ms", totalEnd - totalStart);
            return ftbRosterImportVO;
        } finally {
            cacheExcelUtils.clear();
        }
    }
    @Override
    public void exceptionDataExport(String id) throws IOException {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert servletRequestAttributes != null;
        HttpServletResponse httpServletResponse = servletRequestAttributes.getResponse();
        String redisKey = String.format(FtbRosterImportConstants.ROSTER_IMPORT_REDIS_VARIABLES, id);
        if (!redisUtil.exists(redisKey)) {
            throw new RuntimeException("导入数据已过期，请重新导入!");
        }
        FtbRosterImportVO ftbRosterImportVO = JSON.parseObject(redisUtil.getString(redisKey).toString(), FtbRosterImportVO.class);
        List<FtbRosterCategoryVO> errorRosterCategoryVOS = ftbRosterImportVO.getErrorRosterCategoryVOS();
        List<FtbRosterImportTemplateBO> ftbRosterImportTemplateBOS = errorRosterCategoryVOS.stream()
                .sorted(Comparator.comparing(FtbRosterCategoryVO::getSheetIndex))
                .map(ftbRosterCategoryVO -> {
                    FtbRosterImportTemplateBO ftbRosterImportTemplateBO = new FtbRosterImportTemplateBO();
                    ftbRosterImportTemplateBO.setSheetName(ftbRosterCategoryVO.getClassificationName());
                    ftbRosterImportTemplateBO.setHeader(ftbRosterCategoryVO.convertHead());
                    ftbRosterImportTemplateBO.setData(ftbRosterCategoryVO.convertData());
                    return ftbRosterImportTemplateBO;
                }).collect(Collectors.toList());
        EasyExcelUtils.dynamicHeaderGeneration(httpServletResponse, "花名册错误数据", "classpath:roster/roster.xlsx"
                , ftbRosterImportTemplateBOS, getEmployeeTypeName());
    }

    @Override
    @GlobalTransactional(rollbackFor = {Throwable.class,Exception.class},timeoutMills = 300000)
    public void normalDataImport(String id) {
        String redisKey = String.format(FtbRosterImportConstants.ROSTER_IMPORT_REDIS_VARIABLES, id);
        if (!redisUtil.exists(redisKey)) {
            throw new RuntimeException("导入数据已过期，请重新导入!");
        }
        long redisReadStart = System.currentTimeMillis();
        FtbRosterImportVO ftbRosterImportVO = JSON.parseObject(redisUtil.getString(redisKey).toString(), FtbRosterImportVO.class);
        long redisReadEnd = System.currentTimeMillis();
        log.error("花名册导入(normalDataImport) 从Redis读取并反序列化数据耗时：{}ms", redisReadEnd - redisReadStart);
        List<FtbRosterInsertNomalVO> data = ftbRosterImportVO.getData();
        staffRosterImportSaveUtils.addImportRosters(data);
    }

    @Override
    public List<FtbRosterImportFormFieldsConfigVO> formFieldsConfig(Integer type) {
        List<FtbPersonnelsRegistrationFormType> ftbPersonnelsRegistrationFormTypes;
        if (type == 0) {
            ftbPersonnelsRegistrationFormTypes = ftbPersonnelsRegistrationFormTypeMapper.selectList(FtbRosterImportConstants.getRegistrationFormTypeQueryWrapperExport());
        } else {
            ftbPersonnelsRegistrationFormTypes = ftbPersonnelsRegistrationFormTypeMapper.selectList(FtbRosterImportConstants.getRegistrationFormTypeQueryWrapper());
        }
        return ftbPersonnelsRegistrationFormTypes.stream().map(a -> {
            FtbRosterImportFormFieldsConfigVO ftbRosterImportFormFieldsConfigVO = new FtbRosterImportFormFieldsConfigVO();
            ftbRosterImportFormFieldsConfigVO.setCategoryName(a.getName());
            ftbRosterImportFormFieldsConfigVO.setCategoryId(a.getId());
            // 登记表属性
            List<FtbPersonnelsRegistrationFormField> registrationFormFields = ftbPersonnelsRegistrationFormFieldMapper.selectList(
                    FtbRosterImportConstants.getRegistrationFormFieldQueryWrapper(a.getId()));
            if (CollUtil.isNotEmpty(registrationFormFields)) {
                // 导出附件、图片都要
                if (type == 0) {
                    FtbRosterImportConstants.nameAndMobileNumberAddedNewExport(registrationFormFields, a.getId());
                } else {
                    // 导入额外项排除
                    FtbRosterImportConstants.nameAndMobileNumberAddedNew(registrationFormFields, a.getId());
                }
                ftbRosterImportFormFieldsConfigVO.setOptionNames(registrationFormFields.stream().map(b -> {
                    FtbRosterImportFormFieldsConfigVO.OptionName opName = new FtbRosterImportFormFieldsConfigVO.OptionName();
                    opName.setOptionId(b.getId());
                    opName.setOptionName(b.getName());
                    opName.setIsRequired(b.getIsNeedFill() == 1);
                    return opName;
                }).collect(Collectors.toList()));
            }
            return ftbRosterImportFormFieldsConfigVO;
        }).collect(Collectors.toList());
    }

    @Override
    public void rosterImportTemplateDownloadNew(List<String> formFields) throws IOException {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert servletRequestAttributes != null;
        HttpServletResponse httpServletResponse = servletRequestAttributes.getResponse();
        List<FtbRosterImportTemplateBO> ftbRosterImportTemplateBOS = new ArrayList<>();
        LambdaQueryWrapper<FtbPersonnelsRegistrationFormField> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(SuperBaseEntity.SuperIBaseEntity::getId, formFields);
        queryWrapper.orderByAsc(FtbPersonnelsRegistrationFormField::getSorts);
        // 登记表属性
        FtbRosterImportTemplateBO ftbRosterImportTemplateBO = new FtbRosterImportTemplateBO();
        ftbRosterImportTemplateBO.setSheetName("sheet1");
        List<FtbPersonnelsRegistrationFormField> registrationFormFields = ftbPersonnelsRegistrationFormFieldMapper.selectList(queryWrapper);
        // 入职直属主管处理
        formFields.stream().filter("currReportsToId"::equals).findFirst()
                .ifPresent(a -> registrationFormFields.addAll(FtbRosterImportConstants.ROSTER_IMPORT_JOB_INFORMATION_EXTRA_FIELDS));
        // 姓名和手机号排序靠前用于后续校验
        Predicate<FtbPersonnelsRegistrationFormField> workerNamePredicate = a -> "workerName".equals(a.getId());
        FtbPersonnelsRegistrationFormField workerNameRegistrationFormField = registrationFormFields.stream()
                .filter(workerNamePredicate)
                .findFirst()
                .get();
        registrationFormFields.removeIf(workerNamePredicate);
        registrationFormFields.add(0, workerNameRegistrationFormField);
        Predicate<FtbPersonnelsRegistrationFormField> phonePredicate = a -> "phone".equals(a.getId());
        FtbPersonnelsRegistrationFormField phoneRegistrationFormField = registrationFormFields.stream()
                .filter(phonePredicate)
                .findFirst()
                .get();
        registrationFormFields.removeIf(phonePredicate);
        registrationFormFields.add(1, phoneRegistrationFormField);
        List<List<String>> headers = registrationFormFields.stream().map(personnelsRegistrationFormField -> {
            List<String> list = new ArrayList<>();
            if (personnelsRegistrationFormField.getIsNeedFill() == 1) {
                list.add("*" + personnelsRegistrationFormField.getName());
            } else {
                list.add(personnelsRegistrationFormField.getName());
            }
            return list;
        }).collect(Collectors.toList());
        ftbRosterImportTemplateBO.setHeader(headers);
        ftbRosterImportTemplateBOS.add(ftbRosterImportTemplateBO);
        EasyExcelUtils.dynamicHeaderGeneration(httpServletResponse, "花名册模板", "classpath:roster/roster.xlsx"
                , ftbRosterImportTemplateBOS, getEmployeeTypeName());
    }

    @Override
    public FtbRosterImportVO rosterImportNew(InputStream inputStream) {
        String loginUserId = UserProvider.getLoginUserId();
        String redisKey = String.format(FtbRosterImportConstants.ROSTER_IMPORT_SHEET_REDIS_VARIABLES, loginUserId);
        redisUtil.remove(redisKey);
        long totalStart = System.currentTimeMillis();
        try (ExcelReader excelReader = EasyExcel
                .read(inputStream, new DynamicHeadAnalysisNewEventListener(ftbPersonnelsRosterValidServiceNew))
                .build()) {
            long excelInitEnd = System.currentTimeMillis();
            log.error("花名册导入(rosterImportNew) ExcelReader初始化耗时：{}ms", excelInitEnd - totalStart);
            cacheExcelUtils.init();
            // 获取所有sheet列表,跳过第一个sheet
            List<ReadSheet> sheets = excelReader.excelExecutor().sheetList()
                    .stream()
                    .filter(sheet -> !"导入须知".equals(sheet.getSheetName()))
                    .collect(Collectors.toList());
            long sheetsPreparedEnd = System.currentTimeMillis();
            log.error("花名册导入(rosterImportNew) 准备sheet列表耗时：{}ms", sheetsPreparedEnd - excelInitEnd);
            long excelReadStart = System.currentTimeMillis();
            for (ReadSheet readSheet : sheets) {
                excelReader.read(readSheet);
            }
            long excelReadEnd = System.currentTimeMillis();
            log.error("花名册导入(rosterImportNew) 读取所有sheet耗时：{}ms", excelReadEnd - excelReadStart);
            String idStr = IdWorker.getIdStr();
            FtbRosterImportVO ftbRosterImportVO = new FtbRosterImportVO();
            ftbRosterImportVO.setUniqueId(idStr);
            String rediskey = String.format(FtbRosterImportConstants.ROSTER_IMPORT_SHEET_REDIS_VARIABLES, UserProvider.getLoginUserId());
            for (ReadSheet readSheet : sheets) {
                String sheetName = readSheet.getSheetName();
                String hashValues = redisUtil.getHashValues(rediskey, sheetName);
                FtbRosterImportRedisBO ftbRosterImportRedisBO = JSON.parseObject(hashValues, FtbRosterImportRedisBO.class);
                ftbRosterImportVO.getNormalRosterCategoryVOS().add(ftbRosterImportRedisBO.getNormalData());
                Map<String, String> sortMap = ftbRosterImportRedisBO.getErrorData().getHead().entrySet()
                        .stream()
                        .sorted(Comparator.comparingInt(a -> Integer.parseInt(a.getKey())))
                        .collect(Collectors.toMap(
                                Map.Entry::getKey,
                                Map.Entry::getValue,
                                (oldValue, newValue) -> oldValue,
                                LinkedHashMap::new
                        ));
                ftbRosterImportRedisBO.getErrorData().setHead(sortMap);
                ftbRosterImportVO.getErrorRosterCategoryVOS().add(ftbRosterImportRedisBO.getErrorData());
            }
            long redisDataAssembleEnd = System.currentTimeMillis();
            log.error("花名册导入(rosterImportNew) 从Redis组装sheet数据耗时：{}ms", redisDataAssembleEnd - excelReadEnd);
            long errorOfAbnormalDataItems = ftbRosterImportVO.getErrorRosterCategoryVOS()
                    .stream().mapToLong(ftbRosterCategoryVO -> ftbRosterCategoryVO.getFtbRosterPageVOS().size()).sum();
            long dataEncapsulationStart = System.currentTimeMillis();
            List<FtbRosterInsertNomalVO> data = rosterDataEncapsulationNew(ftbRosterImportVO.getNormalRosterCategoryVOS());
            long dataEncapsulationEnd = System.currentTimeMillis();
            log.error("花名册导入(rosterImportNew) 正常数据封装(rosterDataEncapsulationNew)耗时：{}ms", dataEncapsulationEnd - dataEncapsulationStart);
            ftbRosterImportVO.setNormalNumberOfDataItems((long) data.size());
            ftbRosterImportVO.setErrorOfAbnormalDataItems(errorOfAbnormalDataItems);
            ftbRosterImportVO.setData(data);
            redisUtil.remove(rediskey);
            long redisWriteStart = System.currentTimeMillis();
            redisUtil.insert(String.format(FtbRosterImportConstants.ROSTER_IMPORT_REDIS_VARIABLES, idStr)
                    , ftbRosterImportVO, 30 * 60);
            long redisWriteEnd = System.currentTimeMillis();
            log.error("花名册导入(rosterImportNew) 结果写入Redis耗时：{}ms", redisWriteEnd - redisWriteStart);
            // 防止大数据导入时正常数据将nginx缓存打满及skywalking减少采集数据量
            ftbRosterImportVO.getNormalRosterCategoryVOS().clear();
            ftbRosterImportVO.getData().clear();
            long totalEnd = System.currentTimeMillis();
            log.error("花名册导入(rosterImportNew) 总体耗时：{}ms", totalEnd - totalStart);
            return ftbRosterImportVO;
        } finally {
            cacheExcelUtils.clear();
        }
    }

    private List<FtbRosterInsertNomalVO> rosterDataEncapsulation(List<FtbRosterCategoryVO> normalRosterCategoryVOS
            , List<FtbRosterCategoryVO> errorRosterCategoryVOS) {
        List<FtbRosterInsertNomalVO> result = new ArrayList<>();
        // 错误数据手机号
        List<String> errorPhones = errorRosterCategoryVOS.stream().filter(a -> !CollectionUtils.isEmpty(a.getFtbRosterPageVOS()))
                .flatMap(ftbRosterCategoryVO -> ftbRosterCategoryVO.getFtbRosterPageVOS().stream())
                .filter(b -> !CollectionUtils.isEmpty(b.getFtbRosterAttributesVOS()))
                .flatMap(ftbRosterPageVO -> ftbRosterPageVO.getFtbRosterAttributesVOS().stream())
                .filter(FtbRosterImportConstants.phonePredicate)
                .map(FtbRosterAttributesVO::getAttributeValue)
                .collect(Collectors.toList());
        if (CollUtil.isNotEmpty(normalRosterCategoryVOS)) {
            FtbRosterCategoryVO ftbRosterCategoryVO = normalRosterCategoryVOS
                    .stream()
                    .max(Comparator.comparing(FtbRosterCategoryVO::getSorted)).get();
            List<FtbRosterCategoryVO> rosterCategoryVOS = normalRosterCategoryVOS.stream().filter(a -> !a.getSheetIndex().equals(ftbRosterCategoryVO.getSheetIndex()))
                    .collect(Collectors.toList());
            // 手机号最多的那条
            retry:
            for (FtbRosterPageVO ftbRosterPageVO : ftbRosterCategoryVO.getFtbRosterPageVOS()) {
                FtbRosterAttributesVO phoneRosterAttributesVO = ftbRosterPageVO.getFtbRosterAttributesVOS().stream().filter(FtbRosterImportConstants.phonePredicate)
                        .findFirst().get();
                FtbRosterAttributesVO userNameRosterAttributesVO = ftbRosterPageVO.getFtbRosterAttributesVOS().stream().filter(FtbRosterImportConstants.userNamePredicate)
                        .findFirst().get();
                // 只要手机号在错误数据中存在，则移除属于正常数据，由于跨sheet匹配原因
                if (errorPhones.contains(phoneRosterAttributesVO.getAttributeValue())) {
                    continue;
                }
                FtbRosterInsertNomalVO ftbRosterInsertNomalVO = new FtbRosterInsertNomalVO();
                // 手机号
                ftbRosterInsertNomalVO.setPhone(phoneRosterAttributesVO.getAttributeValue());
                ftbRosterInsertNomalVO.setUserName(userNameRosterAttributesVO.getAttributeValue());
                List<FtbRosterInsertAttributesVO> ftbRosterInsertAttributesVOS = new ArrayList<>();
                for (FtbRosterCategoryVO rosterCategoryVO : rosterCategoryVOS) {
                    // 根据手机号匹配行标，通过行标去匹配数据，手机号没有，则跳出
                    FtbRosterAttributesVO ftbRosterAttributesVO = rosterCategoryVO.getFtbRosterPageVOS().stream()
                            .flatMap(a -> a.getFtbRosterAttributesVOS().stream())
                            .filter(b -> {
                                        boolean equals = false;
                                        if (StringUtils.isNotEmpty(b.getAttributeValue())) { //添加非空判断
                                            equals = b.getAttributeValue().equals(phoneRosterAttributesVO.getAttributeValue());
                                        }
                                        return equals;
                                    }
                            ).findFirst().orElse(null);
                    if (ftbRosterAttributesVO != null) {
                        FtbRosterPageVO rosterPageVO = rosterCategoryVO.getFtbRosterPageVOS()
                                .stream()
                                .filter(a -> a.getRowMark().equals(ftbRosterAttributesVO.getLineMark()))
                                .findFirst().get();
                        dataCleaning(rosterPageVO, ftbRosterInsertNomalVO, ftbRosterInsertAttributesVOS);
                    } else {
                        continue retry;
                    }
                }
                dataCleaning(ftbRosterPageVO, ftbRosterInsertNomalVO, ftbRosterInsertAttributesVOS);
                ftbRosterInsertNomalVO.setFtbRosterInsertAttributesVOS(ftbRosterInsertAttributesVOS);
                result.add(ftbRosterInsertNomalVO);
            }
        }
        return result;
    }

    private static void dataCleaning(FtbRosterPageVO rosterPageVO, FtbRosterInsertNomalVO ftbRosterInsertNomalVO, List<FtbRosterInsertAttributesVO> ftbRosterInsertAttributesVOS) {
        rosterPageVO.getFtbRosterAttributesVOS().forEach(a -> {
            FtbRosterInsertAttributesVO ftbRosterInsertAttributesVO = new FtbRosterInsertAttributesVO();
            // 转正薪酬和入职薪酬特殊化处理
            if ("入职薪酬".equals(a.getAttributeName())) {
                ftbRosterInsertNomalVO.setEntrySalary(a.getAttributeValue());
            }
            if ("转正薪酬".equals(a.getAttributeName())) {
                ftbRosterInsertNomalVO.setRegularSalary(a.getAttributeValue());
            }
            // 排除自定义属性
            if (StrUtil.isBlank(a.getFormFieldId()) && StrUtil.isBlank(a.getFormTypeId())) {
                return;
            }
            if (StrUtil.isBlank(a.getAttributeValue())) {
                return;
            }
            ftbRosterInsertAttributesVO.setAttributeName(a.getAttributeName());
            ftbRosterInsertAttributesVO.setHeaderName(a.getAttributeName());
            ftbRosterInsertAttributesVO.setFormTypeId(a.getFormTypeId());
            ftbRosterInsertAttributesVO.setFormFieldId(a.getFormFieldId());
            ftbRosterInsertAttributesVO.setAttributeValue(a.getAttributeValue());
            ftbRosterInsertAttributesVO.setOriginalValue(a.getAttributeValue());
            if (StrUtil.isNotBlank(a.getAttributeValueId())) {
                ftbRosterInsertAttributesVO.setAttributeValue(a.getAttributeValueId());
            }
            ftbRosterInsertAttributesVOS.add(ftbRosterInsertAttributesVO);
        });
    }


    private boolean verifySheetMatches(List<ReadSheet> sheets) {
        List<String> sheetNames = sheets.stream()
                .map(ReadSheet::getSheetName).collect(Collectors.toList());
        // 登记类型配置
        List<FtbPersonnelsRegistrationFormType> formTypeList = ftbPersonnelsRegistrationFormTypeMapper.
                selectList(FtbRosterImportConstants.getRegistrationFormTypeQueryWrapper());
        // 标记 剔除没有数据的sheet
        List<FtbPersonnelsRegistrationFormType> filterFormTypeList = formTypeList.stream()
                .filter(a -> {
                    List<FtbPersonnelsRegistrationFormField> ftbPersonnelsRegistrationFormFields =
                            ftbPersonnelsRegistrationFormFieldMapper.selectList(FtbRosterImportConstants.getRegistrationFormFieldQueryWrapper(a.getId()));
                    if (CollUtil.isNotEmpty(ftbPersonnelsRegistrationFormFields)) {
                        return true;
                    }
                    return false;
                }).collect(Collectors.toList());

        // sheet有变更
        if (filterFormTypeList.size() != sheetNames.size()) {
            return false;
        }
        for (FtbPersonnelsRegistrationFormType ftbPersonnelsRegistrationFormType : filterFormTypeList) {
            if (!sheetNames.contains(ftbPersonnelsRegistrationFormType.getName())) {
                return false;
            }
        }
        return true;
    }


    private List<FtbRosterInsertNomalVO> rosterDataEncapsulationNew(List<FtbRosterCategoryVO> normalRosterCategoryVOS) {
        List<FtbRosterInsertNomalVO> result = new ArrayList<>();
        if (CollUtil.isNotEmpty(normalRosterCategoryVOS)) {
            for (FtbRosterPageVO ftbRosterPageVO : normalRosterCategoryVOS.get(0).getFtbRosterPageVOS()) {
                FtbRosterAttributesVO phoneRosterAttributesVO = ftbRosterPageVO.getFtbRosterAttributesVOS().stream().filter(FtbRosterImportConstants.phonePredicate)
                        .findFirst().get();
                FtbRosterAttributesVO userNameRosterAttributesVO = ftbRosterPageVO.getFtbRosterAttributesVOS().stream().filter(FtbRosterImportConstants.userNamePredicate)
                        .findFirst().get();
                FtbRosterInsertNomalVO ftbRosterInsertNomalVO = new FtbRosterInsertNomalVO();
                // 手机号
                ftbRosterInsertNomalVO.setPhone(phoneRosterAttributesVO.getAttributeValue());
                ftbRosterInsertNomalVO.setUserName(userNameRosterAttributesVO.getAttributeValue());
                List<FtbRosterInsertAttributesVO> ftbRosterInsertAttributesVOS = new ArrayList<>();
                dataCleaning(ftbRosterPageVO, ftbRosterInsertNomalVO, ftbRosterInsertAttributesVOS);
                ftbRosterInsertNomalVO.setFtbRosterInsertAttributesVOS(ftbRosterInsertAttributesVOS);
                result.add(ftbRosterInsertNomalVO);
            }
        }
        return result;
    }

    private String getEmployeeTypeName() {
        List<FtbPersonnelsEmployeeTypeVO> result = employeeTypeService.employeeList();
        return result.stream()
                .map(FtbPersonnelsEmployeeTypeVO::getName)
                .collect(Collectors.joining("，"));
    }

}
