package jnpf.personnels.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.google.common.collect.ImmutableMap;
import io.seata.core.context.RootContext;
import jnpf.base.ActionResult;
import jnpf.base.UserInfo;
import jnpf.base.entity.SuperBaseEntity;
import jnpf.certificate.service.CertificateInstanceService;
import jnpf.model.enums.FContractSignStatus;
import jnpf.model.enums.GrowthLogEnum;
import jnpf.model.enums.SelfrowingEnum;
import jnpf.model.enums.StaffWorkerStatus;
import jnpf.model.personnels.bo.FtbRosterImportConstants;
import jnpf.model.personnels.dto.regular.FtbPersonnelsRegularCreateDTO;
import jnpf.model.personnels.dto.staff.growth.AddGrowthLogDto;
import jnpf.model.personnels.dto.staff.registerform.ProbationPeriodDto;
import jnpf.model.personnels.dto.staff.roster.StaffBaseInfoDto;
import jnpf.model.personnels.po.FtbPersonnelsStaffGrowthLog;
import jnpf.model.personnels.po.FtbPersonnelsStaffRegistrationFormData;
import jnpf.model.personnels.po.FtbPersonnelsStaffRoster;
import jnpf.model.personnels.vo.roster.FtbRosterInsertAttributesVO;
import jnpf.model.personnels.vo.roster.FtbRosterInsertNomalVO;
import jnpf.permission.V2UserApi;
import jnpf.permission.dto.v2.UserBoundInfoDTO;
import jnpf.permission.dto.v2.user.BatchUpdateUserDTO;
import jnpf.permission.dto.v2.user.SaveUserDTO;
import jnpf.permission.vo.v2.user.SaveUserVO;
import jnpf.permission.vo.v2.user.UserBoundVO;
import jnpf.personnels.mapper.FtbPersonnelsStaffRosterMapper;
import jnpf.personnels.service.FtbPersonnelsRegularManagementService;
import jnpf.personnels.service.FtbPersonnelsStaffGrowthLogService;
import jnpf.personnels.service.FtbPersonnelsStaffRegistrationFormDataService;
import jnpf.personnels.service.FtbPersonnelsUchisuikePondService;
import jnpf.util.Constants;
import jnpf.util.SelfGrowthUtil;
import jnpf.util.UserProvider;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Component
@Slf4j
public class StaffRosterImportSaveUtils {
    @Autowired
    private FtbPersonnelsUchisuikePondService ftbPersonnelsUchisuikePondService;

    @Autowired
    private FtbPersonnelsRegularManagementService regularManagementService;

    @Autowired
    private PersonnelOrgUtils personnelOrgUtils;

    @Autowired
    private PersonnelAsyncServiceUtils personnelAsyncServiceUtils;

    @Autowired
    private FtbPersonnelsStaffRegistrationFormDataService registrationFormDataService;

    @Resource
    private FtbPersonnelsStaffRosterMapper staffRosterMapper;

    @Autowired
    private V2UserApi v2UserApi;

    @Resource
    private FtbPersonnelsStaffGrowthLogService ftbPersonnelsStaffGrowthLogService;

    @Resource
    private CertificateInstanceService certificateInstanceService;

    private static final String DEFAULT_USER_LOGO = "001.png";

