package com.qmth.sop.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.sop.business.bean.dto.UserArchivesImportDto;
import com.qmth.sop.business.bean.params.UserArchivesParam;
import com.qmth.sop.business.bean.result.*;
import com.qmth.sop.business.entity.*;
import com.qmth.sop.business.mapper.TBUserArchivesMapper;
import com.qmth.sop.business.service.*;
import com.qmth.sop.common.contant.SystemConstant;
import com.qmth.sop.common.enums.*;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 人员档案表 服务实现类
 * </p>
 *
 * @author wangliang
 * @since 2023-08-01
 */
@Service
public class TBUserArchivesServiceImpl extends ServiceImpl<TBUserArchivesMapper, TBUserArchives> implements TBUserArchivesService {
    @Resource
    private SysUserRoleService sysUserRoleService;
    @Resource
    private SysSupplierService sysSupplierService;
    @Resource
    private TBUserArchivesSupplierService tbUserArchivesSupplierService;
    @Resource
    private SysUserService sysUserService;
    @Resource
    private TBServiceService tbServiceService;
    @Resource
    private TBCrmService tbCrmService;
    @Resource
    private SysRoleService sysRoleService;
    @Resource
    private BasicAttachmentService basicAttachmentService;
    @Resource
    private TBUserArchivesService tbUserArchivesService;
    @Resource
    private SequenceService sequenceService;
    @Resource
    private TBSopInfoService tbSopInfoService;

    @Override
    public IPage<UserArchivesResult> findUserArchivesPage(String city, Long supplierId, String archivesName, RoleTypeEnum roleType, Boolean authenticationStatus, Long archivesTimeStart, Long archivesTimeEnd, Integer remainValidDay, Integer pageNumber, Integer pageSize) throws Exception {
        if (city != null && city.length() > 0) {
            city = SystemConstant.translateSpecificSign(city);
        }
        if (archivesName != null && archivesName.length() > 0) {
            archivesName = SystemConstant.translateSpecificSign(archivesName);
        }
        // 认证的角色枚举
        List<RoleTypeEnum> authRole = new ArrayList<>();
        authRole.add(RoleTypeEnum.EFFECT_ENGINEER);
        authRole.add(RoleTypeEnum.REGION_COORDINATOR);
        authRole.add(RoleTypeEnum.ASSISTANT_ENGINEER);

        Long remainValidTime = null;
        if (remainValidDay != null && remainValidDay > 0) {
            remainValidTime = SystemConstant.processMiniutePlus(Duration.ofDays(remainValidDay));
        }
        Long currentTime = System.currentTimeMillis();
        IPage<UserArchivesResult> page = this.baseMapper.findUserArchivesPage(new Page<>(pageNumber, pageSize), city, supplierId, archivesName, roleType, authenticationStatus, archivesTimeStart, archivesTimeEnd, remainValidTime, currentTime);
        for (UserArchivesResult record : page.getRecords()) {
            List<RoleResult> roleResultList = new ArrayList<>();
            Long userId = record.getUserId();
            if (userId != null && userId > 0) {
                for (RoleTypeEnum roleTypeEnum : authRole) {
                    // TODO: 2023/8/14 可优化查询 
                    if (sysUserRoleService.userContainsRoles(userId, roleTypeEnum)) {
                        RoleResult roleResult = sysRoleService.findRoleInfoByArchivesType(roleTypeEnum);
                        if (Objects.nonNull(roleResult)) {
                            roleResultList.add(roleResult);
                        }
                    }
                }
            }
            record.setRoleInfoList(roleResultList);
            record.setAge(this.getAgeByIdentity(record.getIdentity()));
            record.setAuthenticationStatus(record.getAuthenticationValidTime() != null && record.getAuthenticationValidTime() > currentTime);
            String basePhotoPath = record.getBasePhotoPath();
            if (basePhotoPath != null && basePhotoPath.length() > 0) {
                record.setBasePhotoPreviewPath(basicAttachmentService.filePreviewPath(basePhotoPath));
            }

            // 人员占用情况
            List<TBCrm> occupiedCrm = tbCrmService.findOccupiedCrm(userId, null);
            if (CollectionUtils.isNotEmpty(occupiedCrm)) {
                String occupiedInfo = occupiedCrm.stream()
                        .map(e -> String.format("%s(%s)", e.getName(), e.getCrmNo()))
                        .collect(Collectors.joining(";"));
                record.setOccupiedInfo(occupiedInfo);
            }
        }
        return page;
    }

