package jnpf.personnels.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tencentcloudapi.faceid.v20180301.models.IdCardVerificationResponse;
import jnpf.config.StringToDateConverter;
import jnpf.model.enums.StaffWorkerStatus;
import jnpf.model.personnels.bo.FtbRosterImportConstants;
import jnpf.model.personnels.bo.FtbRosterImportHeadRuleBO;
import jnpf.model.personnels.bo.FtbRosterImportRedisBO;
import jnpf.model.personnels.po.FtbPersonnelsRegistrationFormField;
import jnpf.model.personnels.po.FtbPersonnelsRegistrationFormFieldOption;
import jnpf.model.personnels.po.FtbPersonnelsStaffRoster;
import jnpf.model.personnels.vo.roster.FtbRosterAttributesVO;
import jnpf.model.personnels.vo.roster.FtbRosterCategoryVO;
import jnpf.model.personnels.vo.roster.FtbRosterPageVO;
import jnpf.permission.dto.v2.user.QueryUserBoundDTO;
import jnpf.permission.vo.v2.user.UserBoundVO;
import jnpf.permission.vo.v2.user.api.OrganizeAndPositionAndGradeVO;
import jnpf.permission.vo.v2.user.api.OrganizeAndStoreTeamVO;
import jnpf.permission.vo.v2.user.api.OrganizeAndUserVO;
import jnpf.personnels.mapper.FtbPersonnelsRegistrationFormFieldMapper;
import jnpf.personnels.mapper.FtbPersonnelsRegistrationFormFieldOptionMapper;
import jnpf.personnels.mapper.FtbPersonnelsStaffRegistrationFormDataMapper;
import jnpf.personnels.service.FtbPersonnelsBlacklistService;
import jnpf.personnels.service.FtbPersonnelsRosterValidService;
import jnpf.personnels.utils.CacheExcelUtils;
import jnpf.personnels.utils.PersonnelIdCardVerificationUtils;
import jnpf.util.RedisUtil;
import jnpf.util.UserProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service("FtbPersonnelsRosterValidServiceNew")
public class FtbPersonnelsRosterValidServiceNewImpl implements FtbPersonnelsRosterValidService {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private CacheExcelUtils cacheExcelUtils;

    @Autowired
    private FtbPersonnelsRegistrationFormFieldMapper ftbPersonnelsRegistrationFormFieldMapper;

    @Autowired
    private FtbPersonnelsStaffRegistrationFormDataMapper ftbPersonnelsStaffRegistrationFormDataMapper;

    @Autowired
    private FtbPersonnelsRegistrationFormFieldOptionMapper ftbPersonnelsRegistrationFormFieldOptionMapper;

    @Resource
    private FtbPersonnelsBlacklistService ftbPersonnelsBlacklistService;

    @Resource
    private PersonnelIdCardVerificationUtils personnelIdCardVerificationUtils;