    @SuppressWarnings("Duplicates")
    public void addImportRosters(List<FtbRosterInsertNomalVO> list) {
        if (CollectionUtil.isEmpty(list)) {
            return;
        }
        long totalStartTime = System.currentTimeMillis();
        if (list.size() > 500) {
            throw new RuntimeException("导入数据不能超过500条");
        }
        long startTimeBegin = System.currentTimeMillis();
        // 查询手机号是否在花名册列表中已存在
        List<String> phones = list.stream().map(FtbRosterInsertNomalVO::getPhone).collect(Collectors.toList());
        QueryWrapper<FtbPersonnelsStaffRoster> wrapper = new QueryWrapper<>();
        wrapper.lambda().in(FtbPersonnelsStaffRoster::getPhone, phones);
        List<FtbPersonnelsStaffRoster> rosterList = staffRosterMapper.selectList(wrapper);
        Map<String, FtbPersonnelsStaffRoster> rosterExistMap = rosterList.stream()
                .collect(Collectors.toMap(FtbPersonnelsStaffRoster::getPhone,
                        Function.identity(), (a, b) -> a));
        // 已存在的数据
        List<String> rosterIds = rosterList.stream().map(SuperBaseEntity.SuperIBaseEntity::getId).collect(Collectors.toList());
        Map<String, List<FtbPersonnelsStaffRegistrationFormData>> existFormDataMaps = new HashMap<>();
        if (!rosterIds.isEmpty()) {
            LambdaQueryWrapper<FtbPersonnelsStaffRegistrationFormData> formDataQueryWrapper = new LambdaQueryWrapper<>();
            formDataQueryWrapper.in(FtbPersonnelsStaffRegistrationFormData::getRosterId, rosterIds);
            List<FtbPersonnelsStaffRegistrationFormData> formDataList = registrationFormDataService.list(formDataQueryWrapper);
            existFormDataMaps = formDataList.stream()
                    .collect(Collectors.groupingBy(FtbPersonnelsStaffRegistrationFormData::getRosterId));
        }
        long existDataEndTime = System.currentTimeMillis();
        log.error("花名册导入(addImportRosters) 查询花名册及档案历史数据耗时：{}ms", existDataEndTime - startTimeBegin);
        List<String> existUserIds = rosterList.stream().map(FtbPersonnelsStaffRoster::getUserId).collect(Collectors.toList());
        Map<String, UserBoundVO> existUserMap = new HashMap<>();
        long userBoundStart = System.currentTimeMillis();
        ActionResult<List<UserBoundVO>> userPrimaryBoundBatch = v2UserApi.getUserPrimaryBoundBatch(existUserIds, null);
        long userBoundEnd = System.currentTimeMillis();
        log.error("花名册导入(addImportRosters) 查询已有用户绑定关系(getUserPrimaryBoundBatch)耗时：{}ms", userBoundEnd - userBoundStart);
        if (userPrimaryBoundBatch != null && CollUtil.isNotEmpty(userPrimaryBoundBatch.getData())) {
            existUserMap = userPrimaryBoundBatch.getData().stream().collect(Collectors.toMap(UserBoundVO::getId, Function.identity(), (k1, k2) -> k1));
        }
        // 构建数据入库
        // 用户组织架构组装
        List<SaveUserDTO> saveUserDTOs = new ArrayList<>();
        // 待新增的花名册数据
        List<FtbPersonnelsStaffRoster> newRosters = new ArrayList<>();
        // 待新增的花名册表单数据
        List<FtbPersonnelsStaffRegistrationFormData> newFormDatas = new ArrayList<>();
        // 员工成长
        List<AddGrowthLogDto> addGrowthLogDtos = new ArrayList<>();
        // 转正信息
        List<FtbPersonnelsRegularCreateDTO> createDTOs = new ArrayList<>();
        // 更新信息
        List<BatchUpdateUserDTO> updateUserBoundInfoDTOs = new ArrayList<>();
        // 待更新的花名册信息
        List<LambdaUpdateWrapper<FtbPersonnelsStaffRoster>> updateWrappers = new ArrayList<>();
        // 离职员工导入花名册，清除之前的数据，重新生成
        List<String> cleanRosterIds = new ArrayList<>();
        long buildDataStart = System.currentTimeMillis();
        Set<String> needAddUserIds = new HashSet<>();
        for (FtbRosterInsertNomalVO ftbRosterInsertNomalVO : list) {
            FtbPersonnelsStaffRoster oldRoster = rosterExistMap.get(ftbRosterInsertNomalVO.getPhone());
            if (null != oldRoster && !"305".equals(oldRoster.getWorkerStatus()) && oldRoster.getEnabledMark() == 0) {
                if (oldRoster.getWorkerStatus().equals("304")) {
                    // 待离职不处理
                    continue;
                }
                if (oldRoster.getWorkerStatus().equals("302") || oldRoster.getWorkerStatus().equals("303") || oldRoster.getWorkerStatus().equals("306")) {
                    // 更新数据，对于未存在的数据做新增，已存在的数据不做处理
                    FtbPersonnelsStaffRoster ftbPersonnelsStaffRoster = buildImportUpdateRoster(ftbRosterInsertNomalVO, oldRoster);
                    List<FtbPersonnelsStaffRegistrationFormData> ftbPersonnelsStaffRegistrationFormData = existFormDataMaps.getOrDefault(oldRoster.getId(), new ArrayList<>());
                    List<String> formFieldIds = ftbPersonnelsStaffRegistrationFormData.stream()
                            .filter(a -> {
                                if (StringUtils.isNotBlank(a.getValue())) {
                                    if ("[]".equals(a.getValue()) || "null".equals(a.getValue())) {
                                        return false;
                                    }
                                    return true;
                                }
                                return false;
                            })
                            .map(FtbPersonnelsStaffRegistrationFormData::getFormFieldId).collect(Collectors.toList());
                    List<FtbPersonnelsStaffRegistrationFormData> newFormData = buildImportFormData(ftbRosterInsertNomalVO, ftbPersonnelsStaffRoster, null);
                    // 若为空则可将新增的内容进行补充，若不为空则不进行补充
                    newFormData.removeIf(a -> formFieldIds.contains(a.getFormFieldId()));
                    // 更新入职班组、入职职级、入职直属主管
                    UserBoundVO userBoundVO = existUserMap.get(oldRoster.getUserId());
                    if (Objects.nonNull(userBoundVO)) {
                        if ((StrUtil.isEmpty(userBoundVO.getStoreTeamId()) && StrUtil.isNotEmpty(ftbPersonnelsStaffRoster.getCurrGroupId()))
                                || (StrUtil.isEmpty(userBoundVO.getGradeId()) && StrUtil.isNotEmpty(ftbPersonnelsStaffRoster.getCurrRank()))
                                || (StrUtil.isEmpty(userBoundVO.getLeaderId()) && StrUtil.isNotEmpty(ftbPersonnelsStaffRoster.getCurrReportsTo()))) {
                            BatchUpdateUserDTO userDTO = new BatchUpdateUserDTO();
                            userDTO.setUserId(oldRoster.getUserId());
                            UserBoundInfoDTO userBoundInfoDTO = new UserBoundInfoDTO();
                            userBoundInfoDTO.setOrganizeId(ftbPersonnelsStaffRoster.getCurrOrg());
                            userBoundInfoDTO.setPositionId(ftbPersonnelsStaffRoster.getCurrPosition());
                            if (StrUtil.isEmpty(userBoundVO.getGradeId()) && StrUtil.isNotEmpty(ftbPersonnelsStaffRoster.getCurrRank())) {
                                userBoundInfoDTO.setGradesId(ftbPersonnelsStaffRoster.getCurrRank());
                            } else {
                                userBoundInfoDTO.setGradesId(userBoundVO.getGradeId());
                            }
                            userBoundInfoDTO.setStoreTeamId(ftbPersonnelsStaffRoster.getCurrGroupId());
                            userBoundInfoDTO.setLeaderId(ftbPersonnelsStaffRoster.getCurrReportsTo());
                            userDTO.setBoundInfoDTO(userBoundInfoDTO);
                            // 更新用户信息
                            updateUserBoundInfoDTOs.add(userDTO);
                        }
                    }
                    // 更新转正日期
                    if (Objects.isNull(oldRoster.getActualProbationaryDate()) && Objects.nonNull(ftbPersonnelsStaffRoster.getActualProbationaryDate())) {
                        LambdaUpdateWrapper<FtbPersonnelsStaffRoster> updateWrapper = Wrappers.lambdaUpdate();
                        updateWrapper.eq(SuperBaseEntity.SuperIBaseEntity::getId, oldRoster.getId());
                        updateWrapper.set(FtbPersonnelsStaffRoster::getActualProbationaryDate, ftbPersonnelsStaffRoster.getActualProbationaryDate());
                        updateWrappers.add(updateWrapper);
                    }
                    newFormDatas.addAll(newFormData);
                }
            } else {
                // 新增数据，构建花名册
                FtbPersonnelsStaffRoster newRoster = buildImportRoster(ftbRosterInsertNomalVO);
                // 离职员工导入花名册，清除之前的数据，重新生成
                 if (null != oldRoster) {
                    newRoster.setId(oldRoster.getId());
                    cleanRosterIds.add(oldRoster.getId());
                    // 离职且未删除状态为多次入职
                    if ("305".equals(oldRoster.getWorkerStatus()) && oldRoster.getEnabledMark() == 0) {
                         newRoster.setJoinNum(oldRoster.getJoinNum() + 1);
                    } else if (oldRoster.getEnabledMark() == 1) {
                       // 之前员工已删除
                       newRoster.setJoinNum(1);
                    }
                } else {
                    // 生成Id主键
                    newRoster.setId(IdWorker.getIdStr());
                }
                // 转正数据整理
                FtbPersonnelsRegularCreateDTO createDTO = FtbPersonnelsRegularCreateDTO.coverFtbPersonnelsRegularInfoVO(newRoster);
                fillPositiveData(createDTO, newRoster, ftbRosterInsertNomalVO);
                // 员工档案信息
                List<FtbPersonnelsStaffRegistrationFormData> ftbPersonnelsStaffRegistrationFormData = buildImportFormData(ftbRosterInsertNomalVO, newRoster, createDTO);
                // 生成账号建立关系信息
                SaveUserDTO saveUserDTO = new SaveUserDTO();
                saveUserDTO.setAccount(newRoster.getPhone());
                saveUserDTO.setRealName(newRoster.getName());
                saveUserDTO.setMobilePhone(newRoster.getPhone());
                saveUserDTO.setWorkerStatus(newRoster.getWorkerStatus());
                saveUserDTO.setHeadIcon(DEFAULT_USER_LOGO);
                // 花名册员工id
                saveUserDTO.setSystemWorkerId(newRoster.getSystemWokerId());
                saveUserDTO.setWorkerStatus(newRoster.getWorkerStatus());
                // 入职时间
                saveUserDTO.setEntryDate(newRoster.getActualStartDate());
                // 转正时间
                saveUserDTO.setBecomeDate(newRoster.getActualProbationaryDate());
                UserBoundInfoDTO userBoundInfoDTO = new UserBoundInfoDTO();
                userBoundInfoDTO.setOrganizeId(newRoster.getCurrOrg());
                userBoundInfoDTO.setPositionId(newRoster.getCurrPosition());
                userBoundInfoDTO.setGradesId(newRoster.getCurrRank());
                userBoundInfoDTO.setStoreTeamId(newRoster.getCurrGroupId());
                userBoundInfoDTO.setLeaderId(newRoster.getCurrReportsTo());
                saveUserDTO.setBoundInfoDTO(userBoundInfoDTO);
                saveUserDTOs.add(saveUserDTO);
                newRosters.add(newRoster);
                newFormDatas.addAll(ftbPersonnelsStaffRegistrationFormData);
                // 员工成长
                AddGrowthLogDto addGrowthLogDto = new AddGrowthLogDto();
                addGrowthLogDto.setChangeDate(new Date());
                addGrowthLogDto.setNum(newRoster.getJoinNum());
                addGrowthLogDto.setGrowthType(GrowthLogEnum.FIRST_JOIN.getCode());
                // 添加导入实际入职日期
                addGrowthLogDto.setDetail(buildGrowthLogDetail(ftbRosterInsertNomalVO, newRoster));
                addGrowthLogDto.setActualStartDate(newRoster.getActualStartDate());
                addGrowthLogDto.setEmployeeId(newRoster.getSystemWokerId());
                addGrowthLogDto.setPhone(newRoster.getPhone());
                // 导入的
                addGrowthLogDtos.add(addGrowthLogDto);
                // 试用期状态同步转正数据
                if (newRoster.getWorkerStatus().equals(StaffWorkerStatus.TRIAL.getCode())) {
                    createDTOs.add(createDTO);
                }
            }
        }
        long buildDataEnd = System.currentTimeMillis();
        log.error("花名册导入(addImportRosters) 遍历导入数据构建新增/更新实体耗时：{}ms", buildDataEnd - buildDataStart);
        // 员工信息更新
        if (CollUtil.isNotEmpty(updateUserBoundInfoDTOs)) {
            long startTime = System.currentTimeMillis();
            v2UserApi.updateBatchUserInfo(updateUserBoundInfoDTOs);
            long costTime = System.currentTimeMillis() - startTime;
            log.error("员工信息更新耗时：{}ms", costTime);
        }
        // 清楚离职员工导入花名册
        doCleanPersonData(cleanRosterIds);
        // 花名册数据更新
        updateWrappers.forEach(a -> {
            staffRosterMapper.update(new FtbPersonnelsStaffRoster(), a);
        });
        // 数据集体入库
        if (CollUtil.isNotEmpty(saveUserDTOs)) {
            long startTime = System.currentTimeMillis();
            List<SaveUserVO> actionResult = v2UserApi.saveUserInfoBatch(saveUserDTOs);
            long costTime = System.currentTimeMillis() - startTime;
            log.error("数据集体入库耗时：{}ms", costTime);
            if (CollUtil.isNotEmpty(actionResult)) {
                Map<String, String> saveUserBatchMaps = actionResult.stream().collect(Collectors.toMap(SaveUserVO::getPhone, SaveUserVO::getUserId));
                List<String> userIds = actionResult.stream().map(SaveUserVO::getUserId).collect(Collectors.toList());
                needAddUserIds.addAll(userIds);
                // 重复入职
                //Map<String, Integer> numberOfOnboardings = getEntryCount(userIds);
                newRosters.parallelStream().forEach(a -> {
                    String userId = saveUserBatchMaps.get(a.getPhone());
                    a.setUserId(userId);
                    // 重复入职
//                    Integer numberOfOnboarding = numberOfOnboardings.get(userId);
//                    if (Objects.nonNull(numberOfOnboarding)) {
//                        a.setJoinNum(numberOfOnboarding + 1);
//                    } else {
//                        a.setJoinNum(1);
//                    }
                });
                addGrowthLogDtos.parallelStream().forEach(a -> {
                    String userId = saveUserBatchMaps.get(a.getPhone());
                    a.setUserId(userId);
                });
                createDTOs.parallelStream().forEach(a -> {
                    String userId = saveUserBatchMaps.get(a.getPhoneNumber());
                    a.setUserId(userId);
                });
                // 花名册数据入库
                long rosterSaveStart = System.currentTimeMillis();
                Db.saveBatch(newRosters);
                long rosterSaveEnd = System.currentTimeMillis();
                log.error("花名册导入(addImportRosters) 花名册主表批量入库耗时：{}ms", rosterSaveEnd - rosterSaveStart);
                // 员工成长数据入库
                if (CollUtil.isNotEmpty(addGrowthLogDtos)) {
                    long growthSaveStart = System.currentTimeMillis();
                    ftbPersonnelsStaffGrowthLogService.addGrowthLogBatch(addGrowthLogDtos);
                    long growthSaveEnd = System.currentTimeMillis();
                    log.error("花名册导入(addImportRosters) 员工成长批量入库耗时：{}ms", growthSaveEnd - growthSaveStart);
                }
                // 转正数据异步入库
                if (CollUtil.isNotEmpty(createDTOs)) {
                    long regularSaveStart = System.currentTimeMillis();
                    regularManagementService.applyForRegularizationBatch(createDTOs);
                    long regularSaveEnd = System.currentTimeMillis();
                    log.error("花名册导入(addImportRosters) 转正记录批量入库耗时：{}ms", regularSaveEnd - regularSaveStart);
                }
                // 删除用户历史档案信息
                long asyncHistoryStart = System.currentTimeMillis();
                asyncDeleteHistory(userIds);
                long asyncHistoryEnd = System.currentTimeMillis();
                log.error("花名册导入(addImportRosters) 异步删除历史档案提交耗时(不含后台执行)：{}ms", asyncHistoryEnd - asyncHistoryStart);
            }
        }
        // 花名册表单数据入库
        if (CollUtil.isNotEmpty(newFormDatas)) {
            long formDataStart = System.currentTimeMillis();
            // 优化：批量删除，减少数据库交互次数
            LambdaQueryWrapper<FtbPersonnelsStaffRegistrationFormData> deleteWrapper = Wrappers.lambdaQuery();
            List<String> phonesQuery = newFormDatas.stream()
                    .map(FtbPersonnelsStaffRegistrationFormData::getPhone)
                    .distinct()
                    .collect(Collectors.toList());
            List<String> formFieldIdsQuery = newFormDatas.stream()
                    .map(FtbPersonnelsStaffRegistrationFormData::getFormFieldId)
                    .distinct()
                    .collect(Collectors.toList());
            deleteWrapper.in(FtbPersonnelsStaffRegistrationFormData::getPhone, phonesQuery);
            deleteWrapper.in(FtbPersonnelsStaffRegistrationFormData::getFormFieldId, formFieldIdsQuery);
            List<FtbPersonnelsStaffRegistrationFormData> staffRegistrationFormDatas = registrationFormDataService.list(deleteWrapper);
            Map<String, Map<String, FtbPersonnelsStaffRegistrationFormData>> deleteMapStaffFormDatas = staffRegistrationFormDatas.stream()
                    .collect(Collectors.groupingBy(FtbPersonnelsStaffRegistrationFormData::getPhone,
                            Collectors.toMap(FtbPersonnelsStaffRegistrationFormData::getFormFieldId,
                                    Function.identity(),
                                    (old, newOne) -> newOne)));
            Map<String, List<FtbPersonnelsStaffRegistrationFormData>> phoneMaps = newFormDatas.stream().collect(Collectors.groupingBy(FtbPersonnelsStaffRegistrationFormData::getPhone));
            List<String> forDataIds = new ArrayList<>();
            phoneMaps.forEach((phone, formDatas) -> {
                Map<String, FtbPersonnelsStaffRegistrationFormData> registrationFormDataMap = deleteMapStaffFormDatas.get(phone);
                if (Objects.nonNull(registrationFormDataMap)) {
                    List<String> formFieldIds = formDatas.stream().map(FtbPersonnelsStaffRegistrationFormData::getFormFieldId).collect(Collectors.toList());
                    List<String> forDataId = registrationFormDataMap.entrySet().stream()
                            .filter(entry -> formFieldIds.contains(entry.getKey()))
                            .map(entry -> entry.getValue().getId()).collect(Collectors.toList());
                    forDataIds.addAll(forDataId);
                }
            });
            if (CollUtil.isNotEmpty(forDataIds)) {
                long formDeleteStart = System.currentTimeMillis();
                List<List<String>> forDataIdsPartitionIds = ListUtil.partition(forDataIds, 100);
                forDataIdsPartitionIds.forEach(a -> {
                    registrationFormDataService.removeBatchByIds(a);
                });
                long formDeleteEnd = System.currentTimeMillis();
                log.error("花名册导入(addImportRosters) 花名册表单数据批量删除耗时：{}ms", formDeleteEnd - formDeleteStart);
            }
            long formInsertStart = System.currentTimeMillis();
            Db.saveBatch(newFormDatas);
            long formInsertEnd = System.currentTimeMillis();
            log.error("花名册导入(addImportRosters) 花名册表单数据批量入库耗时：{}ms", formInsertEnd - formInsertStart);
            long formDataEnd = System.currentTimeMillis();
            log.error("花名册导入(addImportRosters) 花名册表单整体处理耗时：{}ms", formDataEnd - formDataStart);
        }
        // 内推池状态修改
        long pondStart = System.currentTimeMillis();
        newRosters.forEach(a -> ftbPersonnelsUchisuikePondService.updateWorkStatus(a.getWorkerStatus(), a.getPhone()));
        //健康证初始化
        certificateInstanceService.batchInitHealthCertificate(needAddUserIds);
        long pondEnd = System.currentTimeMillis();
        log.error("花名册导入(addImportRosters) 内推池状态更新耗时：{}ms", pondEnd - pondStart);
        log.error("花名册导入整体耗时(方法内)：{}ms", System.currentTimeMillis() - startTimeBegin);
        log.error("花名册导入整体耗时(含前置校验到结束)：{}ms", System.currentTimeMillis() - totalStartTime);
    }