    /**
     * 根据身份证号解析年龄
     *
     * @param identity identity
     * @return 年龄
     * @throws ParseException 异常
     */
    private Integer getAgeByIdentity(String identity) throws ParseException {
        Calendar calendar = Calendar.getInstance();
        int currentYear = calendar.get(Calendar.YEAR);
        // 提取身份证号中的出生日期
        String birthDateStr = identity.substring(6, 14);
        // 将出生日期字符串转换为Date类型
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        Date birthDate = dateFormat.parse(birthDateStr);
        // 计算年龄
        calendar.setTime(birthDate);
        int birthYear = calendar.get(Calendar.YEAR);
        // 打印年龄
        return currentYear - birthYear;
    }

    @Transactional
    @Override
    public Long editUserArchives(UserArchivesParam userArchivesParam, SysUser requestUser) throws InterruptedException {
        Long id = userArchivesParam.getId();
        // 校验身份证号唯一
        String identify = userArchivesParam.getIdentity();
        List<TBUserArchives> identifyCheckList = this.list(new QueryWrapper<TBUserArchives>().lambda().eq(TBUserArchives::getIdentity, identify));
        if (identifyCheckList.size() > 1) {
            throw ExceptionResultEnum.ERROR.exception("系统中存在多个相同的身份证号异常[" + identify + "]");
        } else if (identifyCheckList.size() == 1) {
            TBUserArchives identifyCheck = identifyCheckList.get(0);
            if (!Objects.equals(identifyCheck.getId(), id)) {
                throw ExceptionResultEnum.ERROR.exception("系统中已经存在身份证号[" + identify + "]");
            }
        }
        // 校验手机号唯一
        String mobileNumber = userArchivesParam.getMobileNumber();
        List<TBUserArchives> mobileNumberCheckList = this.list(new QueryWrapper<TBUserArchives>().lambda().eq(TBUserArchives::getMobileNumber, mobileNumber));
        if (mobileNumberCheckList.size() > 1) {
            throw ExceptionResultEnum.ERROR.exception("系统中存在多个相同的手机号异常[" + mobileNumber + "]");
        } else if (mobileNumberCheckList.size() == 1) {
            TBUserArchives mobileNumberCheck = mobileNumberCheckList.get(0);
            if (!Objects.equals(mobileNumberCheck.getId(), id)) {
                throw ExceptionResultEnum.ERROR.exception("系统中已经存在手机号[" + mobileNumber + "]");
            }
        }

        String name = userArchivesParam.getName();
        String country = userArchivesParam.getCountry();
        String province = userArchivesParam.getProvince();
        String city = userArchivesParam.getCity();
        String area = userArchivesParam.getArea();
        String address = userArchivesParam.getAddress();
        GenderEnum gender = userArchivesParam.getGender();
        EducationEnum education = userArchivesParam.getEducation();
        String email = userArchivesParam.getEmail();
        String basePhotoPath = userArchivesParam.getBasePhotoPath();
        Long supplierId = userArchivesParam.getSupplierId();
        if (supplierId != null && supplierId > 0) {
            SysSupplier sysSupplier = sysSupplierService.getById(supplierId);
            if (Objects.isNull(sysSupplier)) {
                throw ExceptionResultEnum.ERROR.exception("供应商不存在");
            }
        }
        Long archivesTime = userArchivesParam.getArchivesTime();
        Long[] roleIds = userArchivesParam.getRoleIds();
        Long authenticationTime = userArchivesParam.getAuthenticationTime();
        Double authenticationScore = userArchivesParam.getAuthenticationScore();
        Long authenticationValidTime = userArchivesParam.getAuthenticationValidTime();
        String remark = userArchivesParam.getRemark();

        TBUserArchives tbUserArchives = new TBUserArchives();
        tbUserArchives.setName(name);
        tbUserArchives.setCountry(country);
        tbUserArchives.setProvince(province);
        tbUserArchives.setCity(city);
        tbUserArchives.setArea(area);
        tbUserArchives.setAddress(address);
        tbUserArchives.setIdentity(identify);
        tbUserArchives.setGender(gender);
        tbUserArchives.setEducation(education);
        tbUserArchives.setMobileNumber(mobileNumber);
        tbUserArchives.setEmail(email);
        tbUserArchives.setEnable(true);
        tbUserArchives.setBasePhotoPath(basePhotoPath);
        // 档案表编辑
        Long userId = null;
        if (id == null || id == 0) {
            // 新增
            String code = sequenceService.createSerialNo(SequenceEnum.USER_ARCHIVES_CODE);
            tbUserArchives.setStatus(UserArchivesStatusEnum.FREE);
            tbUserArchives.setCreateId(requestUser.getId());
            tbUserArchives.setCode(code);
            this.save(tbUserArchives);
            id = tbUserArchives.getId();
            List<SysUser> userList = sysUserService.list(new QueryWrapper<SysUser>().lambda().eq(SysUser::getMobileNumber, mobileNumber));
            if (CollectionUtils.isNotEmpty(userList)) {
                if (userList.size() > 1) {
                    throw ExceptionResultEnum.ERROR.exception("用户表数据异常: 存在多个手机号相同的用户[" + mobileNumber + "]");
                }
                userId = userList.get(0).getId();
            }
        } else {
            // 编辑
            TBUserArchives old = this.getById(id);
            if (Objects.isNull(old)) {
                throw ExceptionResultEnum.ERROR.exception("用户不存在");
            }
            List<SysUser> userList = sysUserService.list(new QueryWrapper<SysUser>().lambda().eq(SysUser::getMobileNumber, old.getMobileNumber()));
            if (CollectionUtils.isNotEmpty(userList)) {
                if (userList.size() > 1) {
                    throw ExceptionResultEnum.ERROR.exception("用户表数据异常: 存在多个手机号相同的用户[" + mobileNumber + "]");
                }
                userId = userList.get(0).getId();
            }
            tbUserArchives.setId(id);
            tbUserArchives.setUpdateId(requestUser.getId());
            this.updateById(tbUserArchives);
        }

        // 档案详细表编辑 （先根据档案id删除再新增）
        tbUserArchivesSupplierService.remove(new QueryWrapper<TBUserArchivesSupplier>().lambda().eq(TBUserArchivesSupplier::getUserArchivesId, id));
        TBUserArchivesSupplier tbUserArchivesSupplier = new TBUserArchivesSupplier();
        tbUserArchivesSupplier.setUserArchivesId(id);
        tbUserArchivesSupplier.setArchivesTime(archivesTime);
        tbUserArchivesSupplier.setAuthenticationTime(authenticationTime);
        tbUserArchivesSupplier.setAuthenticationScore(authenticationScore);
        tbUserArchivesSupplier.setAuthenticationValidTime(authenticationValidTime);
        tbUserArchivesSupplier.setSupplierId(supplierId);
        tbUserArchivesSupplier.setRemark(remark);
        tbUserArchivesSupplierService.save(tbUserArchivesSupplier);

        // 用户编辑 - 根据手机号关联更新
        SysUser sysUser = new SysUser();
        if (userId != null && userId > 0) {
            // 编辑
            sysUser = sysUserService.getById(userId);
        }
        sysUser.setLoginName(mobileNumber);
        sysUser.setRealName(name);
        sysUser.setMobileNumber(mobileNumber);
        sysUser.setGender(gender);
        sysUser.setRoleIds(roleIds);
        sysUser.setSource(UserSourceEnum.ARCHIVES);
        sysUserService.saveUser(sysUser, requestUser);
        return id;
    }