    @Override
    public Map<Integer, FtbRosterImportHeadRuleBO> headerVerification(String sheetName, Map<Integer, String> head) {
        LambdaQueryWrapper<FtbPersonnelsRegistrationFormField> queryWrapper = FtbRosterImportConstants.getRegistrationFormFieldQueryWrapper(null);
        List<FtbPersonnelsRegistrationFormField> registrationFormFields = ftbPersonnelsRegistrationFormFieldMapper.selectList(queryWrapper);
        // 额外项排除
        FtbRosterImportConstants.nameAndMobileNumberAddedNew(registrationFormFields, "3");
        // 校验必填项是否勾选一致
        long first = registrationFormFields.stream().filter(f -> f.getIsNeedFill() == 1).count();
        long second = head.values().stream().filter(a -> Objects.nonNull(a) && a.contains("*")).count();
        if (first != second) {
            throw new RuntimeException("表头必填项与配置项不一致，请重新勾选配置项下载最新模板导入");
        }
        Map<Integer, FtbRosterImportHeadRuleBO> result = new HashMap<>(head.size());
        head.forEach((k, v) -> {
            FtbRosterImportHeadRuleBO ftbRosterImportHeadRuleBO = new FtbRosterImportHeadRuleBO();
            FtbPersonnelsRegistrationFormField ftbPersonnelsRegistrationFormField = registrationFormFields.stream().filter(f -> {
                if (StrUtil.isNotBlank(v) && v.contains("*")) {
                    return f.getName().equals(v.substring(v.indexOf("*") + 1));
                }
                return f.getName().equals(v);
            }).findFirst().orElse(null);
            if (ftbPersonnelsRegistrationFormField == null) {
                throw new RuntimeException("表头不存在，请重新勾选配置项下载最新模板导入");
            }
            ftbRosterImportHeadRuleBO.setHeadName(v);
            ftbRosterImportHeadRuleBO.setVerificationRule(ftbPersonnelsRegistrationFormField.getRules());
            ftbRosterImportHeadRuleBO.setRequired(ftbPersonnelsRegistrationFormField.getIsNeedFill() == 1);
            // 校验字符仅限单行文本和多行文本
            if (Objects.nonNull(ftbPersonnelsRegistrationFormField.getType()) &&
                    (ftbPersonnelsRegistrationFormField.getType() == 0 || ftbPersonnelsRegistrationFormField.getType() == 1)) {
                ftbRosterImportHeadRuleBO.setVerificationCharacter(ftbPersonnelsRegistrationFormField.getLimits());
            }
            ftbRosterImportHeadRuleBO.setOptionType(ftbPersonnelsRegistrationFormField.getOptionType());
            ftbRosterImportHeadRuleBO.setFormTypeId(ftbPersonnelsRegistrationFormField.getFormTypeId());
            ftbRosterImportHeadRuleBO.setFormFieldId(ftbPersonnelsRegistrationFormField.getId());
            // 日期
            if (Objects.nonNull(ftbPersonnelsRegistrationFormField.getType()) && ftbPersonnelsRegistrationFormField.getType() == 4) {
                ftbRosterImportHeadRuleBO.setOptionType(100);
            }
            // 兼容自定义登记表字段单选和多选未设置选项情况
            if (Objects.nonNull(ftbPersonnelsRegistrationFormField.getType()) &&
                    ftbPersonnelsRegistrationFormField.getSystemType() == 1 &&
                    (ftbPersonnelsRegistrationFormField.getType() == 2 || ftbPersonnelsRegistrationFormField.getType() == 3)) {
                ftbRosterImportHeadRuleBO.setOptionType(1);
            }
            // 选项表中选项
            if (Objects.nonNull(ftbPersonnelsRegistrationFormField.getType()) &&
                    (ftbPersonnelsRegistrationFormField.getOptionType() == 1 ||
                            ftbPersonnelsRegistrationFormField.getType() == 2 || ftbPersonnelsRegistrationFormField.getType() == 3)) {
                LambdaQueryWrapper<FtbPersonnelsRegistrationFormFieldOption> formFieldOptionLambdaQueryWrapper = Wrappers.lambdaQuery();
                formFieldOptionLambdaQueryWrapper.select(FtbPersonnelsRegistrationFormFieldOption::getId, FtbPersonnelsRegistrationFormFieldOption::getName);
                formFieldOptionLambdaQueryWrapper.eq(FtbPersonnelsRegistrationFormFieldOption::getEnabledMark, 0);
                formFieldOptionLambdaQueryWrapper.eq(FtbPersonnelsRegistrationFormFieldOption::getFormFieldId, ftbPersonnelsRegistrationFormField.getId());
                List<FtbPersonnelsRegistrationFormFieldOption> ftbPersonnelsRegistrationFormFieldOptions = ftbPersonnelsRegistrationFormFieldOptionMapper.selectList(formFieldOptionLambdaQueryWrapper);
                ftbRosterImportHeadRuleBO.setVerificationOptions(
                        ftbPersonnelsRegistrationFormFieldOptions.stream()
                                .collect(Collectors.toMap(
                                        FtbPersonnelsRegistrationFormFieldOption::getName,
                                        FtbPersonnelsRegistrationFormFieldOption::getId,
                                        (s, a) -> a)));
            }
            result.put(k, ftbRosterImportHeadRuleBO);
        });
        return result;
    }