    /**
     * 构建员工成长json
     */
    private String buildGrowthLogDetail(FtbRosterInsertNomalVO ftbRosterInsertNomalVO, FtbPersonnelsStaffRoster newRoster) {
        StaffBaseInfoDto dto = new StaffBaseInfoDto();
        ftbRosterInsertNomalVO.getFtbRosterInsertAttributesVOS()
                .stream()
                .filter(FtbRosterImportConstants.organizationPredicate)
                .findFirst()
                .ifPresent(data -> {
                    dto.setCurrOrg(data.getAttributeValue());
                    dto.setCurrOrgName(data.getOriginalValue());
                });
        ftbRosterInsertNomalVO.getFtbRosterInsertAttributesVOS()
                .stream()
                .filter(FtbRosterImportConstants.postPredicate)
                .findFirst()
                .ifPresent(data -> {
                    dto.setCurrPosition(data.getAttributeValue());
                    dto.setCurrPositionName(data.getOriginalValue());
                });
        ftbRosterInsertNomalVO.getFtbRosterInsertAttributesVOS()
                .stream()
                .filter(FtbRosterImportConstants.gradePredicate)
                .findFirst()
                .ifPresent(data -> {
                    dto.setCurrRank(data.getAttributeValue());
                    dto.setCurrRankName(data.getOriginalValue());
                });
        ftbRosterInsertNomalVO.getFtbRosterInsertAttributesVOS()
                .stream()
                .filter(a -> "入职直属主管ID".equals(a.getHeaderName()))
                .findFirst()
                .ifPresent(data -> {
                    dto.setReportsTo(data.getAttributeValue());
                    dto.setReportsToName(data.getOriginalValue());
                });
        dto.setActualStartDate(newRoster.getActualStartDate());
        return JSONUtil.toJsonStr(dto);
    }