    @Override
    public UserArchivesSubTotalResult findUserArchivesSubTotal(String city, Long supplierId, String archivesName, RoleTypeEnum roleType, Boolean authenticationStatus, Long archivesTimeStart, Long archivesTimeEnd, Integer remainValidDay) {
        UserArchivesSubTotalResult result = new UserArchivesSubTotalResult();
        if (city != null && city.length() > 0) {
            city = SystemConstant.translateSpecificSign(city);
        }
        if (archivesName != null && archivesName.length() > 0) {
            archivesName = SystemConstant.translateSpecificSign(archivesName);
        }

        Long remainValidTime = null;
        if (remainValidDay != null && remainValidDay > 0) {
            remainValidTime = SystemConstant.processMiniutePlus(Duration.ofDays(remainValidDay));
        }
        Long currentTime = System.currentTimeMillis();
        List<UserArchivesResult> userArchivesResultList = this.baseMapper.findUserArchivesList(city, supplierId, archivesName, roleType, authenticationStatus, archivesTimeStart, archivesTimeEnd, remainValidTime, currentTime);
        if (CollectionUtils.isNotEmpty(userArchivesResultList)) {
            Integer totalCount = userArchivesResultList.size();
            List<UserArchivesResult> validList = userArchivesResultList.stream()
                    .filter(e -> e.getAuthenticationValidTime() != null && e.getAuthenticationValidTime() > currentTime)
                    .collect(Collectors.toList());
            Integer validCount = validList.size();
            Integer inValidCount = totalCount - validCount;

            result.setTotalCount(totalCount);
            result.setValidCount(validCount);
            result.setInvalidCount(inValidCount);

            List<Long> userIdList = validList.stream().map(UserArchivesResult::getUserId).distinct().collect(Collectors.toList());
            List<SysUserBriefResult> effectEngineer = sysUserService.findUserListByRoleType(RoleTypeEnum.EFFECT_ENGINEER);
            int effectEngineerCount = 0;
            if (CollectionUtils.isNotEmpty(effectEngineer)) {
                List<Long> effectEngineerIdList = effectEngineer.stream().map(SysUserBriefResult::getId).distinct().collect(Collectors.toList());
                effectEngineerCount = (int) userIdList.stream().filter(effectEngineerIdList::contains).count();
            }
            result.setEffectEngineerCount(effectEngineerCount);

            List<SysUserBriefResult> regionCoordinator = sysUserService.findUserListByRoleType(RoleTypeEnum.REGION_COORDINATOR);
            int regionCoordinatorCount = 0;
            if (CollectionUtils.isNotEmpty(regionCoordinator)) {
                List<Long> regionCoordinatorIdList = regionCoordinator.stream().map(SysUserBriefResult::getId).distinct().collect(Collectors.toList());
                regionCoordinatorCount = (int) userIdList.stream().filter(regionCoordinatorIdList::contains).count();
            }
            result.setRegionCoordinatorCount(regionCoordinatorCount);

            List<SysUserBriefResult> assistantEngineer = sysUserService.findUserListByRoleType(RoleTypeEnum.ASSISTANT_ENGINEER);
            int assistantEngineerCount = 0;
            if (CollectionUtils.isNotEmpty(assistantEngineer)) {
                List<Long> assistantEngineerIdList = assistantEngineer.stream().map(SysUserBriefResult::getId).distinct().collect(Collectors.toList());
                assistantEngineerCount = (int) userIdList.stream().filter(assistantEngineerIdList::contains).count();
            }
            result.setAssistantEngineerCount(assistantEngineerCount);
        }
        return result;
    }

