package com.gic.haoban.manage.service.service.out.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gic.api.base.commons.Constant;
import com.gic.api.base.commons.Page;
import com.gic.clerk.api.dto.ClerkDTO;
import com.gic.clerk.api.service.ClerkService;
import com.gic.clerk.api.service.PowerService;
import com.gic.commons.util.DateUtil;
import com.gic.commons.util.EntityUtil;
import com.gic.commons.util.ImageUtil;
import com.gic.enterprise.api.dto.*;
import com.gic.enterprise.api.service.EnterpriseService;
import com.gic.enterprise.api.service.StoreGroupService;
import com.gic.enterprise.api.service.StoreService;
import com.gic.enterprise.api.service.StoreWidgetService;
import com.gic.haoban.base.api.common.BasePageInfo;
import com.gic.haoban.base.api.common.ServiceResponse;
import com.gic.haoban.common.utils.PageUtil;
import com.gic.haoban.common.utils.RolesListUtils;
import com.gic.haoban.common.utils.UuidUtil;
import com.gic.haoban.manage.api.dto.*;
import com.gic.haoban.manage.api.dto.qdto.TransferActiveCodeQDTO;
import com.gic.haoban.manage.api.dto.role.StoreRoleDTO;
import com.gic.haoban.manage.api.enums.ChannelCodeEnum;
import com.gic.haoban.manage.api.enums.SecretTypeEnum;
import com.gic.haoban.manage.api.enums.SyncTaskTypeEnum;
import com.gic.haoban.manage.api.service.DealSyncOperationApiService;
import com.gic.haoban.manage.api.service.MessageApiService;
import com.gic.haoban.manage.api.service.StaffApiService;
import com.gic.haoban.manage.service.config.Config;
import com.gic.haoban.manage.service.dao.mapper.StaffDepartmentRelatedMapper;
import com.gic.haoban.manage.service.dao.mapper.StaffMapper;
import com.gic.haoban.manage.service.entity.*;
import com.gic.haoban.manage.service.entity.fee.TabHaobanQywxFeeOrder;
import com.gic.haoban.manage.service.entity.fee.TabHaobanQywxFeeOrderAccount;
import com.gic.haoban.manage.service.errorcode.QywxErrCode;
import com.gic.haoban.manage.service.pojo.bo.StaffListBO;
import com.gic.haoban.manage.service.service.*;
import com.gic.haoban.manage.service.service.chat.GroupChatService;
import com.gic.haoban.manage.service.service.fee.HaobanQywxFeeOrderAccountService;
import com.gic.haoban.manage.service.service.fee.HaobanQywxFeeOrderService;
import com.gic.haoban.manage.service.util.DingUtils;
import com.gic.haoban.manage.service.util.EmojiFilterUtil;
import com.gic.redis.data.util.RedisUtil;
import com.gic.thirdparty.cloudfile.CloudFileUtil;
import com.gic.thirdparty.cloudfile.enums.CloudFileBusinessOptEnum;
import com.gic.thirdparty.cloudfile.enums.CloudFileTypeEnum;
import com.gic.thirdparty.cloudfile.pojo.CloudFileInfo;
import com.gic.wechat.api.dto.qywx.QywxNewUseridDTO;
import com.gic.wechat.api.dto.qywx.UserDTO;
import com.gic.wechat.api.dto.qywx.fee.AccountTransferUserDTO;
import com.gic.wechat.api.dto.qywx.fee.FeeOrderDeatilResponseDTO;
import com.gic.wechat.api.dto.qywx.response.QywxResponseDTO;
import com.gic.wechat.api.service.qywx.QywxOrderApiService;
import com.gic.wechat.api.service.qywx.QywxUserApiService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class StaffApiServiceImpl implements StaffApiService {

    private static final Logger logger = LoggerFactory.getLogger(StaffApiServiceImpl.class);
    @Autowired
    private StaffService staffService;
    @Autowired
    private StaffMapper staffMapper;
    @Autowired
    private StaffDepartmentRelatedService staffDepartmentRelatedService;
    @Autowired
    private StaffDepartmentRelatedMapper staffDepartmentRelatedMapper;
    @Autowired
    private QywxUserApiService qywxUserApiService;
    @Autowired
    private WxEnterpriseService wxEnterpriseService;
    @Autowired
    private DepartmentService departmentService;
    @Autowired
    private ClerkService clerkService;
    @Autowired
    private StoreGroupService storeGroupService;
    @Autowired
    private UserLoginLogService userLoginLogService;
    @Autowired
    private SyncErrorLogService syncErrorLogService;
    @Autowired
    private StaffClerkRelationService staffClerkRelationService;
    @Autowired
    private SecretSettingService secretSettingService;
    @Autowired
    private StaffPrivacyUseLogService staffPrivacyUseLogService;
    @Autowired
    private StoreWidgetService storeWidgetService;
    @Autowired
    private PowerService powerService;
    @Autowired
    private StoreRangeService storeRangeService;
    @Autowired
    private EnterpriseService enterpriseService;
    @Autowired
    private Config config;
    @Autowired
    private QywxOrderApiService qywxOrderApiService;
    @Autowired
    private GroupChatService groupChatService;
    @Autowired
    private WxEnterpriseRelatedService wxEnterpriseRelatedService;
    @Autowired
    private DealSyncOperationApiService dealSyncOperationApiService;
    @Autowired
    private ExternalClerkRelatedService externalClerkRelatedService;
    @Autowired
    private WxEnterpriseActiveDataService wxEnterpriseActiveDataService;
    @Autowired
    private HaobanQywxFeeOrderAccountService haobanQywxFeeOrderAccountService;
    @Autowired
    private HaobanQywxFeeOrderService haobanQywxFeeOrderService;
    @Autowired
    private MessageApiService messageApiService ;
    @Autowired
    private StoreService storeService ;
    @Autowired
    private OpenStaffService openStaffService ;

    @Override
    public StaffDTO selectById(String staffId) {
        TabHaobanStaff staff = staffService.selectById(staffId);
        return EntityUtil.changeEntityByJSON(StaffDTO.class, staff);
    }

    @Override
    public List<StaffDTO> listByPhoneNumber(String phoneNumber) {
        List<TabHaobanStaff> staffs = staffMapper.listByPhoneNumber(phoneNumber);
        return EntityUtil.changeEntityListByJSON(StaffDTO.class, staffs);
    }

    @Override
    public StaffDTO selectByNationcodeAndPhoneNumber(String wxEnterpriseId, String nationcode, String phoneNumber) {
        TabHaobanStaff staff = staffService.selectByNationcodeAndPhoneNumber(wxEnterpriseId, nationcode, phoneNumber);
        return EntityUtil.changeEntityByJSON(StaffDTO.class, staff);
    }

    @Override
    public List<StaffDepartmentRelatedDTO> listStaffDepartmentByStaffId(String staffId) {
        List<TabHaobanStaffDepartmentRelated> list = staffDepartmentRelatedService.listStaffDepartmentByStaffId(staffId);
        // 如果成员部门为空,修复部门数据
        if(CollectionUtils.isEmpty(list)) {
           this.staffDepartmentRelatedService.repairStaffDepart(staffId);
        }
        return EntityUtil.changeEntityListByJSON(StaffDepartmentRelatedDTO.class, list);
    }

    @Override
    public Page<StaffDTO> pageStaff(StaffListDTO staffListDTO) {
        if (null == staffListDTO){
            return new Page<>();
        }
        logger.info("通讯录列表查询参数：{}",JSONObject.toJSONString(staffListDTO));
        Integer relationFlag = staffListDTO.getRelationFlag();
        String wxEnterpriseId = staffListDTO.getWxEnterpriseId();
        BasePageInfo pageInfo = staffListDTO.getPageInfo();
        String enterpriseIdParam = staffListDTO.getEnterpriseIdParam();
        if(staffListDTO.getQwOpenFlag()==1) {
            enterpriseIdParam = staffListDTO.getLoginEnterpriseId() ;
        }
        List<String> staffIds = new ArrayList<>();
        //查询所属品牌成员id
        if(StrUtil.isNotBlank(enterpriseIdParam)){
            //-1表示查询成员所属商户是无归属的
            if ("-1".equals(enterpriseIdParam)){
                staffIds = staffClerkRelationService.listByWxEnterpriseId(wxEnterpriseId);
                relationFlag = 0;
            }else {
                staffIds = staffClerkRelationService.listAllStaffIdByEnterpriseId(enterpriseIdParam, wxEnterpriseId);
                relationFlag = 1;
            }
            if (CollectionUtils.isEmpty(staffIds)){
                return new Page<>();
            }
        }else {
            if (relationFlag != null) {
                staffIds = staffClerkRelationService.listByWxEnterpriseId(wxEnterpriseId);
                if (CollectionUtils.isEmpty(staffIds) && relationFlag == 1){
                    return new Page<>();
                }
            }
        }
        if(staffListDTO.getQwOpenFlag()==1) {
            List<String> list = this.openStaffService.listAllStaffId(wxEnterpriseId) ;
            staffIds = staffIds.stream().filter(o->!list.contains(o)).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(staffIds)){
                return new Page<>();
            }
        }
        StaffListBO staffListBO = EntityUtil.changeEntityByJSON(StaffListBO.class, staffListDTO);
        staffListBO.setStaffIds(staffIds);
        staffListBO.setRelationFlag(relationFlag);
        PageHelper.startPage(pageInfo.getPageNum(), pageInfo.getPageSize());
        Page<StaffDTO> page = PageUtil.changePageHelperToCurrentPage(staffService.pageStaff(staffListBO), StaffDTO.class);
        List<StaffDTO> staffDTOList = page.getResult();
        if (CollectionUtils.isEmpty(staffDTOList)) {
            return new Page<>();
        }
        Set<String> staffIdList = staffDTOList.stream().map(dto -> dto.getStaffId()).collect(Collectors.toSet());
        List<String> relationIdList = this.staffClerkRelationService.listRelationsStaffId(staffIdList);
        //已关联的成员需要查询关联的品牌名称
        List<TabHaobanWxEnterpriseRelated> list = wxEnterpriseRelatedService.getByWxEnterpriseId(wxEnterpriseId);
        //解决空指针异常问题
        Map<String, String> map = list.stream().collect(HashMap::new,(k, v) -> k.put(v.getEnterpriseId(), v.getEnterpriseName()), HashMap::putAll);
        List<StaffClerkRelationDTO> relationDTOList = staffClerkRelationService.listByWxEnterpriseIdAndStaffId(wxEnterpriseId, staffIdList);
        String loginEnterpriseId = staffListDTO.getLoginEnterpriseId() ;
        Map<String,ClerkDTO> clerkMap = new HashMap<>() ;
        if(CollectionUtils.isNotEmpty(relationDTOList)) {
            Set<String> clerkIdSet = relationDTOList.stream().filter(o->o.getEnterpriseId().equals(loginEnterpriseId)).map(o->o.getClerkId()).collect(Collectors.toSet()) ;
            if(CollectionUtils.isNotEmpty(clerkIdSet)) {
                List<ClerkDTO> clerkDTOS = this.clerkService.getClerkByIds(clerkIdSet);
                clerkMap.putAll(clerkDTOS.stream().collect(Collectors.toMap(o -> o.getClerkId(), o -> o, (k1, k2) -> k1)));
            }
        }
        logger.info("导购={}",JSONObject.toJSONString(clerkMap));
        staffDTOList.forEach(one -> {
            if(relationIdList.contains(one.getStaffId())){
                one.setRelationFlag(1);
                //查询导购关联关系表，找到对应的商户名称
                List<String> enterpriseNameList = new ArrayList<>(8);
                for (StaffClerkRelationDTO dto : relationDTOList){
                    if (dto.getStaffId().equals(one.getStaffId())){
                        enterpriseNameList.add(map.get(dto.getEnterpriseId()));
                        if(null != clerkMap.get(dto.getClerkId())) {
                            String c = one.getClerkCode() ;
                            if(StringUtils.isBlank(c)) {
                                one.setClerkCode(clerkMap.get(dto.getClerkId()).getClerkCode());
                            }else {
                               one.setClerkCode(c+"、"+clerkMap.get(dto.getClerkId()).getClerkCode());
                            }
                        }
                    }
                }
                if (CollUtil.isNotEmpty(enterpriseNameList)){
                    //对商户名称去重
                    enterpriseNameList = enterpriseNameList.stream().distinct().collect(Collectors.toList());
                    one.setEnterpriseNameList(enterpriseNameList);
                }
            }else {
                one.setRelationFlag(0);
            }

        });
        return page;
    }

    @Override
    public List<StaffDTO> listByIds(List<String> staffIds) {
        if (CollectionUtil.isEmpty(staffIds)) {
            return new ArrayList<StaffDTO>();
        }
        List<TabHaobanStaff> staffs = staffMapper.listByIds(staffIds);
        if (CollectionUtil.isNotEmpty(staffs)) {
            List<StaffDTO> resultList = EntityUtil.changeEntityListByJSON(StaffDTO.class, staffs);
            return resultList;
        } else {
            return new ArrayList<StaffDTO>();
        }
    }

    public ServiceResponse getWxSaveNew(String wxUserId, String wxEnterpriseId) {
        return this.getWxSaveNew(wxUserId,wxEnterpriseId,false) ;
    }

    @Override
    public ServiceResponse getWxSaveNew(String wxUserId, String wxEnterpriseId,boolean isSyncDepart) {
        ServiceResponse res = new ServiceResponse();
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        if (null == qwDTO) {
            logger.info("企业不存在:{}:{}", wxEnterpriseId, wxUserId);
            res.setMessage("企业不存在");
            res.setCode(2);
            return res;
        }
        String dkCorpid = qwDTO.getDkCorpid();
        SecretSettingDTO secretSetting = secretSettingService.getSecretSetting(qwDTO.getWxEnterpriseId(), SecretTypeEnum.CUSTOMIZED_APP.getVal());
        if (null == secretSetting || secretSetting.getCheckFlag() == 0) {
            logger.info("没有配置secret：{}", JSONObject.toJSONString(qwDTO));
            res.setMessage("没有配置secret");
            res.setCode(4);
            return res;
        }
        UserDTO user = null;
        if (qwDTO.getWxSecurityType() == 4) {
            user = qywxUserApiService.getWorkWxUser(qwDTO.getThirdCorpid(), config.getWxSuiteid(), wxUserId);
            logger.info("成员详情(第三方)={}", JSON.toJSONString(user));
            UserDTO userSelf = qywxUserApiService.getSelfWorkWxUser(dkCorpid, secretSetting.getSecretVal(), user.getOpen_userid() , qwDTO.getUrlHost());
            logger.info("成员详情(代开)={}", JSON.toJSONString(user));
            if (user != null && userSelf != null) {
                user.setName(userSelf.getName());
                user.setPosition(userSelf.getPosition());
            }
        } else {
            user = qywxUserApiService.getSelfWorkWxUser(dkCorpid, secretSetting.getSecretVal(), wxUserId , qwDTO.getUrlHost());
            logger.info("成员详情(代开)={}", JSON.toJSONString(user));
        }
        if (null == user) {
            logger.info("企业微信用户不存在:{}:{}", wxEnterpriseId, wxUserId);
            res.setMessage("企业微信用户不存在");
            res.setCode(3);
            return res;
        }
        String nationCode = null;
        String phoneNumber = null;
        String imageUrl = changeHeaderImageUrl(user.getAvatar());
        String mobile = user.getMobile();
        if (StringUtils.isNotBlank(mobile)) {
            String[] arr = getNationCodeAndPhoneNumber(mobile);
            nationCode = arr[0];
            phoneNumber = arr[1];
        }
        String openUserid = getOpenUserid(wxUserId, dkCorpid, qwDTO);
        TabHaobanStaff staff = new TabHaobanStaff();
        List<StaffDTO> staffDTOList = staffService.listByUserIdsAndWxEnterpriseId(Lists.newArrayList(wxUserId,openUserid), wxEnterpriseId);
        if (CollUtil.isNotEmpty(staffDTOList) && staffDTOList.size()>1) {
            com.gic.haoban.common.utils.DingUtils.send("告警【多条重复staff】,企业ID"+wxEnterpriseId,true);
        }
        if (CollUtil.isNotEmpty(staffDTOList)){
            staff = JSONObject.parseObject(JSONObject.toJSONString(staffDTOList.get(0)), TabHaobanStaff.class);
        }
        staff.setWxUserId(wxUserId);
        if (StringUtils.isNotBlank(openUserid)) {
            staff.setWxOpenUseId(openUserid);
        }
        staff.setUpdateTime(new Date());
        staff.setStatusFlag(1);
        staff.setWxEnterpriseId(wxEnterpriseId);
        if (StringUtils.isNotBlank(user.getAvatar())) {
            staff.setHeadImg(imageUrl);
        }
        if (StringUtils.isNotBlank(user.getName())) {
            user.setName(EmojiFilterUtil.removeAllEmoji(user.getName()));
            staff.setStaffName((user.getName()));
        }
        if (StringUtils.isNotBlank(user.getAlias())) {
            user.setAlias(EmojiFilterUtil.removeAllEmoji(user.getAlias()));
            staff.setNickName((user.getAlias()));
        }
        staff.setPhoneNumber(phoneNumber);
        staff.setNationCode(nationCode);
        //由于企业微信取不到用户性别字段，默认性别为0
        staff.setSex(user.getGender() == null ? 0 : Integer.parseInt(user.getGender()));
        staff.setPostion(user.getPosition());
        staff.setExtendPostion(user.getExternal_position());
        String qr_code = user.getQr_code();
        if (StringUtils.isNotBlank(qr_code)) {
            staff.setQrCode(qr_code);
        }
        //判断成员是否开启联系我
        if (this.openConcatFlag(wxEnterpriseId,wxUserId,isSyncDepart,qwDTO)) {
            staff.setOpenConcatFlag(1);
        }
        //成员更改或更新
        if (StringUtils.isBlank(staff.getStaffId())) {
            logger.info("新增成员");
            staff.setActiveFlag(0);
            staff.setCreateTime(new Date());
            staffService.add(staff);
            this.messageApiService.updateForSyncStaff(wxEnterpriseId,staff.getStaffName(),qwDTO,staff.getWxUserId(),
                    user.getMain_department(),user.getPosition(),staff.getSex(),user.getMobile(), staff.getNationCode());
        } else {
            staffService.updateByPrimaryKey(staff);
        }
        logger.info("staff变更保存：{}", JSONObject.toJSONString(user));
        this.staffDepartmentRelatedService.staffDepartChange(staff, wxEnterpriseId, user.getDepartment(),true);
        // 返回结果带上员工姓名
        res.setResult(staff.getStaffName());
        return res;
    }
    private Boolean openConcatFlag(String wxEnterpriseId,String userId , boolean isSyncDepart,WxEnterpriseQwDTO qwDTO){
        List<String> wxUserIdsList = null ;
        //企微已经开启联系我
        Boolean flag = false;
        String key = "get_follow_user_list:"+wxEnterpriseId ;
        if(isSyncDepart) {
            Object o = RedisUtil.getCache(key) ;
            if(null != o) {
                logger.info("从缓存中获取联系我列表={}",wxEnterpriseId);
                wxUserIdsList = (List<String>) o ;
            }
        }
        if(null == wxUserIdsList) {
            if(qwDTO.isSelf()) {
                wxUserIdsList = qywxUserApiService.listCorpExternalUserSelf(qwDTO.getDkCorpid(), qwDTO.getSelfSecret(),qwDTO.getUrlHost());
            }else {
                wxUserIdsList = qywxUserApiService.listCorpExternalUser(qwDTO.getThirdCorpid(), config.getWxSuiteid());
            }
            if(isSyncDepart) {
                RedisUtil.setCache(key,wxUserIdsList,60*60L);
            }
        }
        if (CollUtil.isNotEmpty(wxUserIdsList) && wxUserIdsList.contains(userId)) {
            logger.info("成员开启联系我");
            flag = true;
        }
        return flag;
    }

    /**
     * 获取wxopenuserid
     *
     * @param userId
     * @param corpid
     * @return
     */
    private String getOpenUserid(String userId, String corpid, WxEnterpriseQwDTO qwDTO) {
        if(qwDTO.isSelf()) {
            return null ;
        }
        if (qwDTO.getWxSecurityType() == 2) {
            return userId;
        }
        List<QywxNewUseridDTO> list = null;
        if (qwDTO.getWxSecurityType() == 4) {
            list = qywxUserApiService.useridToOpenuserid(qwDTO.getThirdCorpid(), config.getWxSuiteid(), Collections.singletonList(userId));
        } else {
            // 绝色这类商户在2个服务商,在2023516要切换调
            Object o = RedisUtil.getCache("bgrjswxEnterpriseId");
            if (null != o && o.toString().contains(qwDTO.getWxEnterpriseId())) {
                logger.info("绝色同步通讯录");
                list = qywxUserApiService.useridToOpenuserid(qwDTO.getThirdCorpid(), config.getWxSuiteid(), Collections.singletonList(userId));
            } else {
                SecretSettingDTO set = this.secretSettingService.getSecretSetting(qwDTO.getWxEnterpriseId(), SecretTypeEnum.CUSTOMIZED_APP.getVal());
                list = qywxUserApiService.getSelfUseridToOpenuserid(qwDTO.getDkCorpid(), set.getSecretVal(), Collections.singletonList(userId));
            }
        }
        logger.info("明文userId转密文={},{}", userId, JSON.toJSONString(list));
        if (CollectionUtils.isEmpty(list)) {
            return "";
        }
        return list.get(0).getOpen_userid();
    }

    private String[] getNationCodeAndPhoneNumber(String phoneNumber) {
        String[] arr = new String[2];
        if (StringUtils.isBlank(phoneNumber)) {
            arr[0] = "";
            arr[1] = "";
            return arr;
        }
        arr[0] = "86";
        arr[1] = phoneNumber;
        if (phoneNumber.startsWith("+853")) {
            arr[0] = "853";
            arr[1] = phoneNumber.replace("+853", "");
        }
        if (phoneNumber.startsWith("+852")) {
            arr[0] = "852";
            arr[1] = phoneNumber.replace("+852", "");
        }
        if (phoneNumber.startsWith("+886")) {
            arr[0] = "886";
            arr[1] = phoneNumber.replace("+886", "");
        }
        if (phoneNumber.startsWith("+65")) {
            arr[0] = "65";
            arr[1] = phoneNumber.replace("+65", "");
        }
        if (phoneNumber.startsWith("+66")) {
            arr[0] = "66";
            arr[1] = phoneNumber.replace("+66", "");
        }
        return arr;
    }

    @Override
    public ServiceResponse wxGetAdd(String userId, String wxEnterpriseId) {
        RedisUtil.lock("haoban_add_user" + wxEnterpriseId + userId, 2L);
        ServiceResponse wxSaveNew = getWxSaveNew(userId, wxEnterpriseId);
        logger.info("信息:{}", JSONObject.toJSONString(wxSaveNew));
        return wxSaveNew;
    }

    @Override
    public void wxFristAdd(String userJson, String wxEnterpriseId) {
        if (StringUtils.isBlank(userJson)) {
            return;
        }
        UserDTO user = JSON.parseObject(userJson, UserDTO.class);
        //获取微信用户信息
        String userId = user.getUserid();
        TabHaobanStaff staff = staffService.selectByUserIdAndEnterpriseId(userId, wxEnterpriseId);
        if (staff == null) {
            WxEnterpriseDTO enterpriseDTO = wxEnterpriseService.selectById(wxEnterpriseId);
            if (enterpriseDTO != null) {
                Date now = new Date();
                logger.info("【新增用户】user={}", JSON.toJSONString(user));
                TabHaobanStaff tab = new TabHaobanStaff();
                tab.setWxUserId(userId);
                tab.setCreateTime(now);
                tab.setUpdateTime(now);
                tab.setStatusFlag(1);
                tab.setWxEnterpriseId(wxEnterpriseId);
                if (StringUtils.isNotBlank(user.getAvatar())) {
                    tab.setHeadImg(changeHeaderImageUrl(user.getAvatar()));
                }
                tab.setPhoneNumber(user.getMobile());
                if (StringUtils.isNotBlank(user.getName())) {
                    user.setName(EmojiFilterUtil.removeAllEmoji(user.getName()));
                    tab.setStaffName((user.getName()));
                }
                if (StringUtils.isNotBlank(user.getAlias())) {
                    user.setAlias(EmojiFilterUtil.removeAllEmoji(user.getAlias()));
                    tab.setNickName((user.getAlias()));
                }
                if (StringUtils.isNotBlank(tab.getPhoneNumber())) {
                    tab.setNationCode("86");
                }
                tab.setSex(user.getGender() == null ? 1 : Integer.parseInt(user.getGender()));
                tab.setActiveFlag(1);
                tab.setPostion(user.getPosition());
                tab.setExtendPostion(user.getExternal_position());
                if (user.getStatus() != null && user.getStatus() == 1) {
                    tab.setActiveFlag(1);
                } else {
                    tab.setActiveFlag(0);
                }
                staffService.add(tab);
            }
        } else {
            WxEnterpriseDTO enterpriseDTO = wxEnterpriseService.selectById(wxEnterpriseId);
            if (enterpriseDTO != null) {
                logger.info("【修改用户】user={}", JSON.toJSONString(user));
                Integer[] departmentId = user.getDepartment();
                String departmentIds = "";
                for (Integer integer : departmentId) {
                    TabHaobanDepartment tabDepartment = departmentService.getByWxId(integer.toString(), wxEnterpriseId);
                    if (tabDepartment != null) {
                        departmentIds += tabDepartment.getDepartmentId() + ",";
                    }
                }
                if (StringUtils.isNotBlank(departmentIds)) {
                    departmentIds = departmentIds.substring(0, departmentIds.length() - 1);
                }
                StaffDTO staffDTO = EntityUtil.changeEntityByJSON(StaffDTO.class, staff);
                staffDTO.setWeixinPush(true);
                this.staffEdit(staffDTO, departmentIds);
            }
        }
    }

    private void staffEditDeal(StaffDTO staffDTO, String departmentIds) {
        String staffId = staffDTO.getStaffId();
        TabHaobanStaff oldStaff = staffService.selectById(staffId);
        logger.info("【员工修改】oldStaff={}", JSON.toJSONString(oldStaff));
        //1、先更新staff
        logger.info("【员工修改】staffDTO={}", JSON.toJSONString(staffDTO));
        staffService.updateByPrimaryKey(EntityUtil.changeEntityByJSON(TabHaobanStaff.class, staffDTO));
        //再去查一下
        TabHaobanStaff staff = staffService.selectById(staffId);
        String staffName = staff.getStaffName();
        List<TabHaobanStaffDepartmentRelated> list = staffDepartmentRelatedService.listStaffDepartmentByStaffId(staffId);
        Map<String, TabHaobanStaffDepartmentRelated> map = com.gic.commons.util.CollectionUtil.toMap(list, "departmentId");
        //2、该员工新增部门
        if (StringUtils.isNotBlank(departmentIds)) {
            String[] addIds = departmentIds.split(",");
            for (String addId : addIds) {
                if (!map.containsKey(addId)) {
                    //该员工新增了部门
                    StaffDepartmentRelatedDTO related = new StaffDepartmentRelatedDTO();
                    related.setStaffDepartmentRelatedId(UuidUtil.randomUUID());
                    related.setStaffId(staffId);
                    related.setClerkCode(null);
                    related.setDepartmentId(addId);
                    related.setNationCode(staff.getNationCode());
                    related.setPhoneNumber(staff.getPhoneNumber());
                    related.setStatusFlag(1);
                    related.setWxEnterpriseId(staff.getWxEnterpriseId());
                    related.setStaffName(staffName);
                    staffDepartmentRelatedService.add(related);
                } else {
                    //该员工部门没做改变(只更新手机号即可)
                    TabHaobanStaffDepartmentRelated related = map.get(addId);
                    if (StringUtils.isNotBlank(related.getPhoneNumber())) {
                        if (!related.getPhoneNumber().equals(staff.getPhoneNumber())) {
                            related.setPhoneNumber(staff.getPhoneNumber());
                            related.setNationCode(staff.getNationCode());
                            related.setUpdateTime(new Date());
                            related.setStaffName(staffName);
                            related.setWxEnterpriseId(staff.getWxEnterpriseId());
                            staffDepartmentRelatedMapper.updateByPrimaryKeySelective(related);
                        }
                    }
                }
            }
        }
        //3、该员工删除部门
        for (TabHaobanStaffDepartmentRelated staffDepartmentRelated : list) {
            if (departmentIds == null) {
                departmentIds = "";
            }
            //不包含，则说明员工删除了该部门
            if (!departmentIds.contains(staffDepartmentRelated.getDepartmentId())) {
                logger.info("【员工修改删除】tab1.getDepartmentId()={}", staffDepartmentRelated.getDepartmentId());
                StaffDepartmentRelatedDTO related = EntityUtil.changeEntityByJSON(StaffDepartmentRelatedDTO.class, staffDepartmentRelated);
                staffDepartmentRelatedService.del(related);
            }
        }
    }

    @Override
    public void staffEdit(StaffDTO staffDTO, String departmentIds) {
        this.staffEditDeal(staffDTO, departmentIds);
    }


    @Override
    public StaffDTO selectByUserIdAndEnterpriseId(String userId, String wxEnterpriseId) {
        return EntityUtil.changeEntityByJSON(StaffDTO.class, staffService.selectByUserIdAndEnterpriseId(userId, wxEnterpriseId));
    }

    @Override
    public StaffDTO getByUserIdAndReflushWhenNoPhone(String userId, String wxEnterpriseId) {
        StaffDTO staffDTO = EntityUtil.changeEntityByJSON(StaffDTO.class, staffService.selectByUserIdAndEnterpriseId(userId, wxEnterpriseId));
        return staffDTO;
    }

    @Override
    public void initWxUser(String corpid, String contactSecret, String wxEnterpriseId, Integer wxDepartmentId, String taskId) {
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId) ;
        List<UserDTO> list = this.qywxUserApiService.listSelfDepartmentUser(corpid, contactSecret, wxDepartmentId.toString(), 0 , qwDTO.getUrlHost());
        if (CollectionUtils.isNotEmpty(list)) {
            for (UserDTO dto : list) {
                try {
                    this.wxGetAdd(dto.getUserid(), wxEnterpriseId);
                } catch (Exception e) {
                    TabHaobanSyncErrorLog tab = new TabHaobanSyncErrorLog();
                    tab.setDataId(dto.getUserid());
                    tab.setDataType(0);
                    tab.setLogType(0);
                    tab.setReason(e.getMessage());
                    tab.setTaskId(taskId);
                    tab.setWxEnterpriseId(wxEnterpriseId);
                    syncErrorLogService.add(tab);
                }
            }
        }
    }

    @Override
    public List<String> listUnBindClerk(String storeId) {
        if (StringUtils.isBlank(storeId)) {
            logger.error("门店id为空");
            return Collections.emptyList();
        }
        List<String> storeIds = new ArrayList<String>();
        storeIds.add(storeId);
        List<String> clerkList = clerkService.getclerkListByStoreIds(storeIds);
        List<StaffClerkRelationDTO> staffRelationList = staffClerkRelationService.listByClerkIds(clerkList);
        if (CollectionUtils.isEmpty(staffRelationList)) {
            logger.error("无未绑定导购");
            return Collections.emptyList();
        }
        List<String> clerkIds = staffRelationList.stream().filter(s -> s.getClerkId() != null).map(s -> s.getClerkId()).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(clerkIds)) {
            logger.info("无未绑定导购id");
            return Collections.emptyList();
        }
        List<String> unBindList = clerkList.stream().filter(clerkId -> !clerkIds.contains(clerkId)).collect(Collectors.toList());
        logger.info("未绑定导购id：{}", JSON.toJSONString(unBindList));
        return unBindList;
    }

    @Override
    public String insertUserLoginLog(UserLoginLogDTO userLoginLogDTO) {
        return userLoginLogService.insertUserLoginLog(userLoginLogDTO);

    }

    @Override
    public int countByDepartmentIds(List<String> departmentIds) {
        if (departmentIds == null || departmentIds.isEmpty()) {
            return 0;
        }
        return staffDepartmentRelatedMapper.countByDepartmentIds(departmentIds);
    }

    private String changeHeaderImageUrl(String headImgUrl) {
        try {
            logger.info("图片headImgUrl：{}", headImgUrl);
            if (StringUtils.isBlank(headImgUrl)) {
                return headImgUrl;
            }
            byte[] data = ImageUtil.getImgbyte(headImgUrl);
            //上传接口替换
            //PicUploadResDTO uploadPic = qqCloudPicService.uploadPic(GlobalVar.ctxPropertiesMap.get(GlobalInfo.QQPIC_KEY_ENTERPRISE), data);
            //默认后缀为jpg,企业factoryCode取gic内部使用的factoryCode
            String suffix="jpg";
            String factoryCode="gic_inner";
            CloudFileTypeEnum cloudFileTypeEnum = CloudFileTypeEnum.IMAGE;
            CloudFileInfo cloudFileInfo =   CloudFileUtil.uploadFile(data, suffix, cloudFileTypeEnum,factoryCode, CloudFileBusinessOptEnum.HAOBAN_COMMON);
            logger.info("腾讯云万象优图返回" + JSON.toJSONString(cloudFileInfo));
            return cloudFileInfo.getOrgFileUrl();
        } catch (Exception e) {
            logger.info("上传腾讯云万象优图返回失败了:{}", e.getMessage());
            return headImgUrl;
        }
    }

    @Override
    public ServiceResponse<String> getStaffQrcode(String clerkCode, String storeId) {
        ServiceResponse<String> resp = new ServiceResponse<>();
        List<String> clerkCodes = new ArrayList<>();
        clerkCodes.add(clerkCode);
        List<ClerkDTO> list = clerkService.listClerk(storeId, clerkCodes, true);
        if (CollectionUtils.isEmpty(list)) {
            logger.info("成员不存在：{}", clerkCode);
            return null;
        }
        ClerkDTO clerkDTO = list.get(0);

        StaffClerkRelationDTO relationDTO = staffClerkRelationService.getByClerkId(clerkDTO.getClerkId());
        if (relationDTO == null) {
            logger.info("成员没有关联:{}", clerkCode);
            return null;
        }
        String staffId = relationDTO.getStaffId(); 
        TabHaobanStaff staff = this.staffMapper.selectByPrimaryKey(staffId) ;
        resp.setResult(staff.getQrCode());
        return resp;
    }

    @Override
    public List<String> listBindStaffId(String storeId) {
       return this.listBind(storeId, 1) ;
    }
    
    @Override
    public List<String> listBindClerkId(String storeId) {
        return this.listBind(storeId, 2) ;
    }
    
    private List<String> listBind(String storeId , int type) {
        List<String> userIdList = new ArrayList<String>();
        List<String> storeIds = new ArrayList<String>();
        storeIds.add(storeId);
        List<String> clerkList = clerkService.getclerkListByStoreIds(storeIds);
        List<StaffClerkRelationDTO> staffRelationList = staffClerkRelationService.listByClerkIds(clerkList);
        if (CollectionUtils.isEmpty(staffRelationList)) {
            return Collections.EMPTY_LIST;
        }
        if(type==1) {
            Map<String, StaffClerkRelationDTO> clerkIdMap = staffRelationList.stream().filter(s -> s.getClerkId() != null).collect(Collectors.toMap(StaffClerkRelationDTO::getClerkId, s -> s));
            Set<String> keySet = clerkIdMap.keySet();
            for (String clerkId : clerkList) {
                if (keySet.contains(clerkId)) {
                    userIdList.add(clerkIdMap.get(clerkId).getStaffId());
                }
            }
        }
        if(type==2) {
            userIdList = staffRelationList.stream().filter(s -> s.getClerkId() != null).map(dto->dto.getClerkId()).collect(Collectors.toList());
        }
        return userIdList;
    }
    

    @Override
    public List<StaffClerkRelationDTO> listBindRelationUserId(String storeId) {
        List<StaffClerkRelationDTO> bindList = new ArrayList<StaffClerkRelationDTO>();

        List<String> storeIds = new ArrayList<String>();
        storeIds.add(storeId);
        List<String> clerkList = clerkService.getclerkListByStoreIds(storeIds);
        List<StaffClerkRelationDTO> staffRelationList = staffClerkRelationService.listByClerkIds(clerkList);
        Map<String, StaffClerkRelationDTO> clerkIdMap = staffRelationList.stream().filter(s -> s.getClerkId() != null).collect(Collectors.toMap(StaffClerkRelationDTO::getClerkId, s -> s));
        Set<String> keySet = clerkIdMap.keySet();
        for (String clerkId : clerkList) {
            if (keySet.contains(clerkId)) {
                bindList.add(clerkIdMap.get(clerkId));
            }
        }
        return bindList;
    }

    @Override
    public boolean activeStaff(String staffId) {
        TabHaobanStaff staff = new TabHaobanStaff();
        staff.setStaffId(staffId);
        staff.setActiveFlag(1);
        staffService.updateByPrimaryKey(staff);
        return true;
    }

    @Override
    public StaffPrivacyUseLogDTO getStaffPrivacyByStaffId(String staffId) {
        return EntityUtil.changeEntity(StaffPrivacyUseLogDTO.class, staffPrivacyUseLogService.getByStaffId(staffId));
    }

    @Override
    public StaffPrivacyUseLogDTO getStaffPrivacyByUserId(String userId) {
        return EntityUtil.changeEntity(StaffPrivacyUseLogDTO.class, staffPrivacyUseLogService.getByUserId(userId));
    }

    @Override
    public Page<StaffDTO> listUserIdByWxEnterpriseId(String wxEnterpriseId, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<TabHaobanStaff> tabHaobanStaffs = staffMapper.listByWxEnterpriseId(wxEnterpriseId);
        return PageUtil.changePageHelperToCurrentPage(new PageInfo<>(tabHaobanStaffs), StaffDTO.class);
    }

    @Override
    public int updateOpenUserIdsByUserId(String wxEnterpriseId, String wxUserId, String wxOpenUseId) {
        return staffService.updateOpenUserIdsByUserId(wxEnterpriseId, wxUserId, wxOpenUseId);
    }

    @Override
    public int updateOpenIdByStaffId(String staffId, String openId) {
        return staffMapper.updateOpenIdByStaffId(staffId, openId);
    }

    @Override
    public int getSensitiveStatus(String staffId) {
        String qrCode = staffMapper.getQrCodeByStaffId(staffId);
        if(StringUtils.isNotBlank(qrCode))
            return 1;
        return 0;
    }


    @Override
    public int updateQrCodeByUserId(String userId, String qrCode) {
        return staffMapper.updateQrCodeByUserId(userId,qrCode);
    }

    @Override
    public int updateQrCodeByStaffId(String staffId, String qrCode) {
        return staffMapper.updateQrCodeByStaffId(staffId, qrCode);
    }

    @Override
    public StaffQrCodeDTO getQrCodeByClerkId(String clerkId) {
        StaffClerkRelationDTO staffClerkRelationDTO = staffClerkRelationService.getByClerkId(clerkId);
        if (staffClerkRelationDTO == null) {
            return null;
        }
        String staffId = staffClerkRelationDTO.getStaffId();
        String wxEnterpriseId = staffClerkRelationDTO.getWxEnterpriseId();

        SecretSettingDTO secretSetting = secretSettingService.getSecretSetting(wxEnterpriseId, SecretTypeEnum.CUSTOMIZED_APP.getVal());
        if (null == secretSetting || secretSetting.getCheckFlag() == 0) {
            logger.info("没有配置secret：wxEnterpriseId:{}", wxEnterpriseId);
            return null;
        }
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        if (qwDTO == null) {
            logger.info("企业不存在：wxEnterpriseId:{}", wxEnterpriseId);
            return null;
        }
        TabHaobanStaff staff = staffService.selectById(staffId);
        if (staff == null) {
            logger.info("员工不存在：staffId:{}", staffId);
            return null;
        }
        StaffQrCodeDTO staffQrCodeDTO = new StaffQrCodeDTO();
        staffQrCodeDTO.setStaffId(staffId);
        staffQrCodeDTO.setHeadImg(staff.getHeadImg());
        staffQrCodeDTO.setStaffName(staff.getStaffName());
        staffQrCodeDTO.setNickName(staff.getNickName());
        staffQrCodeDTO.setPhoneNumber(staff.getPhoneNumber());
        staffQrCodeDTO.setClerkCode(staffClerkRelationDTO.getClerkCode());

        String qrCode = staff.getQrCode();
        staffQrCodeDTO.setQrCode(qrCode);
        if (StringUtils.isNotBlank(qrCode)) {
            return staffQrCodeDTO;
        }
        return staffQrCodeDTO;
    }

    @Override
    public List<String> isGicSuper(String clerkId, String wxEnterpriseId) {
        ClerkDTO clerkDTO = clerkService.getClerkByClerkId(clerkId);
        if (clerkDTO == null) {
            logger.info("导购不存在：clerkId:{},无门店", clerkId);
            return Collections.emptyList();
        }
        List<String> gicStoreIds = getStoreIdList(clerkDTO);
        return gicStoreIds;
    }

    @Override
    public List<String> getHaoBanStoreIdsRolesByClerkId(String clerkId, String wxEnterpriseId) {
        logger.info("查询导购权限，clerkId={},wxEnterpriseId={}", clerkId, wxEnterpriseId);
        if (StringUtils.isAnyBlank(clerkId, wxEnterpriseId)) {
            logger.info("参数为空clerkId={},wxEnterpriseId={}", clerkId, wxEnterpriseId);
            return Collections.emptyList();
        }
        String cacheKey = "hb:clerk:store:" + clerkId + wxEnterpriseId;
        Object cache = RedisUtil.getCache(cacheKey);
        if (cache != null) {
            List<String> storeList = (List<String>) cache;
            logger.info("从缓存中获取key={},store数量:{}", cacheKey, storeList.size());
            return storeList;
        }
        ClerkDTO clerkDTO = clerkService.getClerkByClerkId(clerkId);
        if (clerkDTO == null) {
            logger.info("导购不存在：clerkId:{},无门店", clerkId);
            return Collections.emptyList();
        }
        String enterpriseId = clerkDTO.getEnterpriseId();
        List<String> enterpriseIdStoreIds = storeRangeService.listStoreIdByWxEnterpriseId(wxEnterpriseId, enterpriseId);
        if (CollectionUtils.isEmpty(enterpriseIdStoreIds)) {
            logger.info("无好办门店,eid={}", enterpriseId);
            return Collections.emptyList();
        }
        logger.info("好办门店数量={}", enterpriseIdStoreIds.size());
        List<String> gicStoreIds = getStoreIdList(clerkDTO);
        if (CollectionUtils.isEmpty(gicStoreIds)) {
            logger.info("无gic门店为空");
            return Collections.emptyList();
        }
        if (gicStoreIds.contains("-1")) {
            logger.info("gic超管，clerkId:{}", clerkId);
            List<String> storeGroupIds = storeRangeService.listStoreGroupIdByWxEnterpriseId(wxEnterpriseId, enterpriseId);
            if (CollectionUtils.isEmpty(storeGroupIds)) {
                logger.info("好办门店分组id为空");
                return Collections.emptyList();
            }
            String[] array = storeGroupIds.toArray(new String[0]);
            List<StoreGroupDTO> storeGroupDTOS = storeGroupService.listStoreGroup(array, enterpriseId);
            List<String> parentGroupIds = storeGroupDTOS.stream().map(StoreGroupDTO::getParentGroupId).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(parentGroupIds) && parentGroupIds.contains("0")) {
                logger.info("gic是超管，企微包含所有门店，clerkId:{}", clerkId);
                enterpriseIdStoreIds = Collections.singletonList("-1");
            }
            RedisUtil.setCache(cacheKey, enterpriseIdStoreIds, 10L, TimeUnit.MINUTES);
            return enterpriseIdStoreIds;
        }
        logger.info("gic门店数量={}", gicStoreIds.size());
        //取交集
        List<String> storeList = RolesListUtils.mergeList(enterpriseIdStoreIds, gicStoreIds);
        logger.info("clerkId={},门店交集数量={}", clerkId, storeList.size());
        RedisUtil.setCache(cacheKey, storeList, 10L, TimeUnit.MINUTES);
        return storeList;
    }

    @Override
    public List<String> getHaoBanStoreRolesByStoreWidgetId(String storeWidgetId, String wxEnterpriseId, String enterpriseId) {
        return getStoreWidgetIdStoreIds(storeWidgetId, enterpriseId);
    }

    @Override
    public boolean isFlagByStoreIdAndEnterpriseId(String storeId, String enterpriseId, String wxEnterpriseId) {
        return storeRangeService.isFlagByStoreId(storeId, wxEnterpriseId, enterpriseId);
    }