    /**
     * 删除用户历史档案信息
     */
    public void asyncDeleteHistory(List<String> userIds) {
        UserInfo userInfo = UserProvider.getUser();
        String tenantId = userInfo.getTenantId();
        String token = userInfo.getToken();
        Map<String, String> headers = ImmutableMap.of(Constants.AUTHORIZATION.toLowerCase(), token);
        personnelAsyncServiceUtils.deleteTurnoverUserHistory(userIds, tenantId, headers);
    }

    private FtbPersonnelsStaffRoster buildImportRoster(FtbRosterInsertNomalVO vo) {
        FtbPersonnelsStaffRoster entity = new FtbPersonnelsStaffRoster();
        entity.setName(vo.getUserName());
        entity.setPhone(vo.getPhone());
        List<FtbRosterInsertAttributesVO> attributesVOList = vo.getFtbRosterInsertAttributesVOS();
        if (CollectionUtil.isNotEmpty(attributesVOList)) {
            for (FtbRosterInsertAttributesVO attributesVO : attributesVOList) {
                String formFieldId = attributesVO.getFormFieldId();
                String attributeValue = attributesVO.getAttributeValue();
                if ("actualStartDate".equals(formFieldId)) {
                    entity.setActualStartDate(personnelOrgUtils.stringDateToDate(attributeValue));
                } else if ("workerType".equals(formFieldId)) {
                    entity.setWorkerType(attributeValue);
                } else if ("workerStatus".equals(formFieldId)) {
                    entity.setWorkerStatus(attributeValue);
                } else if ("actualProbationaryDate".equals(formFieldId)) {
                    entity.setActualProbationaryDate(personnelOrgUtils.stringDateToDate(attributeValue));
                }
            }
        }
        entity.setSystemWokerId(SelfGrowthUtil.providePersonnelsCustomIDBasedOnTheModule(SelfrowingEnum.STAFF_ROSTER));
        entity.setJoinNum(1);
        entity.setEnabledMark(0);
        entity.setIsSubmitForm(1);
        entity.setContractStatus(FContractSignStatus.NOT_INITIATED.getCode());
        entity.setIsTrialJob(0);
        entity.setTrialJobDay(0);
        entity.setIsTrialFail(0);
        entity.setTrialFail("");
        entity.setIsSignSeparation(0);
        return entity;
    }