    @Override
    public List<UserArchivesImportDto> findExportData(String city, Long supplierId, String archivesName, RoleTypeEnum roleType, Boolean authenticationStatus, Long archivesTimeStart, Long archivesTimeEnd, Integer remainValidDay) {
        if (city != null && city.length() > 0) {
            city = SystemConstant.translateSpecificSign(city);
        }
        if (archivesName != null && archivesName.length() > 0) {
            archivesName = SystemConstant.translateSpecificSign(archivesName);
        }
        Long remainValidTime = null;
        if (remainValidDay != null && remainValidDay > 0) {
            remainValidTime = SystemConstant.processMiniutePlus(Duration.ofDays(remainValidDay));
        }
        List<UserArchivesImportDto> userArchivesImportDtoList = this.baseMapper.findExportData(city, supplierId, archivesName, roleType, authenticationStatus,
                archivesTimeStart, archivesTimeEnd, remainValidTime, System.currentTimeMillis());

        List<Long> effectEngineerIdList = sysUserService.findUserListByRoleType(RoleTypeEnum.EFFECT_ENGINEER)
                .stream()
                .map(SysUserBriefResult::getId)
                .distinct()
                .collect(Collectors.toList());
        List<Long> regionCoordinatorIdList = sysUserService.findUserListByRoleType(RoleTypeEnum.REGION_COORDINATOR)
                .stream()
                .map(SysUserBriefResult::getId)
                .distinct()
                .collect(Collectors.toList());
        List<Long> assistantEngineerIdList = sysUserService.findUserListByRoleType(RoleTypeEnum.ASSISTANT_ENGINEER)
                .stream()
                .map(SysUserBriefResult::getId)
                .distinct()
                .collect(Collectors.toList());

        for (UserArchivesImportDto userArchivesImportDto : userArchivesImportDtoList) {
            Long userId = userArchivesImportDto.getUserId();
            List<RoleTypeEnum> hasRoles = new ArrayList<>();
            if (effectEngineerIdList.contains(userId)) {
                hasRoles.add(RoleTypeEnum.EFFECT_ENGINEER);
            }
            if (regionCoordinatorIdList.contains(userId)) {
                hasRoles.add(RoleTypeEnum.REGION_COORDINATOR);
            }
            if (assistantEngineerIdList.contains(userId)) {
                hasRoles.add(RoleTypeEnum.ASSISTANT_ENGINEER);
            }
            String roleNames = hasRoles.stream().map(RoleTypeEnum::getDesc).collect(Collectors.joining(","));
            userArchivesImportDto.setRoleNames(roleNames);
            GenderEnum gender = userArchivesImportDto.getGenderEnum();
            if (Objects.nonNull(gender)) {
                userArchivesImportDto.setGender(gender.getTitle());
            }
            EducationEnum education = userArchivesImportDto.getEducationEnum();
            if (Objects.nonNull(education)) {
                userArchivesImportDto.setEducation(education.getTitle());
            }

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
            Long archivesTime = userArchivesImportDto.getArchivesTime();
            Long authenticationValidTime = userArchivesImportDto.getAuthenticationValidTime();
            if (Objects.nonNull(archivesTime)) {
                String archivesTimeStr = sdf.format(new Date(archivesTime));
                userArchivesImportDto.setArchivesTimeStr(archivesTimeStr);
            }
            if (Objects.nonNull(authenticationValidTime)) {
                String authenticationValidTimeStr = sdf.format(new Date(authenticationValidTime));
                userArchivesImportDto.setAuthenticationValidTimeStr(authenticationValidTimeStr);
            }
        }
        return userArchivesImportDtoList;
    }