    @Override
    public void dataValidation(AnalysisContext context, Map<Integer, FtbRosterImportHeadRuleBO> head, Map<Integer, String> data,
                               FtbRosterCategoryVO normalData, FtbRosterCategoryVO errorData) {
        StringBuilder errorBuilder = new StringBuilder();
        FtbRosterPageVO ftbRosterPageVO = new FtbRosterPageVO();
        ftbRosterPageVO.setRowMark(context.readRowHolder().getRowIndex());
        List<FtbRosterAttributesVO> ftbRosterAttributesVOS = new ArrayList<>();
        // 数据补全，无法识别多行为空
        if (head.size()-1 > data.size()-1) {
            int dataSize = data.size()-1;
            for (int i=1;i<=head.size()-1-dataSize;i++) {
                data.put(dataSize+i, "");
            }
        }
        data.forEach((k, v) -> {
            FtbRosterAttributesVO ftbRosterAttributesVO = new FtbRosterAttributesVO();
            ftbRosterAttributesVO.setLineMark(context.readRowHolder().getRowIndex());
            ftbRosterAttributesVO.setColumnLabel(k);
            ftbRosterAttributesVO.setAttributeValue(v);
            FtbRosterImportHeadRuleBO ftbRosterImportHeadRuleBO = head.get(k);
            // 数据超出表头
            if (ftbRosterImportHeadRuleBO == null) {
                errorBuilder.append("所填数据无对应表头标题;");
                return;
            }
            ftbRosterAttributesVO.setAttributeName(ftbRosterImportHeadRuleBO.getHeadName());
            ftbRosterAttributesVO.setFormTypeId(ftbRosterImportHeadRuleBO.getFormTypeId());
            ftbRosterAttributesVO.setFormFieldId(ftbRosterImportHeadRuleBO.getFormFieldId());
            // 必填项没必填
            if (ftbRosterImportHeadRuleBO.getRequired() && StrUtil.isBlank(v)) {
                errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName()).append("字段内容必填;");
                ftbRosterAttributesVOS.add(ftbRosterAttributesVO);
                return;
            }
            if (StrUtil.isBlank(v)) {
                ftbRosterAttributesVOS.add(ftbRosterAttributesVO);
                return;
            }
            // 校验字符
            if (Objects.nonNull(ftbRosterImportHeadRuleBO.getVerificationCharacter()) &&
                    ftbRosterImportHeadRuleBO.getVerificationCharacter() > 0
                    && v.length() > ftbRosterImportHeadRuleBO.getVerificationCharacter()) {
                errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                        .append("字段内容不能超过")
                        .append(ftbRosterImportHeadRuleBO.getVerificationCharacter())
                        .append("字符;");
            }
            // 校验规则
            if (StrUtil.isNotBlank(ftbRosterImportHeadRuleBO.getVerificationRule())) {
                boolean regularCheck = Pattern.matches(ftbRosterImportHeadRuleBO.getVerificationRule(), v);
                if (!regularCheck) {
                    errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                            .append("字段内容格式有误;");
                }
            }
            // 校验匹配选项 1、选项表中选项  2、省市区选项  3、组织选项 4、岗位选项 5、职等选项 6、门店选项 7、直接主管选项
            if (Objects.nonNull(ftbRosterImportHeadRuleBO.getOptionType()) && ftbRosterImportHeadRuleBO.getOptionType() == 1) {
                // 区分单选和多选
                String multipleSelectionContent = Stream.of(v.split(StringPool.COMMA)).map(a -> {
                    if (!ftbRosterImportHeadRuleBO.getVerificationOptions().containsKey(a)) {
                        errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                                .append("字段内容").append(a).append("不在系统选项范围内;");
                    }
                    return ftbRosterImportHeadRuleBO.getVerificationOptions().get(a);
                }).filter(StrUtil::isNotBlank).collect(Collectors.joining(StringPool.COMMA));
                ftbRosterAttributesVO.setAttributeValueId(multipleSelectionContent);
            }
            // 日期校验
            if (Objects.nonNull(ftbRosterImportHeadRuleBO.getOptionType()) && ftbRosterImportHeadRuleBO.getOptionType() == 100) {
                String date = StringToDateConverter.dateFormatCheck(v);
                if (StrUtil.isBlank(date)) {
                    errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                            .append("字段内容格式有误;");
                } else {
                    // 校验出生日期
                    if ("出生日期".equals(ftbRosterImportHeadRuleBO.getHeadName())) {
                        // 出生日期需要小于今天
                        Date now = new Date();
                        if (DateUtil.parse(date).isAfter(now) || date.equals(DateUtil.format(now, "yyyy-MM-dd"))) {
                            errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName()).append("字段内容不能大于今天;");
                        }
                    } else if ("endHealthDate".equals(ftbRosterImportHeadRuleBO.getFormFieldId())) {
                        // 结束有效日期不能小于今天
                        Date now = new Date();
                        if (DateUtil.parse(date).isBefore(now) || date.equals(DateUtil.format(now, "yyyy-MM-dd"))) {
                            errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName()).append("字段内容不能小于今天;");
                        }
                        // 校验健康证结束有效日期不能小于健康证开始有效日期
                        ftbRosterAttributesVOS.stream()
                                .filter(a->"*开始有效日期".contains(a.getAttributeName()))
                                .findFirst().ifPresent(a -> {
                                    if (StrUtil.isNotBlank(v)) {
                                        if (DateUtil.parse(date).isBefore(DateUtil.parse(a.getAttributeValue()))) {
                                            errorBuilder.append("健康证结束有效日期不能小于健康证开始有效日期");
                                        }
                                    }
                                });
                    }
                    ftbRosterAttributesVO.setAttributeValue(date);
                }
            }
            // 合同类型
            if (Objects.nonNull(ftbRosterImportHeadRuleBO.getOptionType()) && ftbRosterImportHeadRuleBO.getOptionType() == 8) {
                String contractTypeName = cacheExcelUtils.doContractTypeName(v);
                if (StrUtil.isBlank(contractTypeName)) {
                    errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                            .append("字段").append(v).append("不在系统内;");
                } else {
                    ftbRosterAttributesVO.setAttributeValueId(contractTypeName);
                }
            }
            // 手机号码和姓名校验
            if ("*手机号码".equals(ftbRosterImportHeadRuleBO.getHeadName())) {
                // 手机号,离职黑名单校验
                if (ftbPersonnelsBlacklistService.hasItBeenBlacklisted(v)) {
                    errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                            .append("字段").append(v).append("已被拉入黑名单;");
                }

                // 校验手机号是否重复
                normalData.getFtbRosterPageVOS().stream()
                        .flatMap(a -> a.getFtbRosterAttributesVOS().stream())
                        .filter(FtbRosterImportConstants.phonePredicate)
                        .filter(c -> Objects.equals(v, c.getAttributeValue())).findFirst()
                        .ifPresent(rosterAttributesVO -> errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                                .append("字段").append(v).append("在第").append(rosterAttributesVO.getLineMark()).append("行存在重复;"));
            }
            // 身份证号校验
            if ("*身份证号码".contains(ftbRosterImportHeadRuleBO.getHeadName())) {
                normalData.getFtbRosterPageVOS().stream()
                        .flatMap(a -> a.getFtbRosterAttributesVOS().stream())
                        .filter(a -> "*身份证号码".contains(a.getAttributeName()))
                        .filter(c -> Objects.equals(v, c.getAttributeValue())).findFirst()
                        .ifPresent(rosterAttributesVO -> errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                                .append("字段").append(v).append("在第").append(rosterAttributesVO.getLineMark()).append("行存在重复;"));
                ftbRosterAttributesVOS.stream()
                        .filter(FtbRosterImportConstants.phonePredicate)
                        .findFirst().ifPresent(a -> {
                            if (StrUtil.isNotBlank(v)) {
                                if (ftbPersonnelsStaffRegistrationFormDataMapper.verifyWhetherTheDataExistsWithStaff(a.getAttributeValue(), "idCardNum", v) > 0) {
                                    errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                                            .append("字段").append(v).append("在系统内已存在;");
                                }
                                // 校验身份证号码出生日期是未来时间
                                boolean regularCheck = Pattern.matches(ftbRosterImportHeadRuleBO.getVerificationRule(), v);
                                if (regularCheck) {
                                    DateTime ageByIdCard = IdcardUtil.getBirthDate(v);
                                    if (ageByIdCard.isAfter(new Date())) {
                                        errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                                                .append("字段").append(v).append("值不正确;");
                                    }
                                }
                            }
                        });
                // 姓名+身份证号校验
                ftbRosterAttributesVOS.stream()
                        .filter(FtbRosterImportConstants.userNamePredicate)
                        .findFirst().ifPresent(a -> {
                            if (StrUtil.isNotBlank(v) && StrUtil.isNotBlank(a.getAttributeValue())) {
                                IdCardVerificationResponse idCardVerificationResponse = personnelIdCardVerificationUtils.idCardVerification(v,
                                        a.getAttributeValue(), UserProvider.getUser().getTenantId());
                                if (Objects.nonNull(idCardVerificationResponse) && !"0".equals(idCardVerificationResponse.getResult())) {
                                    errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                                            .append("字段").append(v).append(idCardVerificationResponse.getDescription()).append(";");
                                }
                            }
                        });
            }
            // 校验银行卡号
            if ("*银行卡号".contains(ftbRosterImportHeadRuleBO.getHeadName())) {
                normalData.getFtbRosterPageVOS().stream()
                        .flatMap(a -> a.getFtbRosterAttributesVOS().stream())
                        .filter(a -> "*银行卡号".contains(a.getAttributeName()))
                        .filter(c -> Objects.equals(v, c.getAttributeValue())).findFirst()
                        .ifPresent(rosterAttributesVO -> errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                                .append("字段").append(v).append("在第").append(rosterAttributesVO.getLineMark()).append("行存在重复;"));
                ftbRosterAttributesVOS.stream()
                        .filter(FtbRosterImportConstants.phonePredicate)
                        .findFirst().ifPresent(a -> {
                            if (StrUtil.isNotBlank(v)) {
                                if (ftbPersonnelsStaffRegistrationFormDataMapper.verifyWhetherTheDataExists(a.getAttributeValue(), "bankCardNo", v) > 0) {
                                    errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                                            .append("字段").append(v).append("在系统内已存在;");
                                }
                            }
                        });
            }
            // 校验公积金号
            if ("*个人公积金帐号".contains(ftbRosterImportHeadRuleBO.getHeadName())) {
                normalData.getFtbRosterPageVOS().stream()
                        .flatMap(a -> a.getFtbRosterAttributesVOS().stream())
                        .filter(a -> "*个人公积金帐号".contains(a.getAttributeName()))
                        .filter(c -> Objects.equals(v, c.getAttributeValue())).findFirst()
                        .ifPresent(rosterAttributesVO -> errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                                .append("字段").append(v).append("在第").append(rosterAttributesVO.getLineMark()).append("行存在重复;"));
                ftbRosterAttributesVOS.stream()
                        .filter(FtbRosterImportConstants.phonePredicate)
                        .findFirst().ifPresent(a -> {
                            if (StrUtil.isNotBlank(v)) {
                                if (ftbPersonnelsStaffRegistrationFormDataMapper.verifyWhetherTheDataExists(a.getAttributeValue(), "providentFundAccount", v) > 0) {
                                    errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                                            .append("字段").append(v).append("在系统内已存在;");
                                }
                            }
                        });
            }
            // 校验社保账号
            if ("*个人社保帐号".contains(ftbRosterImportHeadRuleBO.getHeadName())) {
                normalData.getFtbRosterPageVOS().stream()
                        .flatMap(a -> a.getFtbRosterAttributesVOS().stream())
                        .filter(a -> "*个人社保帐号".contains(a.getAttributeName()))
                        .filter(c -> Objects.equals(v, c.getAttributeValue())).findFirst()
                        .ifPresent(rosterAttributesVO -> errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                                .append("字段").append(v).append("在第").append(rosterAttributesVO.getLineMark()).append("行存在重复;"));
                ftbRosterAttributesVOS.stream()
                        .filter(FtbRosterImportConstants.phonePredicate)
                        .findFirst().ifPresent(a -> {
                            if (StrUtil.isNotBlank(v)) {
                                if (ftbPersonnelsStaffRegistrationFormDataMapper.verifyWhetherTheDataExists(a.getAttributeValue(), "socialAccount", v) > 0) {
                                    errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                                            .append("字段").append(v).append("在系统内已存在;");
                                }
                            }
                        });
            }
            // 直属主管校验
            if ("直属主管ID".equals(ftbRosterImportHeadRuleBO.getHeadName())) {
                FtbPersonnelsStaffRoster ftbPersonnelsStaffRoster = cacheExcelUtils.doVerificationByDirectSupervisor(v);
                if (ftbPersonnelsStaffRoster == null) {
                    errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                            .append("字段").append(v).append("不在系统内;");
                } else {
                    // 手机号
                    FtbRosterAttributesVO phoneFtbRosterAttributesVO = ftbRosterAttributesVOS.stream()
                            .filter(FtbRosterImportConstants.phonePredicate)
                            .findFirst()
                            .orElseGet(FtbRosterAttributesVO::new);
                    // 直属主管校验
                    if (StaffWorkerStatus.PRE_TRIAL.getCode().equals(ftbPersonnelsStaffRoster.getWorkerStatus())) {
                        errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                                .append("字段").append(v).append("，该用户处于试岗期");
                    } else if (StaffWorkerStatus.RESIGNED.getCode().equals(ftbPersonnelsStaffRoster.getWorkerStatus())) {
                        errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                                .append("字段").append(v).append("，该用户处于已经离职");
                    } else if (ftbPersonnelsStaffRoster.getPhone().equals(phoneFtbRosterAttributesVO.getAttributeValue())) {
                        errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                                .append("字段").append(v).append("，直属主管不能是自己");
                    }
                    FtbRosterAttributesVO organizationPredicate = ftbRosterAttributesVOS.stream().filter(FtbRosterImportConstants.organizationPredicate).findFirst().orElse(null);
                    if (organizationPredicate != null) {
                        OrganizeAndUserVO organizeAndUserVO = cacheExcelUtils.checkOrgNameAndUserId(organizationPredicate.getAttributeValue(), ftbPersonnelsStaffRoster.getUserId());
                        if (Objects.isNull(organizeAndUserVO)) {
                            errorBuilder.append(ftbRosterImportHeadRuleBO.getHeadName())
                                    .append("字段").append(v).append("不在系统内;");
                        } else {
                            ftbRosterAttributesVO.setAttributeValueId(organizeAndUserVO.getUserId());
                        }
                    }
                }
            }
            ftbRosterAttributesVOS.add(ftbRosterAttributesVO);
        });
        if (StrUtil.isBlank(errorBuilder.toString())) {
            // 手机号
            FtbRosterAttributesVO phoneFtbRosterAttributesVO = ftbRosterAttributesVOS.stream()
                    .filter(FtbRosterImportConstants.phonePredicate)
                    .findFirst()
                    .orElseGet(FtbRosterAttributesVO::new);
            UserBoundVO userBoundVO = cacheExcelUtils.doCheckPhoneExist(phoneFtbRosterAttributesVO.getAttributeValue());
            // 不能互为直属主管 A->B,B->A，则A->A
            if (Objects.nonNull(userBoundVO)) {
                ftbRosterAttributesVOS.stream().filter(a -> "入职直属主管ID".equals(a.getAttributeName())).findFirst().ifPresent(a -> {
                    UserBoundVO secondUserBoundVO = cacheExcelUtils.doQueryDirectlyUnderTheSupervisor(a.getAttributeValueId());
                    boolean isSameUserBound = Objects.nonNull(secondUserBoundVO) &&
                            userBoundVO.getId().equals(secondUserBoundVO.getLeaderId());
                    if (isSameUserBound) {
                        errorBuilder.append(userBoundVO.getUserName())
                                .append("是")
                                .append(secondUserBoundVO.getUserName())
                                .append("的直属主管，不能互为主管！");
                    }
                });
            }
            // 校验已存在的员工直属主管是否填写的
            // 校验所属组织、岗位、职级之间的绑定关系
            FtbRosterAttributesVO organizationPredicate = ftbRosterAttributesVOS.stream().filter(FtbRosterImportConstants.organizationPredicate).findFirst().orElse(null);
            FtbRosterAttributesVO postPredicate = ftbRosterAttributesVOS.stream().filter(FtbRosterImportConstants.postPredicate).findFirst().orElse(null);
            FtbRosterAttributesVO gradePredicate = ftbRosterAttributesVOS.stream().filter(FtbRosterImportConstants.gradePredicate).findFirst().orElse(null);
            FtbRosterAttributesVO team = ftbRosterAttributesVOS.stream().filter(FtbRosterImportConstants.team).findFirst().orElse(null);
            if (Objects.nonNull(organizationPredicate) && Objects.nonNull(postPredicate)) {
                QueryUserBoundDTO dto = new QueryUserBoundDTO();
                dto.setOrganizeName(organizationPredicate.getAttributeValue());
                dto.setPositionName(postPredicate.getAttributeValue());
                dto.setGradeName(Objects.nonNull(gradePredicate) ? gradePredicate.getAttributeValue() : null);
                OrganizeAndPositionAndGradeVO resultCheck = cacheExcelUtils.doCheckOrgPositionGradesBoundDTO(dto);
                // 所属组织-岗位-职级校验
                if (Objects.isNull(resultCheck) && Objects.nonNull(gradePredicate)) {
                    errorBuilder.append("所填写的组织名称、岗位名称、职级名称之间不存在绑定关系;");
                } else if (Objects.isNull(resultCheck)) {
                    errorBuilder.append("所填写的组织名称、岗位名称之间不存在绑定关系;");
                } else {
                    // 校验用户组织权限适用范围，返回null则为超级管理员
                    List<String> organizationIdDataPermissions = cacheExcelUtils.doPersonnelOrganizationIdDataPermissions();
                    if (Objects.nonNull(organizationIdDataPermissions) && !organizationIdDataPermissions.contains(resultCheck.getOrganizeId())) {
                        errorBuilder.append("导入组织与当前登录人所选权限组织不匹配;");
                    }
                    for (FtbRosterAttributesVO rosterAttributesVO : ftbRosterAttributesVOS) {
                        if (FtbRosterImportConstants.organizationPredicate.test(rosterAttributesVO)) {
                            rosterAttributesVO.setAttributeValueId(resultCheck.getOrganizeId());
                        }
                        if (FtbRosterImportConstants.postPredicate.test(rosterAttributesVO)) {
                            rosterAttributesVO.setAttributeValueId(resultCheck.getPositionId());
                        }
                        if (FtbRosterImportConstants.gradePredicate.test(rosterAttributesVO)) {
                            rosterAttributesVO.setAttributeValueId(resultCheck.getGradeId());
                        }
                    }
                    if (Objects.nonNull(userBoundVO)) {
                        // 校验组织、岗位是否与原有的保持一致
                        if (!userBoundVO.getOrganizeId().equals(resultCheck.getOrganizeId())) {
                            errorBuilder.append("填写的组织与员工现组织不符合;");
                        } else if (!userBoundVO.getPositionId().equals(resultCheck.getPositionId())) {
                            errorBuilder.append("填写的岗位与员工现岗位不符合;");
                        }
                    }
                }
            }
            if (Objects.nonNull(organizationPredicate) && Objects.nonNull(team)) {
                // 校验所属组织、班组之间的绑定关系
                if (StrUtil.isNotBlank(team.getAttributeValue())) {
                    OrganizeAndStoreTeamVO organizeAndStoreTeamVO = cacheExcelUtils.doOrganizeTeamVerification(organizationPredicate.getAttributeValue(), team.getAttributeValue());
                    if (Objects.isNull(organizeAndStoreTeamVO)) {
                        errorBuilder.append("所填写的组织名称、班组名称之间不存在绑定关系;");
                    } else {
                        for (FtbRosterAttributesVO rosterAttributesVO : ftbRosterAttributesVOS) {
                            if (FtbRosterImportConstants.team.test(rosterAttributesVO)) {
                                rosterAttributesVO.setAttributeValueId(organizeAndStoreTeamVO.getStoreTeamId());
                            }
                        }
                        if (Objects.nonNull(userBoundVO)) {
                            // 校验组织、岗位是否与原有的保持一致
                            if (!userBoundVO.getOrganizeId().equals(organizeAndStoreTeamVO.getOrganizeId())) {
                                errorBuilder.append("填写的班组与现组织不匹配;");
                            }
                        }
                    }
                }
            }
            // 实际入职日期校验是否大于今天
            FtbRosterAttributesVO actualDateOfJoining = ftbRosterAttributesVOS.stream().filter(FtbRosterImportConstants.actualDateOfJoining).findFirst().orElse(null);
            if (Objects.nonNull(actualDateOfJoining)) {
                String actualDateOfJoiningAttributeValue = actualDateOfJoining.getAttributeValue();
                Date date = StringToDateConverter.dateFormatParser(actualDateOfJoiningAttributeValue);
                if (date.after(new Date())) {
                    errorBuilder.append("实际入职日期不能大于当前日期;");
                }
                FtbPersonnelsStaffRoster ftbPersonnelsStaffRoster = cacheExcelUtils.doCheckPhoneStaffRosterExist(phoneFtbRosterAttributesVO.getAttributeValue());
                // 实际入职日期要晚于上一次离职日期
                if (Objects.nonNull(ftbPersonnelsStaffRoster) && Objects.nonNull(ftbPersonnelsStaffRoster.getDepartDate())
                        && "305".equals(ftbPersonnelsStaffRoster.getWorkerStatus())) {
                    if (date.before(ftbPersonnelsStaffRoster.getDepartDate()) || ftbPersonnelsStaffRoster.getDepartDate().compareTo(date) == 0) {
                        errorBuilder.append("实际入职日期不能早于上一次离职日期")
                                .append(DateUtil.format(ftbPersonnelsStaffRoster.getDepartDate(), DatePattern.CHINESE_DATE_PATTERN))
                                .append(";");
                    }
                }
                // 校验是否在入职管理存在，但未进入花名册中
                if (Objects.isNull(ftbPersonnelsStaffRoster) && cacheExcelUtils.checkInOnboardingManagement(phoneFtbRosterAttributesVO.getAttributeValue())) {
                    errorBuilder.append("该员工处于入职流程中")
                            .append(";");
                }
                // 已在花名册中存在且已离职，目前处理入职管理中。但是又从花名册导入
                if (Objects.nonNull(ftbPersonnelsStaffRoster) && "305".equals(ftbPersonnelsStaffRoster.getWorkerStatus())
                        && cacheExcelUtils.checkInOnboardingManagement(phoneFtbRosterAttributesVO.getAttributeValue())) {
                    errorBuilder.append("该员工处于入职流程中")
                            .append(";");
                }
            }
            // 员工状态为试用期，但是未填写试用期
            FtbRosterAttributesVO ftbRosterAttributesVO = ftbRosterAttributesVOS.stream().filter(FtbRosterImportConstants.employeeStatus).findFirst().orElse(null);
            if (Objects.nonNull(ftbRosterAttributesVO) && "试用".equals(ftbRosterAttributesVO.getAttributeValue())) {
                FtbRosterAttributesVO probationPeriod = ftbRosterAttributesVOS.stream().filter(FtbRosterImportConstants.probationPeriod).findFirst().orElse(null);
                if (Objects.isNull(probationPeriod) || StrUtil.isBlank(probationPeriod.getAttributeValue())) {
                    errorBuilder.append("员工状态为试用，请填写试用期;");
                }
            }
        }
        // 有错误信息
        String errorMsg = errorBuilder.toString();
        if (StrUtil.isNotBlank(errorMsg)) {
            // 手动加错误，逆向导出
            FtbRosterAttributesVO ftbRosterAttributesVO = new FtbRosterAttributesVO();
            ftbRosterAttributesVO.setLineMark(context.readRowHolder().getRowIndex());
            ftbRosterAttributesVO.setColumnLabel(errorData.getHead().size() + 1);
            ftbRosterAttributesVO.setAttributeName(FtbRosterImportConstants.ERROR_REMARKS);
            ftbRosterAttributesVO.setAttributeValue(errorMsg);
            ftbRosterAttributesVOS.add(ftbRosterAttributesVO);
            ftbRosterPageVO.setFtbRosterAttributesVOS(ftbRosterAttributesVOS);
            errorData.getFtbRosterPageVOS().add(ftbRosterPageVO);
        } else {
            ftbRosterPageVO.setFtbRosterAttributesVOS(ftbRosterAttributesVOS);
            normalData.getFtbRosterPageVOS().add(ftbRosterPageVO);
        }
    }

    @Override
    public void saveDataToRedis(AnalysisContext context, FtbRosterCategoryVO normalData, FtbRosterCategoryVO errorData) {
        if (normalData.getHead() == null) {
            throw new RuntimeException("导入文件模板不正确");
        }
        String loginUserId = UserProvider.getLoginUserId();
        String redisKey = String.format(FtbRosterImportConstants.ROSTER_IMPORT_SHEET_REDIS_VARIABLES, loginUserId);
        redisUtil.insertHash(redisKey, context.readSheetHolder().getSheetName(), JSON.toJSONString(new FtbRosterImportRedisBO(normalData, errorData)));
        // 30分钟自动过期
        redisUtil.expire(redisKey, 30 * 60);
    }

}