    private FtbPersonnelsStaffRoster buildImportUpdateRoster(FtbRosterInsertNomalVO vo, FtbPersonnelsStaffRoster oldRoster) {
        FtbPersonnelsStaffRoster newRoster = new FtbPersonnelsStaffRoster();
        BeanUtils.copyProperties(oldRoster, newRoster);
        newRoster.setCurrRank(null);
        vo.getFtbRosterInsertAttributesVOS().forEach(a -> {
            String formFieldId = a.getFormFieldId();
            String attributeValue = a.getAttributeValue();
            if ("affiliatedOrg".equals(formFieldId)) {
                newRoster.setCurrOrg(attributeValue);
            } else if ("affiliatedPosition".equals(formFieldId)) {
                newRoster.setCurrPosition(attributeValue);
            } else if ("affiliatedRank".equals(formFieldId)) {
                newRoster.setCurrRank(attributeValue);
            } else if ("currReportsToId".equals(formFieldId)) {
                newRoster.setCurrReportsTo(attributeValue);
            } else if ("team".equals(formFieldId)) {
                newRoster.setCurrGroupId(attributeValue);
            } else if (Objects.isNull(newRoster.getActualProbationaryDate()) && "actualProbationaryDate".equals(formFieldId)) {
                newRoster.setActualProbationaryDate(personnelOrgUtils.stringDateToDate(attributeValue));
            }
        });
        return newRoster;
    }