    @Transactional
    @Override
    public void cancelUserArchives(List<Long> userArchivesIdList) {
        long currentTime = System.currentTimeMillis();
        if (CollectionUtils.isNotEmpty(userArchivesIdList)) {
            for (Long archivesId : userArchivesIdList) {
                UserArchivesResult userArchivesResult = this.findUserArchivesByArchivesIdORUserId(archivesId, null);
                Long validTime = userArchivesResult.getAuthenticationValidTime();
                // 作废校验1 - 认证状态失效
                if (validTime != null && currentTime < validTime) {
                    throw ExceptionResultEnum.ERROR.exception(String.format("[%s]的认证状态为有效,不能作废", userArchivesResult.getName()));
                }
                // 作废校验2 - 没有进行中的SOP
                List<SopInfoResult> sopInfoResultList = tbSopInfoService.findFlowByServiceId(null, userArchivesResult.getUserId());
                if (CollectionUtils.isNotEmpty(sopInfoResultList)) {
                    throw ExceptionResultEnum.ERROR.exception("该用户存在正在进行的SOP不能作废");
                }

                // 作废校验3 - 为空闲状态
                UserArchivesStatusEnum status = userArchivesResult.getStatus();
                Long userId = userArchivesResult.getUserId();
                boolean isCoordinator = sysUserRoleService.userContainsRoles(userId, RoleTypeEnum.REGION_COORDINATOR);
                if (!isCoordinator) {
                    // 不是区域协调人直接判断非空闲即可作废
                    if (UserArchivesStatusEnum.OCCUPIED.equals(status)) {
                        throw ExceptionResultEnum.ERROR.exception(String.format("[%s]为非空闲，不能作废", userArchivesResult.getName()));
                    }
                } else {
                    // 包含区域协调人判断该区域协调人涉及的所有派单均完成
                    if (tbCrmService.list(new QueryWrapper<TBCrm>().lambda()
                            .eq(TBCrm::getRegionCoordinatorId, userId)
                            .ne(TBCrm::getStatus, CrmStatusEnum.FINISH)).size() > 0) {
                        throw ExceptionResultEnum.ERROR.exception(String.format("区域协调人[%s]有未完成的派单，不能作废", userArchivesResult.getName()));
                    }
                }
            }
            UpdateWrapper<TBUserArchives> updateWrapper = new UpdateWrapper<>();
            updateWrapper.lambda().in(TBUserArchives::getId, userArchivesIdList).set(TBUserArchives::getEnable, false);
            this.update(updateWrapper);
        }
    }