//    @Override
//    public boolean isSuperAdmin(String clerkId) {
//        ClerkDTO clerkDTO = clerkService.getClerkByClerkId(clerkId);
//        if (clerkDTO == null) {
//            return false;
//        }
//        Integer superAdmin = clerkDTO.getSuperAdmin();
//        return superAdmin != null && superAdmin == 1;
//    }

//    @Override
//    public List<String> getHaoBanStoreRolesByEnterpriseId(String enterpriseId, String wxEnterpriseId) {
//        return storeRangeService.listStoreIdByWxEnterpriseId(wxEnterpriseId, enterpriseId);
//    }

    @Override
    public StoreRoleDTO getCountHaoBanStoreIdsByClerkId(String clerkId, String wxEnterpriseId) {
        StoreRoleDTO storeRoleDTO = new StoreRoleDTO();
        ClerkDTO clerkDTO = clerkService.getClerkByClerkIdNoStatus(clerkId);
        if (clerkDTO == null) {
            storeRoleDTO.setStoreCount(0);
            return storeRoleDTO;
        }
        Integer clerkType = clerkDTO.getClerkType();
        if (clerkType != null && clerkType != 2 && clerkType != 3) {
            storeRoleDTO.setStoreCount(1);
            storeRoleDTO.setStoreId(clerkDTO.getStoreId());
            return storeRoleDTO;
        }
        List<String> storeIds = getHaoBanStoreIdsRolesByClerkId(clerkId, wxEnterpriseId);
        if (CollectionUtils.isEmpty(storeIds)) {
            storeRoleDTO.setStoreCount(0);
            return storeRoleDTO;
        }
        if (storeIds.contains("-1")) {
            logger.info("该导购为所有门店,clerkId={}",clerkId);
            int storeCount = 0 ;
            String storeId = null ;
            Page<Object> pageParam = new Page<Object>();
            pageParam.setCurrentPage(1);
            pageParam.setPageSize(1);
            if(clerkType == 2) {
                String storeWidgetId = this.powerService.getStoreWidgetId(null, clerkId);
                if(null != storeWidgetId) {
                    Page<StoreDTO> page = storeWidgetService.getStoreWidgetStore(storeWidgetId, null, clerkDTO.getEnterpriseId(), pageParam, null,null);
                    storeId = page.getResult().get(0).getStoreId();
                    storeCount = page.getTotalCount();
                }
            }else if(clerkType == 3) {
                StoreSearchDTO searchDTO = new StoreSearchDTO() ;
                searchDTO.setEnterpriseId(clerkDTO.getEnterpriseId());
                Page<StoreDTO> page = this.storeService.storeListPage(pageParam,searchDTO) ;
                storeId = page.getResult().get(0).getStoreId();
                storeCount = page.getTotalCount();
            }
            storeRoleDTO.setStoreId(storeId);
            storeRoleDTO.setStoreCount(storeCount);
            return storeRoleDTO;
        }
        int size = storeIds.size();
        storeRoleDTO.setStoreCount(size);
        if (size >= 1) {
            storeRoleDTO.setStoreId(storeIds.get(0));
        }
        return storeRoleDTO;
    }

    /**
     * 门店筛选器id企业端获取gic门店id列表
     */
    private List<String> getStoreIdList(ClerkDTO clerkDTO) {
        String clerkId = clerkDTO.getClerkId();
        Integer superAdmin = clerkDTO.getSuperAdmin();
        if (superAdmin != null && superAdmin == 1) {
            logger.info("gic超管，clerkId：{}", clerkId);
            return Collections.singletonList("-1");
        }
        String enterpriseId = clerkDTO.getEnterpriseId();
        EnterpriseSettingDTO enterpriseSetting = enterpriseService.getEnterpriseSettingByEnterpriseId(enterpriseId);
        if (enterpriseSetting.getEnableAccessControl() != null && enterpriseSetting.getEnableAccessControl() == 1) {
            String storeWidgetId = this.powerService.getStoreWidgetId(null, clerkId);
            if (StringUtils.isBlank(storeWidgetId)) {
                logger.info("导购无门店权限,门店组件id is null");
                return Collections.emptyList();
            }
            StoreWidgetDTO storeWidgetDTO = this.storeWidgetService.getStoreWidgetBykey(storeWidgetId);
            if (storeWidgetDTO == null) {
                logger.info("导购门店权限查不到,storeWidgetId={}",storeWidgetId);
                return Collections.emptyList();
            }
            Integer selectType = storeWidgetDTO.getSelectType();
            if (selectType != null && selectType == 0) {
                logger.info("gic超管所有门店,clerkId：{}", clerkId);
                return Collections.singletonList("-1");
            }
            return getStoreWidgetIdStoreIds(storeWidgetId, enterpriseId);
        } else {
            logger.info("无开启权限 ,所有门店,clerkId={}", clerkId);
            return Collections.singletonList("-1");
        }
    }

    /**
     * 获取门店筛选器门店ids
     */
    private List<String> getStoreWidgetIdStoreIds(String storeWidgetId, String enterpriseId) {
        // 门店id列表
        List<String> storeIdList = storeWidgetService.getStoreWidgetStore(storeWidgetId, enterpriseId, null, null, 0);
        if (CollectionUtils.isEmpty(storeIdList)) {
            return Collections.emptyList();
        }
        logger.info("门店筛选器查询结果数量:{}", storeIdList.size());
        return storeIdList;
    }

    @Override
    public boolean isManager(String clerkId) {
        logger.info("查询是否店长：{}", clerkId);
        ClerkDTO clerkDTO = clerkService.getClerkByClerkId(clerkId);
        if (clerkDTO != null) {
            Integer clerkType = clerkDTO.getClerkType();
            if (clerkType == 1 || clerkType == 2 || clerkType == 3) {
                return true;
            }
        }
        return false;
    }
    
    @Override
    public com.gic.api.base.commons.ServiceResponse<Boolean> isEnterpriseManager(String clerkId) {
        ClerkDTO clerkDTO = clerkService.getClerkByClerkId(clerkId);
        if (clerkDTO != null) {
            Integer clerkType = clerkDTO.getClerkType();
            if (clerkType == 2) {
                return com.gic.api.base.commons.ServiceResponse.success(true);
            }
        }
        return com.gic.api.base.commons.ServiceResponse.success(false);
    }

    @Override
    public List<StaffDTO> listBindStoreIds(List<String> storeIds, String wxEnterpriseId) {
        return staffMapper.listBindStoreIds(storeIds,wxEnterpriseId);
    }

    @Override
    public com.gic.api.base.commons.ServiceResponse<TransferActiveCodeDTO> batchTransferLicense(List<TransferActiveCodeQDTO> transferActiveCodeQOList,String wxEnterpriseId) {
        TransferActiveCodeDTO result = new TransferActiveCodeDTO();
        if (CollUtil.isEmpty(transferActiveCodeQOList)){
            return com.gic.api.base.commons.ServiceResponse.failure("-9999"," 传入的参数有误！",result);
        }
        //拼接staffIdList
        List<String> staffIds = new ArrayList<>();
        transferActiveCodeQOList.stream().forEach(a->{
            staffIds.add(a.getHandoverStaffId());
            staffIds.add(a.getTakeoverStaffId());
        });
        List<TabHaobanStaff> tabHaobanStaffs = staffMapper.listByStaffIdList(staffIds);
        if (CollUtil.isEmpty(tabHaobanStaffs)){
            return com.gic.api.base.commons.ServiceResponse.failure("-9999","通讯录成员不存在！",result);
        }
        WxEnterpriseDTO wxEnterpriseDTO = this.wxEnterpriseService.selectById(wxEnterpriseId);
        String openCorpid = wxEnterpriseDTO.getOpenCorpid();
        String serviceCorpid = config.getCorpid();
        //拼接转移参数
        Map<String, TabHaobanStaff> collect = tabHaobanStaffs.stream().collect(Collectors.toMap(TabHaobanStaff::getStaffId, a -> a));
        Map<String, String> map = tabHaobanStaffs.stream().collect(Collectors.toMap(TabHaobanStaff::getWxOpenUseId, a -> a.getStaffId()));

        List<AccountTransferUserDTO> accountTransferUserDTOList = new ArrayList<>();
        transferActiveCodeQOList.stream().forEach(a->{
            AccountTransferUserDTO accountTransferUserDTO = new AccountTransferUserDTO();
            TabHaobanStaff handoverStaff = collect.get(a.getHandoverStaffId());
            TabHaobanStaff takeOverStaff = collect.get(a.getTakeoverStaffId());
            accountTransferUserDTO.setHandover_userid(handoverStaff.getWxOpenUseId());
            accountTransferUserDTO.setTakeover_userid(takeOverStaff.getWxOpenUseId());
            accountTransferUserDTOList.add(accountTransferUserDTO);
        });
        com.gic.api.base.commons.ServiceResponse<List<AccountTransferUserDTO>> listServiceResponse = qywxOrderApiService.batchTransferLicense(serviceCorpid, openCorpid, accountTransferUserDTOList);
        logger.info("转移成员返回结果：{}",JSONObject.toJSONString(listServiceResponse));
        int successNum=0,failedNum=0;
        List<Map<String,String>> failedList =new ArrayList<>();
        List<Map<String,String>> successList =new ArrayList<>();
        if (Constant.SUCCESS.equals(listServiceResponse.getCode())){
            List<AccountTransferUserDTO> resultList = listServiceResponse.getResult();
            result.setTotalNum(resultList.size());
            for (AccountTransferUserDTO dto : resultList) {
                if(0==dto.getErrcode()){
                    //企微转移成功，好办staff表对应更新
                    successNum++;
                    TabHaobanStaff handoverStaff = collect.get(map.get(dto.getHandover_userid()));
                    TabHaobanStaff takeOverStaff = collect.get(map.get(dto.getTakeover_userid()));
                    //置空转移成员的许可信息
                    staffMapper.updateStaffInfoByStaffId(handoverStaff.getStaffId(),null,null,null);
                    //更新接收成员的许可信息
                    staffMapper.updateStaffInfoByStaffId(takeOverStaff.getStaffId(),handoverStaff.getActiveTime(),handoverStaff.getExpireTime(), handoverStaff.getActiveCode());
                    //记录转移成功明细
                    Map<String,String> successMap = new HashMap<>(8);
                    successMap.put("handoverStaffName",handoverStaff.getStaffName());
                    successMap.put("handoverStaffPhone",handoverStaff.getPhoneNumber());
                    successMap.put("takeoverStaffName",takeOverStaff.getStaffName());
                    successMap.put("takeoverStaffPhone",takeOverStaff.getPhoneNumber());
                    successList.add(successMap);
                    //更新成员群列表 todo
                    groupChatService.initStaffGroupChat(takeOverStaff.getStaffId());

                }else{
                    //企微转移失败,记录失败明细
                    failedNum++;
                    TabHaobanStaff handoverStaff = collect.get(map.get(dto.getHandover_userid()));
                    TabHaobanStaff takeOverStaff = collect.get(map.get(dto.getTakeover_userid()));
                    Map<String,String> stringMap = new HashMap<>(8);
                    stringMap.put("handoverStaffName",handoverStaff.getStaffName());
                    stringMap.put("takeoverStaffName",takeOverStaff.getStaffName());
                    stringMap.put("errorCode",String.valueOf(dto.getErrcode()));
                    QywxErrCode code = QywxErrCode.getValue(String.valueOf(dto.getErrcode()));
                    logger.info("错误code码：{}",JSON.toJSONString(code));
                    if (null != code){
                        stringMap.put("errorMessage",code.getMsg());
                    }
                    failedList.add(stringMap);
                }
            }
            result.setSuccessNum(successNum);
            result.setFailedNum(failedNum);
            result.setFailedList(failedList);
            result.setSuccessList(successList);
            return com.gic.api.base.commons.ServiceResponse.success(result);
        }
        //企业微信接口调用失败，记录错误
        result.setTotalNum(accountTransferUserDTOList.size());
        result.setSuccessNum(0);
        result.setFailedNum(accountTransferUserDTOList.size());
        accountTransferUserDTOList.stream().forEach(a->{
            TabHaobanStaff handoverStaff = collect.get(map.get(a.getHandover_userid()));
            TabHaobanStaff takeOverStaff = collect.get(map.get(a.getTakeover_userid()));
            Map<String,String> stringMap = new HashMap<>(8);
            stringMap.put("handoverStaffName",handoverStaff.getStaffName());
            stringMap.put("takeoverStaffName",takeOverStaff.getStaffName());
            stringMap.put("errorCode",listServiceResponse.getCode());
            failedList.add(stringMap);
        });
        result.setFailedList(failedList);
        return com.gic.api.base.commons.ServiceResponse.failure(listServiceResponse.getCode(),listServiceResponse.getMessage(),result);
    }

    @Override
    public com.gic.api.base.commons.ServiceResponse<Boolean> autoActivateCallBack(String params) {
        logger.info("接收企业微信自动激活回调通知：{}",JSON.toJSONString(params));
        if (StrUtil.isBlank(params)) {
            return com.gic.api.base.commons.ServiceResponse.success(false);
        }
        //1、解析参数 2、刷新企业微信群列表 3、更新成员信息 4、实时统计许可总数
        JSONObject object = JSONObject.parseObject(params, JSONObject.class);
        String infoType = object.getString("infoType");
        String authCorpId = object.getString("authCorpId");
        String timeStamp = object.getString("timeStamp");
        Object accountList = object.get("accountList");
        JSONObject obj = JSONObject.parseObject(JSON.toJSONString(accountList), JSONObject.class);
        String activeCode = obj.getString("ActiveCode");
        String expireTime = obj.getString("ExpireTime");
        String userId = obj.getString("UserId");

        //将秒级时间戳转换位Date类型
        SimpleDateFormat formatter = new SimpleDateFormat(DateUtil.FORMAT_DATETIME_19);
        String date_time = formatter.format(new Date(Long.valueOf(timeStamp) * 1000L));
        Date timeStampDate = DateUtil.strToDate(date_time, DateUtil.FORMAT_DATETIME_19);

        String date_time1 = formatter.format(new Date(Long.valueOf(expireTime) * 1000L));
        Date expireTimeDate = DateUtil.strToDate(date_time1, DateUtil.FORMAT_DATETIME_19);
        if ("auto_activate".equals(infoType)){
            // 成员许可自动激活回调通知
            TabHaobanWxEnterprise wxEnterprise = this.wxEnterpriseService.getEnterpriseBycorpId(authCorpId);
            if (wxEnterprise==null){
                logger.info("微信企业id—>{}不存在",authCorpId);
                return com.gic.api.base.commons.ServiceResponse.failure("-9999","微信企业id不存在!");
            }
            TabHaobanStaff staff = staffService.selectByUserIdAndEnterpriseId(userId, wxEnterprise.getWxEnterpriseId());
            if (null == staff){
                logger.info("成员userid—>{}不存在",userId);
                return com.gic.api.base.commons.ServiceResponse.failure("-9999","成员userid不存在!");
            }
            String staffId = staff.getStaffId();

            StaffActiveDataDTO activeDataDTO = wxEnterpriseActiveDataService.getWxEnterpriseActiveDataByWxEnterpriseId(wxEnterprise.getWxEnterpriseId());
            if (null == activeDataDTO){
                logger.info("查询不到企业微信id->{}的许可账号统计信息！",wxEnterprise.getWxEnterpriseId());
            }else {
                //需要区分激活码，待转移状态的激活码不需要处理
                TabHaobanStaff haobanStaff = staffMapper.getNumByActiveCode(wxEnterprise.getWxEnterpriseId(), activeCode);
                if (null == haobanStaff){
                    //已使用的加1，已激活的加1，未激活的减1
                    Integer used = activeDataDTO.getUsed();
                    Integer inactive = activeDataDTO.getInactive();
                    Integer activated = activeDataDTO.getActivated();
                    used++;
                    activated++;
                    if(null != inactive && inactive > 0){
                        inactive--;
                    }
                    activeDataDTO.setUsed(used);
                    activeDataDTO.setInactive(inactive);
                    activeDataDTO.setActivated(activated);
                    wxEnterpriseActiveDataService.updateByStaffActiveDataDTO(activeDataDTO);
                }else {
                    //判断是否是其它占用的许可被当天激活
                    Date delTime = haobanStaff.getDelTime();
                    Date now = new Date();
                    int days = DateUtil.daysBetween(delTime, now);
                    if(days == 0){
                        staffMapper.updateOccupyFlagByStaffId(haobanStaff.getStaffId());
                    }
                }
            }
            staffMapper.updateActiveStatusById(staffId,timeStampDate,expireTimeDate,activeCode);
            groupChatService.initStaffGroupChat(staffId);
            //更新好办激活码许可表
            haobanQywxFeeOrderAccountService.updateByActiveCode(wxEnterprise.getWxEnterpriseId(),activeCode);

        }
        return com.gic.api.base.commons.ServiceResponse.success(true);
    }

    @Override
    public com.gic.api.base.commons.ServiceResponse<List<WxEnterpriseRelatedDTO>> getWxEnterpriseRelatedList(String wxEnterpriseId) {
        List<TabHaobanWxEnterpriseRelated> list = wxEnterpriseRelatedService.getByWxEnterpriseId(wxEnterpriseId);
        return com.gic.api.base.commons.ServiceResponse.success(com.gic.haoban.common.utils.EntityUtil.changeEntityListByJSON(WxEnterpriseRelatedDTO.class, list));
    }

    @Override
    public com.gic.api.base.commons.ServiceResponse<Boolean> updateExternalUserId(String params) {
        if(StrUtil.isBlank(params)){
            return com.gic.api.base.commons.ServiceResponse.failure("-9999","参数不能为空");
        }
        logger.info("定时刷新成员外部联系人开始，id参数：{}",params);
        List<String> wxEnterpriseIdList = Arrays.asList(params.split(","));
        String taskName = "刷新企业微信好友(定时处理)";
        for (String wxEnterpriseId: wxEnterpriseIdList){
            List<TabHaobanWxEnterpriseRelated> list = wxEnterpriseRelatedService.getByWxEnterpriseId(wxEnterpriseId);
            if (CollUtil.isEmpty(list)){
                logger.info("该企业微信没有和gic绑定：{}",wxEnterpriseId);
                continue;
            }
            //查询企业微信下面所有的品牌id
            List<String> enterpriseIdList = list.stream().map(dto -> dto.getEnterpriseId()).collect(Collectors.toList());
            //查询外部联系人id为空的成员id
            List<String> staffIdList = externalClerkRelatedService.listByWxEnterpriseId(wxEnterpriseId, enterpriseIdList);
            if (CollUtil.isNotEmpty(staffIdList)){
                //去重
                List<String> collect = staffIdList.stream().distinct().collect(Collectors.toList());
                logger.info("需要刷新好友的企业微信id：{}，staff成员列表：{}",wxEnterpriseId,JSON.toJSONString(collect));
                for (String staffId : staffIdList){
                    String taskId = dealSyncOperationApiService.createWxFriendTaskSingle(wxEnterpriseId, taskName, staffId,
                            "刷新企业微信好友(定时任务处理)", SyncTaskTypeEnum.FRIEND_SINGLE.getType());
                    if (StringUtils.isNotBlank(taskId)) {
                        dealSyncOperationApiService.dealWxFriendClerkSingle(taskId, staffId, staffId, wxEnterpriseId);
                        //上述刷新企业好友走的是新增数据，所以需要额外去删除外部联系人id为空的数据
                        externalClerkRelatedService.deleteByWxEnterpriseId(wxEnterpriseId,enterpriseIdList);
                    }
                }
            }
        }
        logger.info("定时刷新成员外部联系人结束");
        return com.gic.api.base.commons.ServiceResponse.success(true);
    }

    @Override
    public com.gic.api.base.commons.ServiceResponse<Boolean> syncQywxStaffList(String params) {
        logger.info("定时刷新企业微信通讯录列表信息");
        //查询所有未配置回调地址的自建应用
        List<String> wxEnterpriseList = wxEnterpriseService.listWxEnterpriseByCallbackFlag(0);
        if(CollUtil.isNotEmpty(wxEnterpriseList)){
            for (String wxEnterpriseId : wxEnterpriseList){
                logger.info("开始刷新：{}",wxEnterpriseId);
                String taskId = dealSyncOperationApiService.createQywxTask(wxEnterpriseId, "后门同步企业微信架构", "定时同步处理", "后门同步企业微信架构");
                if (StringUtils.isBlank(taskId)) {
                    logger.info("企业微信id：{}，创建异步任务异常！",wxEnterpriseId);
                    return com.gic.api.base.commons.ServiceResponse.failure("-9999","创建异步任务失败！");
                }
                String ret = dealSyncOperationApiService.dealQywxDepartment(taskId, wxEnterpriseId);
                if (null != ret) {
                    logger.info("企业微信id：{}，异常信息返回：{}",wxEnterpriseId,ret);
                }
            }
        }
        return null;
    }

    @Override
    public com.gic.api.base.commons.ServiceResponse<StaffActiveAllocationDTO> staffActiveAllocation(String wxEnterpriseId, String staffIds) {

        StaffActiveAllocationDTO result = new StaffActiveAllocationDTO();
        if (StrUtil.isBlank(staffIds)){
            return com.gic.api.base.commons.ServiceResponse.failure("-9999","参数不能为空");
        }
        WxEnterpriseDTO wxEnterpriseDTO = wxEnterpriseService.selectById(wxEnterpriseId);
        if (wxEnterpriseDTO == null) {
            return com.gic.api.base.commons.ServiceResponse.failure("-9999", "企业微信不存在！！");
        }
        String openCorpid = wxEnterpriseDTO.getOpenCorpid();
        String serviceCorpid = config.getCorpid();
        List<String> staffIdList = Arrays.asList(staffIds.split(","));
        List<TabHaobanStaff> haobanStaffs = staffMapper.listByIds(staffIdList);
        List<TabHaobanQywxFeeOrderAccount> accounts = haobanQywxFeeOrderAccountService.selectByWxEnterpriseId(wxEnterpriseId);
        if ( CollUtil.isEmpty(accounts) || accounts.size() < haobanStaffs.size()){
            return com.gic.api.base.commons.ServiceResponse.failure("-9999", "剩余可用许可数量小于激活成员数量");
        }
        if (CollUtil.isNotEmpty(haobanStaffs)){
            int num = 0;
            String errMessage = null;
            for (int i = 0;i<haobanStaffs.size();i++){
                String activeCode = accounts.get(i).getActiveCode();
                String orderId = accounts.get(i).getOrderId();
                String staffId = haobanStaffs.get(i).getStaffId();
                JSONObject object = new JSONObject();
                object.put("active_code",accounts.get(i).getActiveCode());
                object.put("corpid",openCorpid);
                String wxUserId = haobanStaffs.get(i).getWxUserId();
                if (StrUtil.isBlank(wxUserId)){
                    wxUserId = haobanStaffs.get(i).getWxOpenUseId();
                }
                object.put("userid",wxUserId);
                com.gic.api.base.commons.ServiceResponse<QywxResponseDTO> response = qywxOrderApiService.activeAccount(serviceCorpid, JSON.toJSONString(object));
                if(!response.isSuccess()){
                    num++;
                    errMessage = "许可账号分配失败，复制链接查看失败原因：https://developer.work.weixin.qq.com/devtool/query?e="+response.getCode();
                }else {
                    //手动分配成功需要实时更新许可激活码状态
                    StaffActiveDataDTO activeDataDTO = wxEnterpriseActiveDataService.getWxEnterpriseActiveDataByWxEnterpriseId(wxEnterpriseId);
                    if (null == activeDataDTO){
                        logger.info("查询不到企业微信id->{}的许可账号统计信息！",wxEnterpriseId);
                    }else {
                        //需要区分激活码，待转移状态的激活码不需要处理
                        TabHaobanStaff haobanStaff = staffMapper.getNumByActiveCode(wxEnterpriseId, activeCode);
                        if (null == haobanStaff){
                            //已使用的加1，已激活的加1，未激活的减1
                            Integer used = activeDataDTO.getUsed();
                            Integer inactive = activeDataDTO.getInactive();
                            Integer activated = activeDataDTO.getActivated();
                            used++;
                            activated++;
                            if(null != inactive && inactive > 0){
                                inactive--;
                            }
                            activeDataDTO.setUsed(used);
                            activeDataDTO.setInactive(inactive);
                            activeDataDTO.setActivated(activated);
                            wxEnterpriseActiveDataService.updateByStaffActiveDataDTO(activeDataDTO);
                        }else {
                            //判断是否是其它占用的许可被当天激活
                            Date delTime = haobanStaff.getDelTime();
                            Date now = new Date();
                            int days = DateUtil.daysBetween(delTime, now);
                            if(days == 0){
                                staffMapper.updateOccupyFlagByStaffId(haobanStaff.getStaffId());
                            }
                        }
                    }
                    //根据订单id，查询订单详情，获取购买的时长，当前激活时间加上时长为过期时间
                    TabHaobanQywxFeeOrder tabHaobanQywxFeeOrder = haobanQywxFeeOrderService.selectByOrderId(wxEnterpriseId, orderId);
                    Integer months = tabHaobanQywxFeeOrder.getMonths();
                    Date expireTime = null;
                    if (null != months){
                        //转换成天数
                        months = months * 31;
                        expireTime = DateUtil.addDay(new Date(),months);
                    }
                    staffMapper.updateActiveStatusById(staffId,new Date(),expireTime,activeCode);
                    //更新好办激活码许可表
                    haobanQywxFeeOrderAccountService.updateByActiveCode(wxEnterpriseId,activeCode);
                }
            }
            result.setNums(num);
            result.setErrMessage(errMessage);
            return com.gic.api.base.commons.ServiceResponse.success(result);
        }
        return com.gic.api.base.commons.ServiceResponse.failure("-9999","成员不存在");
    }

    @Override
    public void updateStaffHead(String wxEnterpriseId ,String staffId, String headUrl) {
        this.staffService.updateStaffHead(wxEnterpriseId,staffId,headUrl) ;
    }

    @Override
    public Page<StaffDTO> listByParams(String enterpriseId, String params , String wxEnterpriseId , BasePageInfo pageInfo) {
        PageHelper.startPage(pageInfo.getPageNum(), pageInfo.getPageSize());
        List<TabHaobanWxEnterprise> list = this.wxEnterpriseRelatedService.listByEnterpriseId(enterpriseId) ;
        List<String> wxEnterpriseIdList = list.stream().map(o->o.getWxEnterpriseId()).collect(Collectors.toList());
        if(StringUtils.isNotBlank(params)) {
            params = "%"+params+"%" ;
        }
        List<StaffDTO> pageList = this.staffMapper.listByParams(wxEnterpriseIdList , params) ;
        return PageUtil.changePageHelperToCurrentPage(new PageInfo<>(pageList), StaffDTO.class);
    }
}