    private List<FtbPersonnelsStaffRegistrationFormData> buildImportFormData(FtbRosterInsertNomalVO vo, FtbPersonnelsStaffRoster newRoster, FtbPersonnelsRegularCreateDTO createDTO) {
        Date now = new Date();
        List<FtbPersonnelsStaffRegistrationFormData> result = vo.getFtbRosterInsertAttributesVOS().stream().map(data -> {
            FtbPersonnelsStaffRegistrationFormData formData = new FtbPersonnelsStaffRegistrationFormData();
            formData.setPhone(vo.getPhone());
            formData.setFormFieldId(data.getFormFieldId());
            formData.setFormTypeId(data.getFormTypeId());
            formData.setValue(data.getAttributeValue());
            formData.setRosterId(newRoster.getId());
            // 试用期
            if ("probationPeriod".equals(data.getFormFieldId())) {
                ProbationPeriodDto probationPeriodDto = new ProbationPeriodDto(StringUtils.isEmpty(data.getAttributeValue()) ? "100" : data.getAttributeValue(), "0");
                if (StaffWorkerStatus.FULL_TIME.getCode().equals(newRoster.getWorkerStatus())) {
                    probationPeriodDto = new ProbationPeriodDto("100", "0");
                }
                formData.setValue(JSONUtil.toJsonStr(probationPeriodDto));
            }
            return formData;
        }).collect(Collectors.toList());
        // 司龄（系统自动计算），单位天
        if (null != newRoster.getActualStartDate()) {
            FtbPersonnelsStaffRegistrationFormData formData = new FtbPersonnelsStaffRegistrationFormData();
            formData.setPhone(vo.getPhone());
            formData.setFormFieldId("companyAge");
            formData.setFormTypeId("3");
            formData.setRosterId(newRoster.getId());
            if (now.after(newRoster.getActualStartDate())) {
                long betweenDay = DateUtil.betweenDay(newRoster.getActualStartDate(), new Date(), false);
                formData.setValue(String.valueOf(betweenDay));
            } else {
                formData.setValue("0");
            }
            result.add(formData);
        }
        // 身份证号码识别出生日期
        vo.getFtbRosterInsertAttributesVOS().stream()
                .filter(data -> "idCardNum".equals(data.getFormFieldId()) && StringUtils.isNotEmpty(data.getAttributeValue()))
                .findFirst()
                .ifPresent(data -> {
                    // 出生日期
                    Date birthDate = IdcardUtil.getBirthDate(data.getAttributeValue());
                    result.add(new FtbPersonnelsStaffRegistrationFormData() {{
                        setPhone(vo.getPhone());
                        setFormFieldId("birthday");
                        setFormTypeId("1");
                        setRosterId(newRoster.getId());
                        setValue(DateUtil.format(birthDate, "yyyy-MM-dd"));
                    }});
                    // 年龄
                    result.add(new FtbPersonnelsStaffRegistrationFormData() {{
                        setPhone(vo.getPhone());
                        setFormFieldId("age");
                        setFormTypeId("1");
                        setRosterId(newRoster.getId());
                        setValue(DateUtil.ageOfNow(birthDate) + "岁");
                    }});
                });
        // 正式状态员工，实际转正日期与实际入职日期保持一致
        if (newRoster.getWorkerStatus().equals(StaffWorkerStatus.FULL_TIME.getCode())) {
            result.removeIf(a -> "actualProbationaryDate".equals(a.getFormFieldId()));
            result.add(new FtbPersonnelsStaffRegistrationFormData() {{
                setPhone(vo.getPhone());
                setFormFieldId("actualProbationaryDate");
                setFormTypeId("3");
                setRosterId(newRoster.getId());
                setValue(DateUtil.format(newRoster.getActualStartDate(), "yyyy-MM-dd"));
            }});
        }
        // 员工状态为试用期，自动填充计划转正日期，并将实际转正日期清空
        if (newRoster.getWorkerStatus().equals(StaffWorkerStatus.TRIAL.getCode())) {
            newRoster.setActualProbationaryDate(null);
            result.removeIf(a -> "actualProbationaryDate".equals(a.getFormFieldId()));
            // 自动填充计划转正日期
            FtbRosterInsertAttributesVO ftbRosterInsertAttributesVO = vo.getFtbRosterInsertAttributesVOS()
                    .stream()
                    .filter(a -> "probationPeriod".equals(a.getFormFieldId()))
                    .findFirst()
                    .orElseGet(FtbRosterInsertAttributesVO::new);
            result.removeIf(a -> "planProbationaryDate".equals(a.getFormFieldId()));
            FtbPersonnelsStaffRegistrationFormData formData = new FtbPersonnelsStaffRegistrationFormData();
            formData.setPhone(vo.getPhone());
            formData.setFormFieldId("planProbationaryDate");
            formData.setFormTypeId("3");
            formData.setRosterId(newRoster.getId());
            String dateIsCalculated = thePlannedConversionDateIsCalculated(newRoster.getActualStartDate(), ftbRosterInsertAttributesVO.getAttributeValue());
            formData.setValue(dateIsCalculated);
            result.add(formData);
            // 仅限新增花名册导入
            if (Objects.nonNull(createDTO)) {
                createDTO.setProbation(ftbRosterInsertAttributesVO.getAttributeValue());
                // 计划转正日期
                createDTO.setSchedConverDate(DateUtil.parse(dateIsCalculated, "yyyy-MM-dd"));
            }
        }
        return result;
    }