    @Override
    public TBUserArchives findByUserId(Long userId) {
        SysUser sysUser = sysUserService.getById(userId);
        if (Objects.isNull(sysUser)) {
            throw ExceptionResultEnum.ERROR.exception("用户不存在");
        }
        String mobileNumber = sysUser.getMobileNumber();

        List<TBUserArchives> tbUserArchivesList = this.list(new QueryWrapper<TBUserArchives>().lambda()
                .eq(TBUserArchives::getMobileNumber, mobileNumber)
                .eq(TBUserArchives::getEnable, true));
        if (CollectionUtils.isEmpty(tbUserArchivesList)) {
            throw ExceptionResultEnum.ERROR.exception("不存在档案");
        }
        if (tbUserArchivesList.size() > 1) {
            throw ExceptionResultEnum.ERROR.exception("存在多个相同手机号的档案异常[" + mobileNumber + "]");
        }
        return tbUserArchivesList.get(0);
    }

    @Override
    public UserArchivesResult findUserArchivesByArchivesIdORUserId(Long archivesId, Long userId) {
        UserArchivesResult result = null;
        List<UserArchivesResult> userArchivesResultList = this.baseMapper.findUserArchivesById(archivesId, userId);
        if (CollectionUtils.isNotEmpty(userArchivesResultList)) {
            if (userArchivesResultList.size() > 1) {
                throw ExceptionResultEnum.ERROR.exception("档案数据异常");
            }
            result = userArchivesResultList.get(0);
        }
        return result;
    }

