package com.yeejoin.amos.boot.module.tcm.biz.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Sets;
import com.yeejoin.amos.boot.biz.common.bo.CompanyBo;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.entity.BaseEntity;
import com.yeejoin.amos.boot.biz.common.entity.DataDictionary;
import com.yeejoin.amos.boot.biz.common.excel.ExcelUtil;
import com.yeejoin.amos.boot.biz.common.service.impl.DataDictionaryServiceImpl;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.biz.common.utils.SnowflakeIdUtil;
import com.yeejoin.amos.boot.module.common.api.dto.UserPermissionDto;
import com.yeejoin.amos.boot.module.tcm.api.dto.*;
import com.yeejoin.amos.boot.module.tcm.api.entity.*;
import com.yeejoin.amos.boot.module.tcm.api.enums.EquipmentClassifityEnum;
import com.yeejoin.amos.boot.module.tcm.api.enums.PersonManageRoleEnum;
import com.yeejoin.amos.boot.module.tcm.api.enums.TwoStipulateGroupEnum;
import com.yeejoin.amos.boot.module.tcm.api.enums.UnitTypeEnum;
import com.yeejoin.amos.boot.module.tcm.api.mapper.TzsBaseIndividualityMapper;
import com.yeejoin.amos.boot.module.tcm.api.mapper.TzsUserEquipMapper;
import com.yeejoin.amos.boot.module.tcm.api.mapper.TzsUserInfoMapper;
import com.yeejoin.amos.boot.module.tcm.api.service.ITzsUserInfoService;
import com.yeejoin.amos.boot.module.tcm.api.vo.TzsUserInfoVo;
import com.yeejoin.amos.boot.module.tcm.api.vo.UserInfoVo;
import com.yeejoin.amos.boot.module.tcm.flc.biz.service.impl.RegUnitInfoServiceImpl;
import com.yeejoin.amos.component.feign.config.InnerInvokException;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.component.feign.utils.FeignUtil;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.privilege.model.CompanyModel;
import com.yeejoin.amos.feign.privilege.model.GroupModel;
import com.yeejoin.amos.feign.privilege.model.RoleModel;
import com.yeejoin.amos.feign.privilege.util.DesUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.ehcache.impl.internal.concurrent.ConcurrentHashMap;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;
import org.typroject.tyboot.core.restful.utils.ResponseHelper;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class TzsUserInfoServiceImpl extends BaseService<TzsUserInfoDto, TzsUserInfo, TzsUserInfoMapper> implements ITzsUserInfoService {

    // 企业人员角色
    private final String USER_ROLE = "QYRYJS";
    // 企业人员用户组
    private final String ROLE_GROUP = "QYRYYHZ";
    // 两个规定用户组-对应企业人员的人员类型前缀
    private final String QYRYGW = "QYRYGW";
    // 两个规定用户组-对应企业人员的人员类型前缀
    private final String QYRYGW_NAME = "企业人员类型";
    // 平台用户锁定状态
    private final String UNLOCK = "UNLOCK";
    private final String LOCK = "LOCK";
    @Autowired
    DataDictionaryServiceImpl iDataDictionaryService;
    @Autowired
    TzBaseEnterpriseInfoServiceImpl baseEnterpriseInfoService;
    @Autowired
    TzsBaseIndividualityServiceImpl individualityService;
    @Autowired
    TzsBaseIndividualityMapper individualityMapper;
    @Autowired
    private TzsUserInfoMapper tzsUserInfoMapper;
    @Autowired
    private TzsUserEquipMapper tzsUserEquipMapper;
    @Autowired
    private TzsUserEquipServiceImpl tzsUserEquipService;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private TzsUserQualificationsServiceImpl tzsUserQualificationsService;
    @Autowired
    private TzsUserPermissionServiceImpl tzsUserPermissionServiceImpl;

    @Autowired
    private RegUnitInfoServiceImpl regUnitInfoService;

    private static Map<String, String> statusColorMap = new HashMap<>();

    static {
        statusColorMap.put("无资质要求", "#868686");
        statusColorMap.put("资质超期", "#FF0000");
        statusColorMap.put("资质临期", "#FC9700");
        statusColorMap.put("正常", "#18B100");
    }


    private static Map<String, List<String>> menuMap = new HashMap<>();

    static {
        // 业务办理人员管理
        menuMap.put("ywblry", Collections.singletonList("6616"));
        // 主要负责人管理
        menuMap.put("zyfzr", Collections.singletonList("6548"));
        // 作业人员管理
        menuMap.put("zyry", Collections.singletonList("6552"));
        // 检测人员管理
        menuMap.put("jcry", Collections.singletonList("66152"));
        // 安全总监管理
        menuMap.put("aqzj", Collections.singletonList("6547"));
        // 质量保证体系人员管理
        menuMap.put("zlbztxry", Collections.singletonList("6619"));
        // 质量安全员管理
        menuMap.put("zlaqy", Collections.singletonList("6551"));
        // 质量安全总监管理
        menuMap.put("zlaqzj", Collections.singletonList("6550"));
        // 安全员管理
        menuMap.put("aqy", Collections.singletonList("6549"));
        // 检验人员管理
        menuMap.put("jyry", Collections.singletonList("66151"));
        // 其他人员管理
        menuMap.put("qtry", Collections.singletonList("6546"));
    }

    @Autowired
    private Validator validator;


    @Autowired
    SnowflakeIdUtil sequence;

    @Override
    public Page<TzsUserInfoDto> page(TzsUserInfoDto dto, Page<TzsUserInfoDto> page) {
        dto.setMenuTypeUnderPost(menuMap.get(dto.getMenuType()));
        // 其他人员管理 包含 普通员工、安全管理员、安改维负责人
        // 上面menuMap中的其他人员只是在新增人员时为页面赋默认值
        if ("qtry".equals(dto.getMenuType())) {
            dto.setMenuTypeUnderPost(Arrays.asList("6546", "6617", "6553"));
        }
        Page<TzsUserInfoDto> tzsUserInfoDtoPage = tzsUserInfoMapper.selectPageMessage(page, dto);
        tzsUserInfoDtoPage.getRecords().forEach(item -> {
            if (!ObjectUtils.isEmpty(item.getProfile())) {
                List<CommonFile> commonFiles = JSON.parseArray(item.getProfile(), CommonFile.class);
                if (!ObjectUtils.isEmpty(commonFiles)) {
                    item.setProfile(commonFiles.get(0).getUrl());
                }
            }
            if (!ObjectUtils.isEmpty(item.getBirthday())) {
                int age = getAge(item.getBirthday());
                item.setAge(Math.max(age, 0));
            }
        });
        return tzsUserInfoDtoPage;
    }

    // 判断字符串是否为合法的 JSON 格式
    public boolean isJSONValid(String test) {
        try {
            JSON.parseArray(test);
            return true;
        } catch (Exception ex) {
            return false;
        }
    }

    public String setPostName(String postKey) {
        JSONArray dictIds = JSON.parseArray(postKey);
        if (dictIds == null || dictIds.isEmpty()) {
            return "";
        }
        LambdaQueryWrapper<DataDictionary> lambda = new QueryWrapper<DataDictionary>().lambda();
        lambda.in(DataDictionary::getSequenceNbr, dictIds);
        List<DataDictionary> dataDictionaries = iDataDictionaryService.getByTypeAndDesc(QYRYGW, QYRYGW_NAME);
        List<DataDictionary> postDataList = dataDictionaries.stream().filter(d -> dictIds.stream().anyMatch(id -> id.toString().equals(d.getSequenceNbr().toString()))).collect(Collectors.toList());
        return postDataList.stream().map(DataDictionary::getName).collect(Collectors.joining(","));
    }


    private int getAge(Date birth) {
        Calendar cal = Calendar.getInstance();
        int thisYear = cal.get(Calendar.YEAR);
        int thisMonth = cal.get(Calendar.MONTH);
        int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);

        cal.setTime(birth);
        int birthYear = cal.get(Calendar.YEAR);
        int birthMonth = cal.get(Calendar.MONTH);
        int birthdayOfMonth = cal.get(Calendar.DAY_OF_MONTH);

        int age = thisYear - birthYear;

        // 未足月
        if (thisMonth <= birthMonth) {
            // 当月
            if (thisMonth == birthMonth) {
                // 未足日
                if (dayOfMonth < birthdayOfMonth) {
                    age--;
                }
            } else {
                age--;
            }
        }
        return age;
    }

    @Override
    public void addQualificationsMessage(String userId, List<TzsUserQualifications> list) {
        list.forEach(item -> {
            item.setUserInfoId(userId);
        });
        tzsUserQualificationsService.saveOrUpdateBatch(list);
    }

    @Override
    public void updateQualificationsMessage(String userId, List<TzsUserQualifications> list) {
        LambdaQueryWrapper<TzsUserQualifications> lambda = new QueryWrapper<TzsUserQualifications>().lambda();
        lambda.eq(TzsUserQualifications::getUserInfoId, userId);
        tzsUserQualificationsService.getBaseMapper().delete(lambda);
        addQualificationsMessage(userId, list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBatch(Object[] ids1) {
        LambdaQueryWrapper<TzsUserInfo> lambda = new QueryWrapper<TzsUserInfo>().lambda();
        lambda.in(TzsUserInfo::getSequenceNbr, ids1);
        TzsUserInfo tzsUserInfo = new TzsUserInfo();
        tzsUserInfo.setIsDelete(true);
        tzsUserInfoMapper.update(tzsUserInfo, lambda);
        List<TzsUserInfo> tzsUserInfos = tzsUserInfoMapper.selectList(lambda);
        for (TzsUserInfo userInfo : tzsUserInfos) {
            tzsUserEquipMapper.delete(new QueryWrapper<TzsUserEquip>().eq("user_seq", userInfo.getSequenceNbr()));
            if (!ObjectUtils.isEmpty(userInfo.getAmosUserId())) {
                Privilege.agencyUserClient.multDeleteUser(userInfo.getAmosUserId());
                deleteGroupAndPersonRelation(userInfo.getPostName(), userInfo.getAmosUserId());
            }
        }
    }


    @Override
    public void deleteGroupAndPersonRelation(String postName, String amosUserId) {
        String[] split = postName.split(",");
        for (String s : split) {
            if (!ObjectUtils.isEmpty(TwoStipulateGroupEnum.getId.get(s))) {
                Privilege.groupUserClient.deleteGroupUser(TwoStipulateGroupEnum.getId.get(s), amosUserId);
            }
        }
    }

    @Override
    public Map<String, Object> getDetail(Long id) {
        Map<String, Object> maps = new HashMap<>();
        TzsUserInfo tzsUserInfo = tzsUserInfoMapper.selectById(id);
        TzsUserInfoVo tzsUserInfoVo = new TzsUserInfoVo();
        BeanUtils.copyProperties(tzsUserInfo, tzsUserInfoVo, "identification", "profile", "post", "permissionItem", "appointDoc");
        if (!ObjectUtils.isEmpty(tzsUserInfo.getPost())) {
            tzsUserInfoVo.setPost(JSON.parseArray(tzsUserInfo.getPost()));
        }
        if (!ObjectUtils.isEmpty(tzsUserInfo.getNewPost())) {
            tzsUserInfoVo.setNewPost(JSON.parseArray(tzsUserInfo.getNewPost()));
        }
        if (!ObjectUtils.isEmpty(tzsUserInfo.getEquipType())) {
            JSONArray equipTypeJSONArray = JSON.parseArray(tzsUserInfo.getEquipType());
            tzsUserInfoVo.setEquipType(equipTypeJSONArray);
            if(CollUtil.isNotEmpty(equipTypeJSONArray)){
                StringBuilder equipTypeName = new StringBuilder();
                for (Object o : equipTypeJSONArray) {
                    String s = EquipmentClassifityEnum.getName.get(o);
                    if(StringUtils.isEmpty(s)){
                        s = String.valueOf(o);
                    }
                    equipTypeName.append(s);
                    equipTypeName.append(",");
                }
                tzsUserInfoVo.setEquipTypeName(equipTypeName.substring(0,equipTypeName.length()-1));
            }
        }
        tzsUserInfoVo.setIdentification(ObjectUtils.isEmpty(tzsUserInfo.getIdentification()) ? null : JSON.parseArray(tzsUserInfo.getIdentification()));
        tzsUserInfoVo.setProfile(ObjectUtils.isEmpty(tzsUserInfo.getProfile()) ? null : JSON.parseArray(tzsUserInfo.getProfile()));
        tzsUserInfoVo.setAppointDoc(ObjectUtils.isEmpty(tzsUserInfo.getAppointDoc()) ? null : JSON.parseArray(tzsUserInfo.getAppointDoc()));
        tzsUserInfoVo.setOtherAccessories(ObjectUtils.isEmpty(tzsUserInfo.getOtherAccessories()) ? null : JSON.parseArray(tzsUserInfo.getOtherAccessories()));
        String companyType = getUnitType();
        tzsUserInfoVo.setCompanyType(companyType.contains("个人主体") ? "individual" : "no-individual");
        Map<String, Object> userInfoMap = BeanUtil.beanToMap(tzsUserInfoVo);
//        userInfoMap.putAll(this.getPermissionDataJson(tzsUserInfo.getPermissionData()));
        // 填充资质信息
        Map<? extends String, ?> permissions = tzsUserPermissionServiceImpl.queryForSubFormByUserSeq(String.valueOf(tzsUserInfo.getSequenceNbr()));
        userInfoMap.putAll(permissions);
        maps.put("userInfo", userInfoMap);
        return maps;
    }

    private Map<? extends String, ?> getPermissionDataJson(String permissionData) {
        if (permissionData != null) {
            return JSON.parseObject(permissionData);
        }
        return new JSONObject();
    }

    @Override
    public boolean BindAccount(Map<String, Object> map) {
        String loginName = map.get("userName").toString();
        String pwd = map.get("password").toString();
        String sequenceNbr = map.get("sequenceNbr").toString();
        String roles = map.get("role").toString();
        String status = map.get("status").toString();
        String roleGroupCode = map.get("roleGroup").toString();
        TzsUserInfo tzsUserInfo = tzsUserInfoMapper.selectById(sequenceNbr);

        FeignClientResult<AgencyUserModel> userResult = null;
        try {
            AgencyUserModel agencyUserModel = new AgencyUserModel();
            agencyUserModel.setUserName(loginName);
            agencyUserModel.setRealName(tzsUserInfo.getName());
            agencyUserModel.setLockStatus(status);
            agencyUserModel.setPassword(pwd);
            agencyUserModel.setRePassword(pwd);
            agencyUserModel.setAgencyCode("tzs");
            agencyUserModel.setMobile(tzsUserInfo.getPhone());
            agencyUserModel.setEmail(tzsUserInfo.getEmail());

            ReginParams reginParams = JSON.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
            if (ObjectUtils.isEmpty(reginParams)) {
                return false;
            }
            Long companySeq = reginParams.getCompany().getSequenceNbr();
            List<String> appCodesSet = reginParams.getUserModel().getAppCodes();
            List<RoleModel> allRoleList = new ArrayList<>();
            List<Long> roleIds = new ArrayList<>();
            DataDictionary unitType = iDataDictionaryService
                    .getOne(new LambdaQueryWrapper<DataDictionary>().eq(DataDictionary::getCode, roles).eq(DataDictionary::getType, USER_ROLE));
            String role = unitType.getExtend() != null ? unitType.getExtend() : "";
            for (String s : role.split(",")) {
                RoleModel roleModel = Privilege.roleClient.seleteOne(Long.valueOf(s)).getResult();
                allRoleList.add(roleModel);
            }
            allRoleList.forEach(r -> {
                if (!roleIds.contains(r.getSequenceNbr())) {
                    roleIds.add(r.getSequenceNbr());
                }
            });

            // 添加人员管理角色

            String post = tzsUserInfo.getPost();
            if (post.contains(PersonManageRoleEnum.code.getId().toString())) {
                String companyType = tzsUserInfoMapper.selectCompanyTypeById(companySeq);
                setBizOperateUserRole(companyType, roleIds);
            }

            Map<Long, List<Long>> roleSeqMap = new HashMap<>();
            Map<Long, List<RoleModel>> orgRoles = new HashMap<>();
            roleSeqMap.put(companySeq, roleIds);
            orgRoles.put(companySeq, allRoleList);
            agencyUserModel.setAppCodes(new ArrayList<>(appCodesSet));
            agencyUserModel.setOrgRoles(orgRoles);
            agencyUserModel.setOrgRoleSeqs(roleSeqMap);
            userResult = Privilege.agencyUserClient.create(agencyUserModel);
            if (userResult.getStatus() == 200) {

                tzsUserInfo.setAmosUserId(userResult.getResult().getUserId());
                tzsUserInfo.setAmosUserName(userResult.getResult().getUserName());
                tzsUserInfo.setLockStatus(status);
                // 绑定企业整改用户组
                List<String> userIds = new ArrayList<>();
                userIds.add(userResult.getResult().getUserId());
                DataDictionary roleGroup = iDataDictionaryService
                        .getOne(new LambdaQueryWrapper<DataDictionary>().eq(DataDictionary::getCode, roleGroupCode).eq(DataDictionary::getType, ROLE_GROUP));
                if (!ObjectUtils.isEmpty(roleGroup) && roleGroup.getExtend() != null) {
                    Privilege.groupUserClient.create(Long.valueOf(roleGroup.getExtend()), userIds);
                }
                // 绑定两个规定用户组
                post = post.replace("[", "").replace("]", "").replace("\"", "");
                for (String code : post.split(",")) {
                    bind2PermissionGroup(userIds, code);
                }
                tzsUserInfoMapper.updateById(tzsUserInfo);
            }
            return true;
        } catch (Exception e) {
            if (userResult != null && userResult.getResult() != null
                    && StringUtils.isNotEmpty(userResult.getResult().getUserId())) {
                Privilege.agencyUserClient.multDeleteUser(userResult.getResult().getUserId());
            }
            log.error(e.getMessage(), e);
            throw new BadRequest(e.getMessage());
        }

    }

    @Override
    public String startOrStopAccount(Map<String, Object> map) {
        Long sequenceNbr = Long.valueOf(map.get("sequenceNbr").toString());
        String amosUserId = map.get("amosUserId").toString();
        String lockStatus = null;
        FeignClientResult<List<String>> userResult = null;
        if (UNLOCK.equals(map.get("lockStatus"))) {
            userResult = Privilege.agencyUserClient.lockUsers(amosUserId);
            lockStatus = 200 == userResult.getStatus() ? LOCK : UNLOCK;
        } else {
            userResult = Privilege.agencyUserClient.unlockUsers(amosUserId);
            lockStatus = 200 == userResult.getStatus() ? UNLOCK : LOCK;
        }
        if (!ObjectUtils.isEmpty(lockStatus)) {
            TzsUserInfo tzsUserInfo = new TzsUserInfo();
            tzsUserInfo.setSequenceNbr(sequenceNbr);
            tzsUserInfo.setLockStatus(lockStatus);
            tzsUserInfoMapper.updateById(tzsUserInfo);
        }
        return userResult.getResult().get(0);
    }

    @Override
    public List<Map<String, Object>> getEquipmentType(String creditCode) {
        ArrayList<Map<String, Object>> maps = new ArrayList<>();
        LambdaQueryWrapper<TzBaseEnterpriseInfo> lambda = new QueryWrapper<TzBaseEnterpriseInfo>().lambda();
        lambda.eq(TzBaseEnterpriseInfo::getUseCode, creditCode);
        List<TzBaseEnterpriseInfo> tzBaseEnterpriseInfos = baseEnterpriseInfoService.getBaseMapper().selectList(lambda);
        if (!ObjectUtils.isEmpty(tzBaseEnterpriseInfos) && !ObjectUtils.isEmpty(tzBaseEnterpriseInfos.get(0).getEquipCategory())) {
            String equipCategory = tzBaseEnterpriseInfos.get(0).getEquipCategory();
            JSONArray objects = JSON.parseArray(equipCategory);
            for (Object object : objects) {
                HashMap<String, Object> map = new HashMap<>();
                map.put("code", object);
                map.put("name", EquipmentClassifityEnum.getEnumByCode(object.toString()).getName());
                maps.add(map);
            }
            return maps;
        }
        return new ArrayList<>();
    }

    @Override
    public Map<String, Integer> getArrangementStatistic(String companyCode) {
        return tzsUserInfoMapper.getArrangementStatistic(companyCode);
    }

    public String getUnitType() {
        List<CompanyModel> companyModels = FeignUtil.remoteCall(() -> Privilege.companyClient.queryListByChild(RequestContext.getExeUserId()));
        if (companyModels.isEmpty()) {
            return "";
        }
        return companyModels.get(0).getCompanyType();
    }

    @Override
    public Map<String, Object> getCompanyType() {
        Map<String, Object> result = new HashMap<>();
        result.put("companyType", null);
        List<CompanyModel> companyModels = FeignUtil.remoteCall(() -> Privilege.companyClient.queryListByChild(RequestContext.getExeUserId()));
        if (companyModels.isEmpty()) {
            return result;
        }
        result.put("creditCode", companyModels.get(0).getCompanyCode());
        boolean productCompany = false;
        boolean useCompany = false;
        boolean installCompany = false;
        boolean inspectionCompany = false;
        for (CompanyModel companyModel : companyModels) {
            String companyType = companyModel.getCompanyType();
            if (companyType.contains("使用单位") || companyType.contains("个人主体")) {
                useCompany = true;
            }
            if (companyType.contains("充装单位") || companyType.contains("安装改造维修单位") || companyType.contains("制造单位") || companyType.contains("设计单位")) {
                productCompany = true;
            }
            if (companyType.contains("安装改造维修单位")) {
                installCompany = true;
            }
            if (companyType.contains("检验检测机构")) {
                inspectionCompany = true;
            }
        }
        StringBuilder companyType = new StringBuilder();
        if (useCompany) {
            companyType.append("use-");
        }
        if (productCompany) {
            companyType.append("pro-");
        }

        if (installCompany) {
            companyType.append("install-");
        }
        if (inspectionCompany) {
            companyType.append("inspection");
        }
        result.put("companyType", companyType);
        return result;
    }

    @Override
    public Map<String, Object> getCompanyTypeForRedis(ReginParams selectedOrgInfo) {
        Map<String, Object> result = new HashMap<>();
        result.put("companyType", null);
        CompanyBo company = selectedOrgInfo.getCompany();
        if (ObjectUtils.isEmpty(company)) {
            return result;
        }
        result.put("creditCode", company.getCompanyCode());
        boolean productCompany = false;
        boolean useCompany = false;
        boolean installCompany = false;
        boolean inspectionCompany = false;
        String companyType = company.getCompanyType();
        if (companyType.contains("使用单位") || companyType.contains("个人主体")) {
            useCompany = true;
        }
        if (companyType.contains("充装单位") || companyType.contains("安装改造维修单位") || companyType.contains("制造单位") || companyType.contains("设计单位")) {
            productCompany = true;
        }
        if (companyType.contains("安装改造维修单位")) {
            installCompany = true;
        }
        if (companyType.contains("检验检测机构")) {
            inspectionCompany = true;
        }
        StringBuilder companyTypeStr = new StringBuilder();
        if (useCompany) {
            companyTypeStr.append("use-");
        }
        if (productCompany) {
            companyTypeStr.append("pro-");
        }

        if (installCompany) {
            companyTypeStr.append("install-");
        }
        if (inspectionCompany) {
            companyTypeStr.append("inspection");
        }
        result.put("companyType", companyTypeStr);
        return result;
    }

    @Override
    public Page<TzsEquipListDto> getEquipList(String type, String userSeq, TzsEquipListDto dto, Page<TzsEquipListDto> page) {
        List<CompanyModel> companyModels = FeignUtil.remoteCall(() -> Privilege.companyClient.queryListByChild(RequestContext.getExeUserId()));
        if (companyModels.isEmpty()) {
            throw new BadRequest("未指定人员归属单位信息");
        }
        String companyCode = companyModels.get(0).getCompanyCode();
        Page<TzsEquipListDto> tzsUserInfoDtoPage;
        tzsUserInfoDtoPage = tzsUserInfoMapper.getAllEquipList(page, type, companyCode, userSeq, dto);
        return tzsUserInfoDtoPage;
    }

    @Override
    public Boolean equipBind(String type, String userSeq, String creditCode, Map<String, Object> map) {
        Object recordList = map.get("ids");
        List<String> ids = (List<String>) recordList;
        List<TzsUserEquip> tzsUserEquipList = new ArrayList<>();
        boolean flag = false;
        if ("bind".equals(type)) {
            for (String equipId : ids) {
                TzsUserEquip tzsUserEquip = new TzsUserEquip();
                tzsUserEquip.setEquipId(equipId);
                tzsUserEquip.setUserSeq(userSeq);
                tzsUserEquip.setCreditCode(creditCode);
                tzsUserEquipList.add(tzsUserEquip);
            }
            flag = tzsUserEquipService.saveBatch(tzsUserEquipList);
        } else if ("untie".equals(type)) {
            int num = tzsUserEquipMapper.delete(new QueryWrapper<TzsUserEquip>().eq("user_seq", userSeq).in("equip_id", ids));
            flag = num > 0 ? true : flag;
        }
        return flag;
    }

    @Override
    public List<TzsUserInfo> getSafetyList(String companyCode) {
        return tzsUserInfoMapper.selectList(new QueryWrapper<TzsUserInfo>().eq("unit_code", companyCode).eq("is_delete", false).like("post", 6549));
    }

    @Override
    public List<Map<String, Object>> getGroupList() {
        FeignClientResult<Collection<GroupModel>> collectionFeignClientResult = Privilege.groupClient.selectForList(1712370734598221825L, null);
        Collection<GroupModel> GroupModelResult = collectionFeignClientResult.getResult();
        List<GroupModel> collect = GroupModelResult.stream().filter(e -> "twoStipulate".equals(e.getGroupDesc())).collect(Collectors.toList());
        List<Map<String, Object>> result = new ArrayList<>();
        for (GroupModel groupModel : collect) {
            Map<String, Object> map = new HashMap<>();
            map.put("groupName", groupModel.getGroupName());
            map.put("sequenceNbr", groupModel.getSequenceNbr());
            result.add(map);
        }
        return result;
    }

    @Override
    public Map<String, Object> getPersonType() {
        String userId = RequestContext.getExeUserId();
        if (ObjectUtils.isEmpty(userId)) {
            return null;
        }
        String postName = tzsUserInfoMapper.selectPostNameByUserId(userId);
        Map<String, Object> result = new HashMap<>();
        result.put("postName", ObjectUtils.isEmpty(postName) ? null : postName);
        return result;
    }

    @Override
    public List<GroupAndPersonInfoDto> getGroupAndPersonInfo(Long groupId) {

        List<GroupAndPersonInfoDto> result = new ArrayList<>();
        List<GroupAndPersonInfoDto> groupAndPersonInfoDtoList = tzsUserInfoMapper.getUnitInfoByUserId(groupId);
        DataDictionary dataDictionary = iDataDictionaryService.getByExtend(groupId.toString(), QYRYGW);
        for (GroupAndPersonInfoDto groupAndPersonInfoDto : groupAndPersonInfoDtoList) {
            if (!ObjectUtils.isEmpty(groupAndPersonInfoDto)) {
                groupAndPersonInfoDto.setGroupName(ObjectUtils.isEmpty(dataDictionary) ? null : dataDictionary.getName());
                String[] UnitType = groupAndPersonInfoDto.getUnitType().split(",");
                if (UnitType.length > 0) {
                    StringBuilder unitTypeCode = new StringBuilder();
                    for (String s : UnitType) {
                        unitTypeCode.append(UnitTypeEnum.getCode.get(s)).append(",");
                    }
                    groupAndPersonInfoDto.setUnitTypeCode(unitTypeCode.substring(0, unitTypeCode.length() - 1));
                } else {
                    groupAndPersonInfoDto.setUnitTypeCode(UnitTypeEnum.getCode.get(UnitType));
                }

                if (!ObjectUtils.isEmpty(groupAndPersonInfoDto.getEquipCategory())) {
                    String EquipCategory = groupAndPersonInfoDto.getEquipCategory()
                            .replace("[", "")
                            .replace("]", "")
                            .replace("\"", "");
                    List<String> equipCategoryList = Arrays.asList(EquipCategory.split(","));
                    if (equipCategoryList.size() > 0) {
                        StringBuilder equipCategoryCode = new StringBuilder();
                        StringBuilder equipCategory = new StringBuilder();
                        for (String s : equipCategoryList) {
                            equipCategoryCode.append(s).append(",");
                            equipCategory.append(EquipmentClassifityEnum.getName.get(s)).append(",");
                        }
                        groupAndPersonInfoDto.setEquipCategory(equipCategory.substring(0, equipCategory.length() - 1));
                        groupAndPersonInfoDto.setEquipCategoryCode(equipCategoryCode.substring(0, equipCategoryCode.length() - 1));
                    } else {
                        groupAndPersonInfoDto.setEquipCategory(EquipmentClassifityEnum.getName.get(equipCategoryList.get(0)));
                        groupAndPersonInfoDto.setEquipCategoryCode(equipCategoryList.get(0));
                    }
                } else {
                    groupAndPersonInfoDto.setEquipCategory(null);
                    groupAndPersonInfoDto.setEquipCategoryCode(null);
                }
                result.add(groupAndPersonInfoDto);
            }
        }
        return result;
    }

    @Override
    public Boolean createUnitPerson() {
        List<TzsUserInfo> result = tzsUserInfoMapper.getUnitPersonInfo();
        return this.saveBatch(result);
    }


    @Override
    public void testGroup(String groupSeq) {
        List<String> userIds = tzsUserInfoMapper.selectUserIds();
        Privilege.groupUserClient.create(Long.valueOf(groupSeq), userIds);
    }


    @Override
    public List<Map<String, Object>> getUserType(String unitType, String formType) {
        // 详情可展示所有的人员类型
        List<String> type = new ArrayList<>();
        type.add("QYRYGW");
        if ("detail".equals(formType)) {
            type.addAll(Arrays.asList(
                    "QYRYGW-SYDW",
                    "QYRYGW-SCDW",
                    "QYRYGW-INSTALL",
                    "QYRYGW-INSPECTION"
            ));
        } else {
            if (unitType.contains("use")) {
                type.add("QYRYGW-SYDW");
            }
            if (unitType.contains("pro")) {
                type.add("QYRYGW-SCDW");
            }
            if (unitType.contains("install")) {
                type.add("QYRYGW-INSTALL");
                type.add("QYRYGW-INSPECTION");
            }
            if (unitType.contains("inspection")) {
                type.add("QYRYGW-INSPECTION");
                type.add("QYRYGW-SCDW");
            }
        }
        return tzsUserInfoMapper.getUserTypeList(type);
    }

    public List<LinkedHashMap> screenData(List<LinkedHashMap> result, List<LinkedHashMap> data, String id) {
        if (!ObjectUtils.isEmpty(result)) {
            return result;
        }
        List<LinkedHashMap> list = data.stream().filter(item -> item.get("sequenceNbr").toString().equals(id)).collect(Collectors.toList());
        if (!ObjectUtils.isEmpty(list)) {
            return list;
        }
        for (LinkedHashMap item : data) {
            if (!ObjectUtils.isEmpty(item.get("children"))) {
                List<LinkedHashMap> children = screenData(result, (List<LinkedHashMap>) item.get("children"), id);
                if (!ObjectUtils.isEmpty(children)) {
                    result = children;
                    break;
                }
            }
        }
        return result;
    }

    @Override
    public TzIndividualityDto getIndividualityInfo() {
        ReginParams reginParams = JSON.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        AgencyUserModel userModel = reginParams.getUserModel();
        CompanyBo companyBo = reginParams.getCompany();
        TzIndividualityDto individuality = new TzIndividualityDto();
        TzBaseEnterpriseInfoDto baseEnterpriseInfoDto = baseEnterpriseInfoService.getInfoByUseCode(companyBo.getCompanyCode());
        if (!ValidationUtil.isEmpty(baseEnterpriseInfoDto)) {
            individuality = individualityMapper.getIndividualityInfo(baseEnterpriseInfoDto.getSequenceNbr());
            individuality.setPhone(userModel.getMobile());
            individuality.setGoverningBody(baseEnterpriseInfoDto.getGoverningBody());
            individuality.setAddress(baseEnterpriseInfoDto.getAddress());
        }
        return individuality;
    }

    @Transactional
    @Override
    public TzIndividualityDto updateIndividualityInfo(TzIndividualityDto individualityDto) {
        TzsBaseIndividuality individuality = new TzsBaseIndividuality();
        TzBaseEnterpriseInfo baseEnterpriseInfo = baseEnterpriseInfoService.getById(individualityDto.getEnterpriseId());
        if (!ValidationUtil.isEmpty(baseEnterpriseInfo)) {
            BeanUtils.copyProperties(individualityDto, individuality);
            // 更新tz_base_individuality信息
            individuality.setRealName(individualityDto.getName());
            individualityService.saveOrUpdate(individuality);

            // 更新tz_base_enterprise_info信息
            baseEnterpriseInfo.setAddress(individualityDto.getAddress());
            baseEnterpriseInfo.setContactPhone(individualityDto.getPhone());
            baseEnterpriseInfo.setUseContact(individualityDto.getName());
            baseEnterpriseInfoService.updateById(baseEnterpriseInfo);
            // 更新privilege_agency_user手机号
            ReginParams reginParams = JSON.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
            AgencyUserModel userModel = reginParams.getUserModel();
            if (!userModel.getMobile().equals(individualityDto.getPhone())) {
                userModel.setMobile(individualityDto.getPhone());
                Privilege.agencyUserClient.modifyMobile(userModel, userModel.getUserId());
            }
        }
        return individualityDto;
    }

    public Page<UserPermissionDto> getUserByPermission(long current, long size, String type, UserPermissionDto filter) {
        Page<UserPermissionDto> permissionDtoPage = new Page<>(current, size);
        List<String> post = this.getPostByType(type);
        Page<UserPermissionDto> result = this.getBaseMapper().queryUserByPermissionPage(permissionDtoPage, post, filter);
        result.getRecords().forEach(d -> {

            if (StringUtils.isNotEmpty(d.getIdentificationStr())) {
                // 照片赋值
                List<CommonFile> commonFiles = JSON.parseArray(d.getIdentificationStr(), CommonFile.class);
                if (!ObjectUtils.isEmpty(commonFiles)) {
                    d.setPhotoUrl(commonFiles.get(0).getUrl());
                }
            }
            // 人员类型枚举转name
            d.setPost(this.isJSONValid(d.getPost()) ? d.getPost() : "[\"" + d.getPost() + "\"]");
            d.setPostName(this.setPostName(d.getPost()));
        });
        return result;
    }

    public List<UserPermissionDto> getUserPermissionOfCurrentLogin(UserPermissionDto filter) {
        List<UserPermissionDto> result = this.getBaseMapper().queryUserByPermissionOfOneCompany(filter);
        result.forEach(d -> {
            if (StringUtils.isNotEmpty(d.getIdentificationStr())) {
                // String转json
                d.setIdentification(JSON.parseArray(d.getIdentificationStr()));
                // 照片赋值
                List<CommonFile> commonFiles = JSON.parseArray(d.getIdentificationStr(), CommonFile.class);
                if (!ObjectUtils.isEmpty(commonFiles)) {
                    d.setPhotoUrl(commonFiles.get(0).getUrl());
                }
            }
            d.setPermissionStatusColor(statusColorMap.getOrDefault(d.getPermissionStatus(), "#868686"));
            // 人员类型枚举转name
            d.setPost(this.isJSONValid(d.getPost()) ? d.getPost() : "[\"" + d.getPost() + "\"]");
            d.setPostName(this.setPostName(d.getPost()));
        });
        return result;
    }

    private List<String> getPostByType(String type) {
        switch (type) {
            case "jy":
                return Collections.singletonList("66151");
            case "jc":
                return Collections.singletonList("66152");
            case "zyry":
                return Collections.singletonList("6552");
            case "qt":
                return Arrays.asList("6549", "6548", "6547", "6546", "6551", "6550", "6616", "6553", "6617");
            default:
                return Arrays.asList("6549", "6548", "6547", "6546", "6551", "6550", "6616", "6553", "6617", "66151", "66152", "6552");
        }
    }

    public List<UserPermissionDto> getUserPermissionByCompanySeq(Long comSeq) {
        TzBaseEnterpriseInfo enterpriseInfo = baseEnterpriseInfoService.getById(comSeq);
        return getUserPermissionOfCurrentLogin(UserPermissionDto.builder().cityCode(enterpriseInfo.getUseUnitCode()).build());
    }

    @Transactional(rollbackFor = Exception.class)
    public TzsUserInfoDto saveUserInfo(TzsUserInfoDto tzsUserInfo) {
        LambdaQueryWrapper<TzsUserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TzsUserInfo::getCertificateType, tzsUserInfo.getCertificateType());
        queryWrapper.eq(TzsUserInfo::getCertificateNum, tzsUserInfo.getCertificateNum());
        queryWrapper.eq(TzsUserInfo::getIsDelete, false);
        TzsUserInfo certificateNum = tzsUserInfoMapper.selectOne(queryWrapper);
        if (!ObjectUtils.isEmpty(certificateNum)) {
            throw new BadRequest("证件号码重复，请核对！");
        }

        LambdaQueryWrapper<TzsUserInfo> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(TzsUserInfo::getPhone, tzsUserInfo.getPhone());
        queryWrapper1.eq(TzsUserInfo::getIsDelete, false);
        TzsUserInfo phone = tzsUserInfoMapper.selectOne(queryWrapper1);
        if (!ObjectUtils.isEmpty(phone)) {
            throw new BadRequest("联系电话重复，请核对！");
        }

        ReginParams reginParams = JSON.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        if (ObjectUtils.isEmpty(reginParams)) {
            return null;
        }
        CompanyBo companyModel = reginParams.getCompany();
        if (ObjectUtils.isEmpty(companyModel)) {
            throw new BadRequest("未指定人员归属单位信息");
        }
        tzsUserInfo.setUnitName(companyModel.getCompanyName());
        tzsUserInfo.setUnitCode(companyModel.getCompanyCode());
        tzsUserInfo.setAppointDoc(tzsUserInfo.getAppointDoc());
        tzsUserInfo.setRecDate(new Date());
        // 兼容前端只传一个值，并且非json类型的情况
        JSONArray postArray = JSONArray.parseArray(this.isJSONValid(tzsUserInfo.getNewPost()) ? tzsUserInfo.getNewPost() : "[\"" + tzsUserInfo.getNewPost() + "\"]");
        tzsUserInfo.setNewPost(JSONArray.toJSONString(postArray));
        // 兼容 人员类型为【作业人员】且 【作业项目】含有【电梯修理】项目的为【维保人员】post为“6618”
        JSONArray permissionData6552 = tzsUserInfo.getPermissionData6552();
        if (!permissionData6552.isEmpty() && postArray.contains("6552")) {
            JSONObject jsonObject = permissionData6552.getJSONObject(0);
            JSONArray jobItem = jsonObject.getJSONArray("jobItem");
            if (jobItem != null && jobItem.contains("电梯修理")) {
                postArray.add("6618");
            }
        }
        tzsUserInfo.setPost(JSONArray.toJSONString(postArray));
        tzsUserInfo.setPostName(this.setPostName(tzsUserInfo.getNewPost()));
        tzsUserInfo = this.createWithModel(tzsUserInfo);
        // 保存资质
        tzsUserPermissionServiceImpl.savePermissionData(tzsUserInfo);
        return tzsUserInfo;
    }

    @Transactional(rollbackFor = Exception.class)
    public TzsUserInfoDto updateUserInfo(Long rowId, TzsUserInfoDto tzsUserInfoDto) {
        LambdaQueryWrapper<TzsUserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TzsUserInfo::getCertificateType, tzsUserInfoDto.getCertificateType());
        queryWrapper.eq(TzsUserInfo::getCertificateNum, tzsUserInfoDto.getCertificateNum());
        queryWrapper.ne(TzsUserInfo::getSequenceNbr, rowId);
        queryWrapper.eq(TzsUserInfo::getIsDelete, false);
        TzsUserInfo certificateNum = tzsUserInfoMapper.selectOne(queryWrapper);
        if (!ObjectUtils.isEmpty(certificateNum)) {
            throw new BadRequest("证件号码重复，请核对！");
        }

        LambdaQueryWrapper<TzsUserInfo> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(TzsUserInfo::getPhone, tzsUserInfoDto.getPhone());
        queryWrapper1.ne(TzsUserInfo::getSequenceNbr, rowId);
        queryWrapper1.eq(TzsUserInfo::getIsDelete, false);
        TzsUserInfo phone = tzsUserInfoMapper.selectOne(queryWrapper1);
        if (!ObjectUtils.isEmpty(phone)) {
            throw new BadRequest("联系电话重复，请核对！");
        }

        ReginParams reginParams = JSON.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        if (ObjectUtils.isEmpty(reginParams)) {
            return null;
        }
        CompanyBo companyModel = reginParams.getCompany();
        if (ObjectUtils.isEmpty(companyModel)) {
            throw new BadRequest("未指定人员归属单位信息");
        }

        //删除人员与组的关系
        QueryWrapper<TzsUserInfo> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("sequence_nbr", rowId);
        queryWrapper2.eq("is_delete", false);
        TzsUserInfo selectOne = tzsUserInfoMapper.selectOne(queryWrapper2);
        if (!ObjectUtils.isEmpty(selectOne.getAmosUserId())) {
            this.deleteGroupAndPersonRelation(selectOne.getPostName(), selectOne.getAmosUserId());
        }

        tzsUserInfoDto.setUnitName(companyModel.getCompanyName());
        tzsUserInfoDto.setUnitCode(companyModel.getCompanyCode());
        tzsUserInfoDto.setSequenceNbr(rowId);
        tzsUserInfoDto.setRecDate(new Date());
        // 兼容前端只传一个值，并且非json类型的情况
        JSONArray postArray = JSONArray.parseArray(this.isJSONValid(tzsUserInfoDto.getNewPost()) ? tzsUserInfoDto.getNewPost() : "[\"" + tzsUserInfoDto.getNewPost() + "\"]");
        tzsUserInfoDto.setNewPost(JSONArray.toJSONString(postArray));
        // 兼容 人员类型为【作业人员】且 【作业项目】含有【电梯修理】项目的为【维保人员】post为“6618”
        JSONArray permissionData6552 = tzsUserInfoDto.getPermissionData6552();
        if (!permissionData6552.isEmpty() && postArray.contains("6552")) {
            JSONObject jsonObject = permissionData6552.getJSONObject(0);
            JSONArray jobItem = jsonObject.getJSONArray("jobItem");
            if (jobItem != null && jobItem.contains("电梯修理")) {
                postArray.add("6618");
            }
        }
        tzsUserInfoDto.setPost(JSONArray.toJSONString(postArray));
        String postName = this.setPostName(tzsUserInfoDto.getNewPost());
        tzsUserInfoDto.setPostName(postName);
        if (!ObjectUtils.isEmpty(selectOne.getAmosUserId())) {
            // 添加新的人员与组的关系
            String[] split = postName.split(",");
            List<String> ids = new ArrayList<>();
            ids.add(selectOne.getAmosUserId());
            for (String s : split) {
                if (!ObjectUtils.isEmpty(TwoStipulateGroupEnum.getId.get(s))) {
                    Privilege.groupUserClient.create(TwoStipulateGroupEnum.getId.get(s), ids);
                }
            }
        }
        // 更新资质
        tzsUserPermissionServiceImpl.updatePermissionData(tzsUserInfoDto);
        tzsUserInfoDto.setQrCodeState("1");
        this.updateWithModel(tzsUserInfoDto);
        return tzsUserInfoDto;
    }

    public List<DataDictionary> userTypeUnderMenu(String menu) {
        List<String> userTypeCode = menuMap.getOrDefault(menu, new ArrayList<>());
        if (userTypeCode.isEmpty()) {
            return Collections.emptyList();
        }
        List<String> act = new ArrayList<>(userTypeCode);
        return iDataDictionaryService.getBaseMapper().selectBatchIds(act);
    }

    /**
     * 人员列表列表数据导出
     *
     * @param response 响应
     * @param ids      数据id
     */
    @Override
    public void userInfoExport(HttpServletResponse response, List<String> ids) {
        List<UserInfoVo> exportData = tzsUserInfoMapper.queryUserInfoInIds(ids);
        ExcelUtil.createTemplate(response, "人员列表数据", "人员列表", exportData, UserInfoVo.class, null, false);
    }

    private List<String> checkFieldIsValid(List<UserImportDto> userItems) {
        List<String> errors = new ArrayList<>();
        // 1.必输校验
        for (int i = 0; i < userItems.size(); i++) {
            UserImportDto userImportDto = userItems.get(i);
            Set<ConstraintViolation<UserImportDto>> violations = validator.validate(userImportDto);
            for (ConstraintViolation<UserImportDto> violation : violations) {
                errors.add("非法数据，第" + (i + 1) + "行" + violation.getMessage());
            }
        }
        if (!errors.isEmpty()) {
            return errors;
        }
        // 2.手机号重复检验，手机号全局唯一,不同单位下的手机号不能相同 todo 新写判断逻辑
        Map<String, Set<String>> phoneCheckRepeatCount = new HashMap<>();
        userItems.forEach(v -> {
            if (phoneCheckRepeatCount.containsKey(v.getPhone())) {
                phoneCheckRepeatCount.get(v.getPhone()).add(v.getUnitCode());
            } else {
                Set<String> set = new HashSet<>();
                set.add(v.getUnitCode());
                phoneCheckRepeatCount.put(v.getPhone(), set);
            }
        });
        phoneCheckRepeatCount.forEach(((k, v) -> {
            if (v.size() > 1) {
                String phone = k.split("_")[0];
                errors.add(String.format("非法数据，存在手机号%s，在多个单位统一信用代码：%s下共用，请检查后进行上传！", phone, StringUtils.join(v, ",")));
            }
        }));
        // 3.手机号重复检验，手机号全局唯一,不同单位下的手机号不能相同 todo 新写判断逻辑
        Map<String, Set<String>> certNoCheckRepeatCount = new HashMap<>();
        userItems.forEach(v -> {
            if (certNoCheckRepeatCount.containsKey(v.getPhone())) {
                certNoCheckRepeatCount.get(v.getPhone()).add(v.getCertificateNum());
            } else {
                Set<String> set = new HashSet<>();
                set.add(v.getCertificateNum());
                certNoCheckRepeatCount.put(v.getPhone(), set);
            }
        });
        // 3.手机号相同，但是证件号码存在多个-非法数据
        certNoCheckRepeatCount.forEach(((k, v) -> {
            if (v.size() > 1) {
                String phone = k.split("_")[0];
                errors.add(String.format("非法数据，存在多个证件号码：%s，共用相同的手机号%s，请检查后进行上传！", StringUtils.join(v, ","), phone));
            }
        }));
        return errors;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseModel<?> importUserBatch(MultipartFile multipartFile) {
        Map<Long, TzsUserInfo> userInfoMap = new HashMap<>();
        try {
            List<UserImportDto> userItems = ExcelUtil.readFirstSheetExcel(multipartFile, UserImportDto.class, 2);
            // 1.数据检验
            List<String> errors = checkFieldIsValid(userItems);
            // 1.1存在检验不通过的数据则进行提示，不在向下写入库
            if (!errors.isEmpty()) {
                return ResponseHelper.buildResponse(errors);
            }
            // 2.数据处理
            // 2.1数据合并:按照手机号数据去重合并
            Set<UserImportDto> userSet = new HashSet<>(userItems);
            // 2.2合并构造单位类型+人员类型，处理一个人有多个单位类型+多个人员类型
            this.buildMergeFields(userItems, userSet);
            // 3.数据入库
            // 3.1业务库入库
            userInfoMap = this.saveImportData2Db(userSet);
            // 3.2部分类型用户平台创建人员
            this.createAmosUser(userInfoMap, userSet);
        } catch (Exception e) {
            if(!userInfoMap.values().isEmpty()){
                List<String> userIds = userInfoMap.values().stream().map(TzsUserInfo::getAmosUserId).filter(StringUtils::isNotEmpty).collect(Collectors.toList());
                for(String userId : userIds){
                    // 单个删除，平台接口删除时，判断了有才能删除，匹配删除可能存在某个用户不存在导致删除失败
                    try {
                        Privilege.agencyUserClient.multDeleteUser(userId);
                    } catch (Exception e1) {
                        log.error("删除用户：{}，失败:{}！", userId, e1.getMessage());
                    }
                }
            }
            throw new RuntimeException(e);
        }
        return ResponseHelper.buildResponse("succese");
    }

    private void createAmosUser(Map<Long, TzsUserInfo> userInfoMap, Set<UserImportDto> userSet) {
        // 1.公共数据处理
        //   1.1公司缓存
        Map<String, CompanyModel> companyCodeCompanyMap = new ConcurrentHashMap<>();
        Map<Long, UserImportDto> userSeqImportDataMap = userSet.stream().collect(Collectors.toMap(UserImportDto::getSeq, Function.identity()));
        //   1.2单位类型下角色缓存
        List<DataDictionary> unitTypeList = regUnitInfoService.setAndGetUnitTypeList();
        Map<String, DataDictionary> dataDictionaryMap = unitTypeList.stream().collect(Collectors.toMap(DataDictionary::getName, Function.identity(), (k1, k2) -> k1));
        //   1.3通用角色-普通用户处理
        List<RoleModel> allRoleList = getCommonRoleModels();
        // 2.用户创建
        //  2.1创建前检验-单位类型是否合法（用户的单位类型不能大于所在公司的注册时的单位类型）
        userInfoMap.forEach((k, v) -> {
            checkOneUser(v, userSeqImportDataMap.get(k), companyCodeCompanyMap);
        });
        //  2.2创建
        userInfoMap.forEach((k, v) -> {
            createOneUser(v, userSeqImportDataMap.get(k), companyCodeCompanyMap, dataDictionaryMap, allRoleList);
        });
        // 3.绑定用户到用户组
        this.bindUserToGroup(userInfoMap.values());
    }

    private void bindUserToGroup(Collection<TzsUserInfo> values) {
        List<String> userIds =values.stream().map(TzsUserInfo::getAmosUserId).filter(StringUtils::isNotEmpty).collect(Collectors.toList());
        try {
            if(!userIds.isEmpty()){
                // 绑定企业整改用户组
                String roleGroupCode = "6596";
                DataDictionary roleGroup = iDataDictionaryService
                        .getOne(new LambdaQueryWrapper<DataDictionary>().eq(DataDictionary::getCode, roleGroupCode).eq(DataDictionary::getType, ROLE_GROUP));
                if (!ObjectUtils.isEmpty(roleGroup) && roleGroup.getExtend() != null) {
                    Privilege.groupUserClient.create(Long.valueOf(roleGroup.getExtend()), userIds);
                }
                // 绑定两个规定用户组
                for(TzsUserInfo userInfo : values) {
                    String newPost = userInfo.getPost();
                    List<String> posts = Optional.ofNullable(JSONArray.parseArray(newPost, String.class)).orElse(new ArrayList<>());
                    for (String code : posts) {
                        bind2PermissionGroup(Collections.singletonList(userInfo.getAmosUserId()), code);
                    }
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BadRequest(e.getMessage());
        }
    }

    /**
     * 两个规定用户组绑定
     * @param userIds 用户id
     * @param post    人员类型
     */
    private void bind2PermissionGroup(List<String> userIds, String post) {
        // post    name            用户组id
        // 6549	  安全员	        1712372048442978305
        // 6548	  主要负责人	    1712372027123331074
        // 6547	  安全总监	    1712372007611428865
        // 6546	  普通员工	    1712371988107915266
        // 6552	  作业人员	    1712372137114759170
        // 6551	  质量安全员	    1712372116055158786
        // 6550	  质量安全总监	1712372080231608322
        DataDictionary groupId = iDataDictionaryService.getOne(new LambdaQueryWrapper<DataDictionary>().eq(DataDictionary::getCode, post).likeRight(DataDictionary::getType, QYRYGW));
        if (!ObjectUtils.isEmpty(groupId) && groupId.getExtend() != null) {
            Privilege.groupUserClient.create(Long.valueOf(groupId.getExtend()), userIds);
        }
    }

    private List<RoleModel> getCommonRoleModels() {
        String commonRule = "1554";
        List<RoleModel> allRoleList = new ArrayList<>();
        DataDictionary unitType = iDataDictionaryService.getOne(new LambdaQueryWrapper<DataDictionary>().eq(DataDictionary::getCode, commonRule).eq(DataDictionary::getType, USER_ROLE));
        String role = unitType.getExtend() != null ? unitType.getExtend() : "";
        for (String s : role.split(",")) {
            RoleModel roleModel = Privilege.roleClient.seleteOne(Long.valueOf(s)).getResult();
            allRoleList.add(roleModel);
        }
        return allRoleList;
    }

    private Map<Long, TzsUserInfo> saveImportData2Db(Set<UserImportDto> userSet) {
        List<TzsUserInfo> userInfos = userSet.parallelStream().map(dto -> {
            TzsUserInfo userInfo = new TzsUserInfo();
            userInfo.setRecUserId(RequestContext.getExeUserId());
            userInfo.setRecDate(new Date());
            userInfo.setName(dto.getName());
            userInfo.setSequenceNbr(dto.getSeq());
            userInfo.setGender(dto.getGender());
            userInfo.setEmail(dto.getEmail());
            userInfo.setPhone(dto.getPhone());
            userInfo.setAddress(dto.getAddress());
            Set<String> postSet = dto.getUnitTypePostMap().values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
            // TODO 无资质导入，默认post = newPost
            userInfo.setPost(JSON.toJSONString(postSet));
            // TODO 无资质导入，默认post = newPost
            userInfo.setNewPost(JSON.toJSONString(postSet));
            String postName = this.setPostName(userInfo.getNewPost());
            userInfo.setPostName(postName);
            userInfo.setBirthday(dto.getBirthday());
            userInfo.setEducation(dto.getEducation());
            userInfo.setSpeciality(dto.getSpeciality());
            userInfo.setUnitName(dto.getUnitName());
            userInfo.setCertificateNum(dto.getCertificateNum());
            userInfo.setCertificateType(dto.getCertificateType());
            userInfo.setIsDelete(false);
            userInfo.setLockStatus(UNLOCK);
            userInfo.setUnitCode(dto.getUnitCode());
            userInfo.setEquipType(dto.getEquipType());
            userInfo.setJobTitle(dto.getJobTitle());
            userInfo.setEquipType(JSON.toJSONString(dto.getEquipTypeList()));
            return userInfo;
        }).collect(Collectors.toList());
        super.saveOrUpdateBatch(userInfos);
        return userInfos.stream().collect(Collectors.toMap(BaseEntity::getSequenceNbr, Function.identity()));
    }

    private void buildMergeFields(List<UserImportDto> userItems, Set<UserImportDto> userSet) {
        for (UserImportDto userImportDto : userSet) {
            List<UserImportDto> oData = userItems.stream().filter(u -> u.getPhone().equals(userImportDto.getPhone())).collect(Collectors.toList());
            for (UserImportDto user : oData) {
                Map<String, Set<String>> map = userImportDto.getUnitTypePostMap();
                if (map == null) {
                    map = new HashMap<>();
                    map.put(user.getUnitType(), Sets.newHashSet(user.getPost()));
                    userImportDto.setUnitTypePostMap(map);
                } else {
                    map.get(user.getUnitType()).add(user.getPost());
                }
                Set<String> equipTypes = userImportDto.getEquipTypeList();
                if (equipTypes == null) {
                    Set<String> equipTypesNew = new HashSet<>();
                    equipTypesNew.add(user.getEquipType());
                    userImportDto.setEquipTypeList(equipTypesNew);
                } else {
                    equipTypes.add(user.getEquipType());
                }
            }
            userImportDto.getEquipTypeList().remove(null);
            userImportDto.getEquipTypeList().remove("");
            userImportDto.setSeq(sequence.nextId());
        }

    }

    public void checkOneUser(TzsUserInfo tzsUserInfo, UserImportDto userImportDto, Map<String, CompanyModel> companyCodeCompanyMap) {
        CompanyModel companyModel = getCompanyModelUseCache(tzsUserInfo, companyCodeCompanyMap);
        String companyType = companyModel.getCompanyType();
        // 增加约束，增加的人的单位类型不能大于单位的单位类型
        boolean existIllegalUnitType = userImportDto.getUnitTypePostMap().keySet().stream().anyMatch(u -> !companyType.contains(u));
        if(existIllegalUnitType){
            throw new BadRequest("导入的用户：" + tzsUserInfo.getName() + "，手机号：" + tzsUserInfo.getPhone() + "，公司类型只能为：" + companyType  + "之一！");
        }
    }

    public void createOneUser(TzsUserInfo tzsUserInfo, UserImportDto userImportDto, Map<String, CompanyModel> companyCodeCompanyMap, Map<String, DataDictionary> dataDictionaryMap, List<RoleModel> allRoleList) {
        FeignClientResult<AgencyUserModel> userResult = null;
        try {
            CompanyModel companyModel = getCompanyModelUseCache(tzsUserInfo, companyCodeCompanyMap);
            String companyType = companyModel.getCompanyType();
            // 默认的密码
            String passwd = DesUtil.encode("a_" + tzsUserInfo.getPhone(), "qaz");
            // 获取对应单位类型下的引用并去重
            Set<String> appCodesSet = getAppKeys(userImportDto, dataDictionaryMap);
            List<Long> roleIds = new ArrayList<>();
            allRoleList.forEach(r -> {
                if (!roleIds.contains(r.getSequenceNbr())) {
                    roleIds.add(r.getSequenceNbr());
                }
            });
            AgencyUserModel agencyUserModel = new AgencyUserModel();
            agencyUserModel.setUserName(tzsUserInfo.getPhone());
            agencyUserModel.setRealName(tzsUserInfo.getName());
            agencyUserModel.setLockStatus(UNLOCK);
            agencyUserModel.setPassword(passwd);
            agencyUserModel.setRePassword(passwd);
            agencyUserModel.setAgencyCode("tzs");
            agencyUserModel.setMobile(tzsUserInfo.getPhone());
            agencyUserModel.setEmail(tzsUserInfo.getEmail());
            // 添加业务办理人员角色
            String post = tzsUserInfo.getPost();
            if (post.contains(PersonManageRoleEnum.code.getId().toString())) {
                setBizOperateUserRole(companyType, roleIds);
            }
            Map<Long, List<Long>> roleSeqMap = new HashMap<>();
            Map<Long, List<RoleModel>> orgRoles = new HashMap<>();
            roleSeqMap.put(companyModel.getSequenceNbr(), roleIds);
            orgRoles.put(companyModel.getSequenceNbr(), allRoleList);
            agencyUserModel.setAppCodes(new ArrayList<>(appCodesSet));
            agencyUserModel.setOrgRoles(orgRoles);
            agencyUserModel.setOrgRoleSeqs(roleSeqMap);
            userResult = Privilege.agencyUserClient.create(agencyUserModel);
            tzsUserInfo.setAmosUserId(userResult.getResult().getUserId());
            tzsUserInfo.setAmosUserName(userResult.getResult().getUserName());
            tzsUserInfo.setLockStatus(UNLOCK);
            tzsUserInfo.setUnitName(companyModel.getCompanyName());
            tzsUserInfoMapper.updateById(tzsUserInfo);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            // 防止 创建成功后tzsUserInfo.setAmosUserId(userResult.getResult().getUserId()) 报错导致外侧删除不成功，健壮性处理，正常不会出错
            if (userResult != null && userResult.getResult() != null
                    && StringUtils.isNotEmpty(userResult.getResult().getUserId())) {
                Privilege.agencyUserClient.multDeleteUser(userResult.getResult().getUserId());
            }
            if(e instanceof InnerInvokException){
                String message = e.getLocalizedMessage();
                if(StringUtils.isNotEmpty(message) && message.contains("用户名已存在")){
                    throw new BadRequest("手机号：" + tzsUserInfo.getPhone() + "已经被使用，请更换！");
                }
            }
            throw new BadRequest(e.getMessage());
        }
    }

    private CompanyModel getCompanyModelUseCache(TzsUserInfo tzsUserInfo, Map<String, CompanyModel> companyCodeCompanyMap) {
        CompanyModel companyModel;
        if (companyCodeCompanyMap.get(tzsUserInfo.getUnitCode()) != null) {
            companyModel = companyCodeCompanyMap.get(tzsUserInfo.getUnitCode());
        } else {
            companyModel = baseEnterpriseInfoService.getBaseMapper().getOneByCompanyCode(tzsUserInfo.getUnitCode());
            if(companyModel == null){
                throw new BadRequest("单位统一信用代码为：" + tzsUserInfo.getUnitCode() + "的单位还未进行注册，请确认数据是否正确！");
            }
            companyCodeCompanyMap.put(tzsUserInfo.getUnitCode(), companyModel);
        }
        return companyModel;
    }

    private static Set<String> getAppKeys(UserImportDto userImportDto, Map<String, DataDictionary> dataDictionaryMap) {
        Set<String> appCodesSet = new HashSet<>();
        userImportDto.getUnitTypePostMap().forEach((k, v) -> {
            DataDictionary unitType = dataDictionaryMap.get(k);
            String appCode = unitType.getTypeDesc() != null ? unitType.getTypeDesc() : "";
            String[] appCodes = appCode.split(",");
            Collections.addAll(appCodesSet, appCodes);
        });
        return appCodesSet;
    }

    private void setBizOperateUserRole(String companyType, List<Long> roleIds) {
        if (companyType.contains(PersonManageRoleEnum.jyjc.getName())) {
            roleIds.add(PersonManageRoleEnum.jyjc.getId());
        }
        if (companyType.contains(PersonManageRoleEnum.use.getName())) {
            roleIds.add(PersonManageRoleEnum.use.getId());
        }
        if (companyType.contains(PersonManageRoleEnum.agw.getName())) {
            roleIds.add(PersonManageRoleEnum.agw.getId());
        }
    }


}