    /**
     * 清空花名册和用户详情数据
     */
    private void doCleanPersonData(List<String> rosterId) {
        if (CollUtil.isNotEmpty(rosterId)) {
            staffRosterMapper.deleteBatchIds(rosterId);
            String xid = RootContext.getXID();
            RootContext.unbind();
            LambdaQueryWrapper<FtbPersonnelsStaffRegistrationFormData> deleteWrapper = new LambdaQueryWrapper<>();
            deleteWrapper.in(FtbPersonnelsStaffRegistrationFormData::getRosterId, rosterId);
            registrationFormDataService.remove(deleteWrapper);
            RootContext.bind(xid);
        }
    }

    /**
     * 计划转正日期计算
     * 100	无试用期
     * 101	1个月内
     * 102	1个月
     * 103	2个月
     * 104	3个月
     * 105	4个月
     * 106	5个月
     * 107	6个月
     * 108	7个月
     * 109	8个月
     * 110	9个月
     * 111	10个月
     * 112	11个月
     * 113	12个月
     */
    private String thePlannedConversionDateIsCalculated(Date actualStartDate, String probationPeriod) {
        if (StrUtil.isBlank(probationPeriod) || "100".equals(probationPeriod)) {
            return DateUtil.format(actualStartDate, "yyyy-MM-dd");
        }
        int probation = 0;
        switch (probationPeriod) {
            case "102":
                probation = 1;
                break;
            case "103":
                probation = 2;
                break;
            case "104":
                probation = 3;
                break;
            case "105":
                probation = 4;
                break;
            case "106":
                probation = 5;
                break;
            case "107":
                probation = 6;
                break;
            case "108":
                probation = 7;
                break;
            case "109":
                probation = 8;
                break;
            case "110":
                probation = 9;
                break;
            case "111":
                probation = 10;
                break;
            case "112":
                probation = 11;
                break;
            case "113":
                probation = 12;
        }
        Date time = DateUtil.offsetMonth(actualStartDate, probation);
        return DateUtil.format(time, "yyyy-MM-dd");
    }