    @Override
    public List<ArchivesSourceResult> findFreeEngineerSourceByType(RoleTypeEnum roleType, String crmNo) {
        List<ArchivesSourceResult> result = new ArrayList<>();
        if (!RoleTypeEnum.EFFECT_ENGINEER.equals(roleType) && !RoleTypeEnum.ASSISTANT_ENGINEER.equals(roleType)) {
            throw ExceptionResultEnum.ERROR.exception("该方法只支持查询实施工程师和助理工程师");
        }

        List<ArchivesSourceResult> list = new ArrayList<>(this.baseMapper.findArchivesSourceByType(roleType));
        if (CollectionUtils.isNotEmpty(list)) {
            Long currentTime = System.currentTimeMillis();
            list = list.stream()
                    .filter(e -> e.getAuthenticationValidTime() != null && e.getAuthenticationValidTime() >= currentTime && UserArchivesStatusEnum.FREE.equals(e.getArchivesStatus()))
                    .peek(e -> e.setRemainCount(1))
                    .collect(Collectors.toList());

            List<Long> idList = list.stream().map(ArchivesSourceResult::getUserId).collect(Collectors.toList());

            if (crmNo != null && crmNo.length() > 0) {
                List<ArchivesSourceResult> choose = this.baseMapper.findArchivesUsed(roleType, crmNo);
                choose = choose.stream().filter(e -> !idList.contains(e.getUserId())).collect(Collectors.toList());
                list.addAll(choose);
            }
            result = list;
        }
        return result;
    }

    @Override
    public List<ArchivesSourceResult> findFreeCoordinatorByServiceId(Long serviceUnitId, String crmNo, boolean verifyRate) {
        List<ArchivesSourceResult> result = new ArrayList<>();
        TBService tbService = tbServiceService.getById(serviceUnitId);
        if (Objects.isNull(tbService)) {
            throw ExceptionResultEnum.ERROR.exception("服务单元不存在");
        }
        int rate = tbService.getRegionProjectCount() / tbService.getRegionPeopleCount();
        List<TBCrm> tbCrmList = tbCrmService.list(new QueryWrapper<TBCrm>().lambda().eq(TBCrm::getServiceId, serviceUnitId));

        Long currentTime = System.currentTimeMillis();
        List<ArchivesSourceResult> list = this.baseMapper.findArchivesSourceByType(RoleTypeEnum.REGION_COORDINATOR);
        if (CollectionUtils.isNotEmpty(list)) {
            list = list.stream()
                    .filter(e -> e.getAuthenticationValidTime() != null && e.getAuthenticationValidTime() >= currentTime)
                    .peek(e -> {
                        Long userId = e.getUserId();
                        int count = Math.toIntExact(tbCrmList.stream().filter(c -> userId.equals(c.getRegionCoordinatorId())).count());
                        e.setRemainCount(rate - count);
                    })
                    .collect(Collectors.toList());

            if (verifyRate) {
                // 只有自动调配才启用服务单元区域配比
                list = list.stream().filter(e -> e.getRemainCount() > 0).collect(Collectors.toList());
            }

            // 调配选人列表查询的特殊处理
            if (crmNo != null && crmNo.length() > 0) {
                List<TBCrm> temp = tbCrmList.stream().filter(e -> e.getCrmNo().equals(crmNo)).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(temp)) {
                    throw ExceptionResultEnum.ERROR.exception(String.format("派单号[%s]不存在在服务单元[%s]下", crmNo, tbService.getName()));
                }
                TBCrm chooseCrm = temp.get(0);
                Long coordinatorId = chooseCrm.getRegionCoordinatorId();
                if (coordinatorId != null && !list.stream().map(ArchivesSourceResult::getUserId).collect(Collectors.toList()).contains(coordinatorId)) {
                    TBUserArchives chooseArchives = tbUserArchivesService.findByUserId(coordinatorId);
                    ArchivesSourceResult choose = new ArchivesSourceResult();
                    choose.setArchivesId(chooseArchives.getId());
                    choose.setUserId(coordinatorId);
                    choose.setName(chooseArchives.getName());
                    list.add(choose);
                }
            }
            result = list;
        }
        return result;
    }
}