    /**
     * 填充转正及花名册组织、岗位、职等、班组信息
     */
    private void fillPositiveData(FtbPersonnelsRegularCreateDTO createDTO, FtbPersonnelsStaffRoster newRoster, FtbRosterInsertNomalVO ftbRosterInsertNomalVO) {
        if (CollectionUtil.isNotEmpty(ftbRosterInsertNomalVO.getFtbRosterInsertAttributesVOS())) {
            for (FtbRosterInsertAttributesVO attributesVO : ftbRosterInsertNomalVO.getFtbRosterInsertAttributesVOS()) {
                String formFieldId = attributesVO.getFormFieldId();
                String attributeValue = attributesVO.getAttributeValue();
                String originalValue = attributesVO.getOriginalValue();
                if ("affiliatedOrg".equals(formFieldId)) {
                    newRoster.setCurrOrg(attributeValue);
                    createDTO.setOrgId(attributeValue);
                    createDTO.setOrgName(originalValue);
                } else if ("affiliatedPosition".equals(formFieldId)) {
                    newRoster.setCurrPosition(attributeValue);
                    createDTO.setRegularPostId(attributeValue);
                    createDTO.setOnboardPostId(attributeValue);
                    createDTO.setRegularPostName(originalValue);
                    createDTO.setOnboardPostName(originalValue);
                } else if ("affiliatedRank".equals(formFieldId)) {
                    newRoster.setCurrRank(attributeValue);
                    createDTO.setRegularGradeId(attributeValue);
                    createDTO.setOnboardGradeId(attributeValue);
                    createDTO.setRegularGradeName(originalValue);
                    createDTO.setOnboardGradeName(originalValue);
                } else if ("currReportsToId".equals(formFieldId)) {
                    newRoster.setCurrReportsTo(attributeValue);
                    createDTO.setImmediateSuperName(originalValue);
                    createDTO.setImmediateSuperId(attributeValue);
                } else if ("team".equals(formFieldId)) {
                    newRoster.setCurrGroupId(attributeValue);
                }
            }
        }
    }

    /**
     * 入职次数
     *
     * @param userIds 用户Id集合
     * @return key为userId, value为入职次数
     */
    private Map<String, Integer> getEntryCount(List<String> userIds) {
        LambdaQueryWrapper<FtbPersonnelsStaffGrowthLog> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(FtbPersonnelsStaffGrowthLog::getUserId, userIds);
        queryWrapper.in(FtbPersonnelsStaffGrowthLog::getGrowthType, 0, 3);
        List<FtbPersonnelsStaffGrowthLog> ftbPersonnelsStaffGrowthLogs = ftbPersonnelsStaffGrowthLogService.list(queryWrapper);
        return ftbPersonnelsStaffGrowthLogs.stream()
                .collect(Collectors.groupingBy(FtbPersonnelsStaffGrowthLog::getUserId, Collectors.summingInt(log -> 1)));
    }

}
