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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import com.gic.enterprise.api.dto.StoreDTO;
import com.gic.enterprise.api.service.StoreService;
import com.gic.haoban.manage.api.dto.chat.GroupChatUserNoticeDTO;
import com.gic.haoban.manage.service.dao.mapper.WxEnterpriseMapper;
import com.gic.haoban.manage.service.service.*;
import com.gic.haoban.manage.service.service.chat.GroupChatActivityInviteLogService;
import com.gic.haoban.manage.service.util.ExecuteServiceUtil;
import com.gic.member.ext.api.enums.growth.GrowthRuleEnum;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.esotericsoftware.minlog.Log;
import com.gic.api.base.commons.BasePageInfo;
import com.gic.api.base.commons.Page;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.commons.util.DateUtil;
import com.gic.commons.util.EntityUtil;
import com.gic.commons.util.GICMQClientUtil;
import com.gic.commons.util.PageHelperUtils;
import com.gic.commons.util.UniqueIdUtils;
import com.gic.haoban.base.api.common.Constant;
import com.gic.haoban.manage.api.dto.SecretSettingDTO;
import com.gic.haoban.manage.api.dto.StaffClerkRelationDTO;
import com.gic.haoban.manage.api.dto.WxEnterpriseQwDTO;
import com.gic.haoban.manage.api.dto.chat.GroupChatDTO;
import com.gic.haoban.manage.api.dto.chat.GroupChatOwnerDTO;
import com.gic.haoban.manage.api.dto.chat.GroupChatOwnerHistoryDTO;
import com.gic.haoban.manage.api.dto.qdto.chat.GroupChatSearchQDTO;
import com.gic.haoban.manage.api.dto.qdto.chat.OwnerSearchQDTO;
import com.gic.haoban.manage.api.enums.SecretTypeEnum;
import com.gic.haoban.manage.service.config.Config;
import com.gic.haoban.manage.service.dao.mapper.StaffMapper;
import com.gic.haoban.manage.service.dao.mapper.TabHaobanExternalClerkRelatedMapper;
import com.gic.haoban.manage.service.dao.mapper.chat.ChatNoticeMapper;
import com.gic.haoban.manage.service.dao.mapper.chat.GroupChatHmRelationMapper;
import com.gic.haoban.manage.service.dao.mapper.chat.GroupChatInitMapper;
import com.gic.haoban.manage.service.dao.mapper.chat.GroupChatMapper;
import com.gic.haoban.manage.service.dao.mapper.chat.GroupChatOwnerHistoryMapper;
import com.gic.haoban.manage.service.dao.mapper.chat.GroupChatOwnerMapper;
import com.gic.haoban.manage.service.dao.mapper.chat.GroupChatUserMapper;
import com.gic.haoban.manage.service.entity.TabHaobanDepartment;
import com.gic.haoban.manage.service.entity.TabHaobanExternalClerkRelated;
import com.gic.haoban.manage.service.entity.TabHaobanStaff;
import com.gic.haoban.manage.service.entity.TabHaobanWxEnterprise;
import com.gic.haoban.manage.service.entity.TabHaobanWxEnterpriseRelated;
import com.gic.haoban.manage.service.entity.chat.TabChatNotice;
import com.gic.haoban.manage.service.entity.chat.TabGroupChat;
import com.gic.haoban.manage.service.entity.chat.TabGroupChatHmRelation;
import com.gic.haoban.manage.service.entity.chat.TabGroupChatInit;
import com.gic.haoban.manage.service.entity.chat.TabGroupChatOwner;
import com.gic.haoban.manage.service.entity.chat.TabGroupChatOwnerHistory;
import com.gic.haoban.manage.service.entity.chat.TabGroupChatUser;
import com.gic.haoban.manage.service.pojo.bo.chat.GroupChatBO;
import com.gic.haoban.manage.service.service.chat.GroupChatHmService;
import com.gic.haoban.manage.service.service.chat.GroupChatService;
import com.gic.member.api.dto.MemberDTO;
import com.gic.member.api.service.MemberService;
import com.gic.mq.sdk.GicMQClient;
import com.gic.redis.data.util.RedisUtil;
import com.gic.wechat.api.dto.qywx.chat.FailChatListDTO;
import com.gic.wechat.api.dto.qywx.chat.GroupChatDetailDTO;
import com.gic.wechat.api.dto.qywx.chat.GroupChatDetailMemberDTO;
import com.gic.wechat.api.dto.qywx.chat.GroupChatListDTO;
import com.gic.wechat.api.dto.qywx.chat.GroupChatListItemDTO;
import com.gic.wechat.api.dto.qywx.chat.GroupChatUserIdDTO;
import com.gic.wechat.api.service.qywx.QywxChatApiService;
import com.github.pagehelper.PageHelper;

@Service("groupChatService")
public class GroupChatServiceImpl implements GroupChatService {

    private static final Logger logger = LoggerFactory.getLogger(GroupChatService.class);

    @Autowired
    private QywxChatApiService qywxChatApiService;
    @Autowired
    private GroupChatMapper groupChatMapper;
    @Autowired
    private GroupChatUserMapper groupChatUserMapper;
    @Autowired
    private WxEnterpriseService wxEnterpriseService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private TabHaobanExternalClerkRelatedMapper externalClerkRelatedMapper;
    @Autowired
    private StaffMapper staffMapper;
    @Autowired
    private SecretSettingService secretSettingService;
    @Autowired
    private ChatNoticeMapper chatNoticeMapper;
    @Autowired
    private StaffClerkRelationService staffClerkRelationService;
    @Autowired
    private Config config;
    @Autowired
    private GroupChatOwnerMapper groupChatOwnerMapper;
    @Autowired
    private GroupChatOwnerHistoryMapper groupChatOwnerHistoryMapper;
    @Autowired
    private WxEnterpriseRelatedService wxEnterpriseRelatedService;
    @Autowired
    private GroupChatHmService groupChatHmService;
    @Autowired
    private GroupChatHmRelationMapper groupChatHmRelationMapper;
    @Autowired
    private DepartmentService departmentService;
    @Autowired
    private GroupChatInitMapper groupChatInitMapper;
    @Autowired
    private StoreService storeService ;
    @Autowired
    private WxEnterpriseMapper wxEnterpriseMapper ;
    @Autowired
    private ExternalMemberService externalMemberService ;
    @Autowired
    private GroupChatActivityInviteLogService groupChatActivityInviteLogService;

    private static GicMQClient mqClient = GICMQClientUtil.getClientInstance();

    // 每次拉取成员数
    private int pageSize = 100;
    // 每次拉取群数
    private int limit = 1000;
    // 群下线成员数
    private int offNum = 200;

    // 刷新群
    private void putMQRefreshChat(String params) {
        try {
            mqClient.sendCommonMessage("haobanChatMQ", params,
                    "com.gic.haoban.manage.api.service.chat.GroupChatApiService", "refreshChatInfoFromMQ");
        } catch (Exception e) {
            logger.info("异常",e);
        }
    }

    // 刷新群状态
    private void putMQRefreshChatStatus(String params) {
        try {
            mqClient.sendCommonMessage("haobanChatMQ", params,
                    "com.gic.haoban.manage.api.service.chat.GroupChatApiService", "refreshChatInfoFromMQ");
        } catch (Exception e) {
            logger.info("异常",e);
        }
    }

    @Override
    public void createChat(String corpid, String wxChatId) {
        logger.info("创建群,id={}", wxChatId);
        String wxEnterpriseId = this.getWxEnterpriesId(corpid);
        if (null == wxEnterpriseId) {
            return;
        }
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        this.addGroupChat(qwDTO, wxChatId, 0, false);
    }

    @Override
    public void dismissChat(String corpid, String wxChatId) {
        logger.info("解散群corpid={},wxChatId={}", corpid, wxChatId);
        String wxEnterpriseId = this.getWxEnterpriesId(corpid);
        if (null == wxEnterpriseId) {
            return;
        }
        TabGroupChat groupChat = this.groupChatMapper.selectByWxChatId(wxEnterpriseId, wxChatId);
        if (null == groupChat) {
            logger.info("群查不到,wxChatid={}", wxChatId);
            return;
        }
        List<TabGroupChatUser> list = this.groupChatUserMapper.listAllChatUser(wxEnterpriseId,groupChat.getGroupChatId()) ;
        for(TabGroupChatUser user : list) {
            this.notice(user.getEnterpriseId(),user.getMemberId(),0);
        }
        this.groupChatMapper.updateChatStatus(groupChat.getGroupChatId(), 4);
        // 更新群数量
        this.updateOwnerCount(groupChat.getStaffId());
    }

    private void updateOwnerCount(String staffId) {
        if(StringUtils.isNotBlank(staffId)) {
            int chatCount = this.groupChatMapper.getCountByStaffId(staffId);
            logger.info("更新群数={},{}",staffId,chatCount);
            this.groupChatOwnerMapper.updateChatCount(staffId,chatCount) ;
        }
    }

    @Override
    public void updateChat(String corpid, String wxChatId, String updateDetail, String msg) {
        String wxEnterpriseId = this.getWxEnterpriesId(corpid);
        if (null == wxEnterpriseId) {
            return;
        }
        TabGroupChat groupChat = this.groupChatMapper.selectByWxChatId(wxEnterpriseId, wxChatId);
        if (null == groupChat) {
            logger.info("群不存在");
            // 创建群
            this.createChat(corpid, wxChatId);
            return;
        }
        TabChatNotice entity = new TabChatNotice();
        entity.setId(UniqueIdUtils.uniqueLong());
        entity.setChatId(groupChat.getGroupChatId());
        entity.setWxEnterpriseId(wxEnterpriseId);
        entity.setMsg(msg);
        // change_name=群名变更change_notice=群公告变更 1
        if ("change_name".equals(updateDetail) || "change_notice".equals(updateDetail)) {
            entity.setType(1);
        }
        // change_owner=群主变更 2
        if ("change_owner".equals(updateDetail)) {
            entity.setType(2);
        }
        // add_member=成员入群 del_member=成员退群 3
        if ("add_member".equals(updateDetail) || "del_member".equals(updateDetail)) {
            entity.setType(3);
        }
        this.chatNoticeMapper.insert(entity);
    }

    @Override
    public void refreshChatInfo(Long groupChatId) {
        logger.info("刷新群信息={}", groupChatId);
        TabGroupChat chat = this.groupChatMapper.selectById(groupChatId);
        if (null == chat) {
            logger.info("群不存在,groupChatId={}", groupChatId);
            return;
        }
        String wxEnterpriseId = chat.getWxEnterpriseId();
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        this.updateGroupChatDetail(qwDTO, chat, true);
    }

    @Override
    public GroupChatBO detail(String wxEnterpriseId, Long groupChatId) {
        TabGroupChat groupChat = this.groupChatMapper.selectById(groupChatId);
        return EntityUtil.changeEntity(GroupChatBO.class, groupChat);
    }

    @Override
    public GroupChatBO getByWxChatId(String wxEnterpriseId, String wxChatId) {
        TabGroupChat groupChat = this.groupChatMapper.selectByWxChatId(wxEnterpriseId, wxChatId);
        return EntityUtil.changeEntity(GroupChatBO.class, groupChat);
    }

    @Override
    public List<GroupChatBO> listChatByIdList(List<Long> idList) {
        List<TabGroupChat> chatList = this.groupChatMapper.listByIdSet(new HashSet<>(idList));
        List<GroupChatBO> list = EntityUtil.changeEntityListByJSON(GroupChatBO.class, chatList);
        return list;
    }

    @Override
    public Page<GroupChatDTO> listPage(GroupChatSearchQDTO qdto, BasePageInfo basePageInfo) {
        List<TabGroupChatHmRelation> relationList = null;
        if (null != qdto.getChatHmId()) {
            relationList = this.groupChatHmRelationMapper.listByChatHmId(qdto.getChatHmId());
            if (CollectionUtils.isEmpty(relationList)) {
                return new Page<GroupChatDTO>();
            }
            logger.info("活码页查询群列表{},关联群数={}", qdto.getChatHmId(), relationList.size());
            List<Long> groupChatIdList = relationList.stream().map(dto -> dto.getGroupChatId())
                    .collect(Collectors.toList());
            qdto.setGroupChatIdList(groupChatIdList);
        }
        qdto.setDepartmentIdList(this.setDepartIdList(qdto.getWxEnterpriseId(), qdto.getDepartmentId()));
        PageHelper.startPage(basePageInfo);
        if (StringUtils.isNotBlank(qdto.getSearchParams())) {
            String params = qdto.getSearchParams();
            qdto.setWxChatId(params + "%");
            qdto.setSearchParams("%" + params + "%");
        }
        List<GroupChatDTO> list = this.groupChatMapper.list(qdto);
        Page<GroupChatDTO> retPage = PageHelperUtils.changePageHelperToCurrentPage(list, GroupChatDTO.class);
        return retPage;
    }

    @Override
    public void updateChatEnterpriseId(String wxEnterpriseId, String enterpriseId, List<Long> groupChatIdList) {
        this.groupChatMapper.updateChatEnterpriseId(wxEnterpriseId, enterpriseId, groupChatIdList, 0);
        // 更新后重新同步群数据
        JSONObject json = new JSONObject();
        json.put("groupChatIdList", groupChatIdList);
        this.putMQRefreshChat(json.toJSONString());
    }

    // 处理群通知
    @Override
    public void handChatNotice(String params) {
        logger.info("企微群定时,处理群通知");
        String key = "handChatNotice";
        try {
            Object o = RedisUtil.getCache(key);
            if (null != o) {
                logger.info("有缓存,进行中");
                return;
            }
            RedisUtil.setCache(key, "1");
            List<Integer> typeList = Arrays.asList(1, 2, 3);
            Date endTime = new Date();
            Date startTime = DateUtil.addNumForMinute(endTime, -30);
            List<TabChatNotice> list = this.chatNoticeMapper.listAll(typeList, startTime, endTime);
            logger.info("开始群通知定时,count={}", list.size());
            if (CollectionUtils.isEmpty(list)) {
                return;
            }
            this.chatNoticeMapper.closeAll(typeList, startTime, endTime);
            for (TabChatNotice item : list) {
                try {
                    int type = item.getType();
                    String wxEnterpriseId = item.getWxEnterpriseId();
                    Long groupChatId = item.getChatId();
                    WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
                    if (type == 1) {
                        this.updateGroupChatDetail(qwDTO, groupChatId, false);
                    }
                    if (type == 2) {
                        this.updateGroupChatDetail(qwDTO, groupChatId, false);
                        this.updateChatStatus(qwDTO, groupChatId);
                    }
                    if (type == 3) {
                        this.updateGroupChatDetail(qwDTO, groupChatId, true);
                    }
                } catch (Exception e) {
                    logger.info("异常",e);
                }
            }
        } catch (Exception e) {
            logger.info("异常",e);
        } finally {
            RedisUtil.delCache(key);
        }
    }

    @Override
    public void initGroupChatForTimer(String params) {
        logger.info("企微群定时,群初始化");
        String key = "initGroupChatForTimer";
        try {
            Object o = RedisUtil.getCache(key);
            if (null != o) {
                logger.info("有缓存,进行中");
                return;
            }
            RedisUtil.setCache(key, "1");
            List<TabGroupChat> initList = this.groupChatMapper.listAllNeedInit();
            if (CollectionUtils.isNotEmpty(initList)) {
                logger.info("初始化群,数量={}", initList.size());
                for (TabGroupChat item : initList) {
                    try {
                        String wxEnterpriseId = item.getWxEnterpriseId();
                        Long groupChatId = item.getGroupChatId();
                        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
                        this.updateGroupChatDetail(qwDTO, groupChatId, true);
                    } catch (Exception e) {
                        logger.info("异常",e);
                    }
                }
            }
            List<TabGroupChat> list = this.groupChatMapper.listAllNeedInitWxChatIdDk();
            logger.info("更新群代开发ID,数量={}", list.size());
            for (TabGroupChat item : list) {
                try {
                    String wxEnterpriseId = item.getWxEnterpriseId();
                    String staffId = item.getStaffId();
                    this.updateWxChatIdDk(wxEnterpriseId, staffId);
                } catch (Exception e) {
                    logger.info("异常",e);
                }
            }
        } catch (Exception e) {
            logger.info("异常",e);
        } finally {
            RedisUtil.delCache(key);
        }
    }

    // 更新群状态
    private void updateChatStatus(WxEnterpriseQwDTO qwDTO, Long groupChatId) {
        logger.info("更新群状态,groupchatId={}", groupChatId);
        TabGroupChat chat = this.groupChatMapper.selectById(groupChatId);
        if (null == chat) {
            logger.info("群主变更事件,群不存在");
            return;
        }
        String staffId = chat.getStaffId();
        if (StringUtils.isBlank(staffId)) {
            logger.info("群主staffid不存在,groupChatId={}", groupChatId);
            return;
        }
        TabHaobanStaff staff = this.staffMapper.selectByPrimaryKey(staffId);
        if (null == staff) {
            logger.info("群主已删除,staffid={}", staffId);
            return;
        }
        String userId = staff.getWxUserId();
        if (qwDTO.needOpenUserId3th()) {
            userId = staff.getWxOpenUseId();
        }
        this.syncGroupChatList(qwDTO, Arrays.asList(userId), null, false);
    }
    
    private void updateChatStatusTimer() {
        List<GroupChatDTO> dtoList =  this.groupChatMapper.listChangeOwner() ;
        if(CollectionUtils.isNotEmpty(dtoList)) {
            for(GroupChatDTO dto : dtoList) {
                String staffId = dto.getStaffId();
                String wxEnterpriseId = dto.getWxEnterpriseId() ;
                TabHaobanStaff staff = this.staffMapper.selectByPrimaryKey(staffId);
                if (null == staff) {
                    logger.info("群主已删除,staffid={}", staffId);
                    continue;
                }
                WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
                String userId = staff.getWxUserId();
                if (qwDTO.needOpenUserId3th()) {
                    userId = staff.getWxOpenUseId();
                }
                this.syncGroupChatList(qwDTO, Arrays.asList(userId), null, false);
            }
        }
    }

    @Override
    public void initHaobaonGroupChat(String params) {
        logger.info("企微群定时,整个企业初始化");
        String key = "initHaobaonGroupChat";
        try {
            Object o = RedisUtil.getCache(key);
            if (null != o) {
                logger.info("有缓存,进行中");
                return;
            }
            RedisUtil.setCache(key, "1");
            List<TabGroupChatInit> initList = this.groupChatInitMapper.listAllInit();
            logger.info("开始企业群待初始化,数量={}", initList.size());
            if (CollectionUtils.isNotEmpty(initList)) {
                for (TabGroupChatInit init : initList) {
                    try {
                        this.initEnterpriseGroupChat(init.getWxEnterpriseId());
                        this.groupChatInitMapper.update(init.getWxEnterpriseId(), 2);
                    } catch (Exception e) {
                        logger.info("初始化异常,wxEid={}", init.getWxEnterpriseId());
                        this.groupChatInitMapper.update(init.getWxEnterpriseId(), 4);
                        logger.info("异常",e);
                    }
                }
            }
        } catch (Exception e) {
            logger.info("异常",e);
        } finally {
            RedisUtil.delCache(key);
        }
    }

    @Override
    public void ownerDimission(String staffId) {
        logger.info("群主离职,刷新群状态,staffId={}", staffId);
        TabGroupChatOwner owner = this.groupChatOwnerMapper.selectByStaffId(staffId);
        if (null != owner) {
            TabHaobanStaff staff = this.staffMapper.selectByPrimaryKeyNoStatus(staffId);
            this.dimissionOwner(staff.getWxEnterpriseId(), staff.getWxUserId(), staff.getWxOpenUseId());
            this.updateOwnerCount(staffId);
        }
    }

    // 群主离职列表
    public void ownerDimission() {
        logger.info("企微群定时,离职群主群状态更新");
        List<GroupChatOwnerDTO> dimissionOwnerList = this.groupChatOwnerMapper.dimissionOwnerList();
        for (GroupChatOwnerDTO dto : dimissionOwnerList) {
            try {
                logger.info("群主离职,群状态处理={}", JSON.toJSONString(dto));
                this.dimissionOwner(dto.getWxEnterpriseId(), dto.getWxUserId(), dto.getWxOpenUserId());
            } catch (Exception e) {
                logger.info("异常",e);
            }
        }
        try {
            logger.info("转移群的状态");
            this.updateChatStatusTimer();
        } catch (Exception e) {
            logger.info("异常",e);
        }
    }

    private void dimissionOwner(String wxEnterpriseId, String wxUserId, String wxOpenUserId) {
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        if (null == qwDTO) {
            logger.info("wxEnterpriseId不存在,id={}", wxEnterpriseId);
            return;
        }
        List<String> userIdList = null;
        if (qwDTO.needOpenUserId3th()) {
            userIdList = Arrays.asList(wxOpenUserId);
        } else {
            userIdList = Arrays.asList(wxUserId);
        }
        if (CollectionUtils.isNotEmpty(userIdList)) {
            this.syncGroupChatList(qwDTO, userIdList, null, false);
        }
    }

    /**
     * 初始化整个群数据,拉取所有成员的所有群,并立即获取群信息、群成员、同时也会匹配客户标识
     */
    private void initEnterpriseGroupChat(String wxEnterpriseId) {
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        if (null == qwDTO) {
            logger.info("wxEnterpriseId不存在,id={}", wxEnterpriseId);
            return;
        }
        int pageNum = 0;
        while (true) {
            List<TabHaobanStaff> staffList = this.staffMapper.listAllByPage(wxEnterpriseId, pageNum * pageSize,
                    pageSize);
            if (CollectionUtils.isEmpty(staffList)) {
                break;
            }
            logger.info("查询staff表第{}页,共{}条,{}", pageNum + 1, staffList.size(), wxEnterpriseId);
            List<String> userIdList = null;
            if (qwDTO.needOpenUserId3th()) {
                userIdList = staffList.stream().filter(dto -> StringUtils.isNotBlank(dto.getWxOpenUseId()))
                        .map(dto -> dto.getWxOpenUseId()).collect(Collectors.toList());
            } else {
                userIdList = staffList.stream().filter(dto -> StringUtils.isNotBlank(dto.getWxUserId()))
                        .map(dto -> dto.getWxUserId()).collect(Collectors.toList());
            }
            if (CollectionUtils.isNotEmpty(userIdList)) {
                this.syncGroupChatList(qwDTO, userIdList, null, true);
            }
            pageNum++;
        }
    }

    // 同步群列表
    private void syncGroupChatList(WxEnterpriseQwDTO qwDTO, List<String> userIdList, String cursor,
            boolean syncDetailFlag) {
        logger.info("同步群列表={},idlist={},cursor={}", JSON.toJSONString(qwDTO), JSON.toJSONString(userIdList), cursor);
        ServiceResponse<GroupChatListDTO> resp = this.qywxChatApiService.groupchatList(qwDTO.getThirdCorpid(),
                qwDTO.getSelf3thSecret() , userIdList, limit, cursor , qwDTO.isSelf(), qwDTO.getUrlHost());
        if (!resp.isSuccess()) {
            logger.info("拉取群列表异常={}", JSON.toJSON(resp));
            return;
        }
        GroupChatListDTO dto = resp.getResult();
        cursor = dto.getNext_cursor();
        List<GroupChatListItemDTO> list = dto.getGroup_chat_list();
        for (GroupChatListItemDTO item : list) {
            String wxChatId = item.getChat_id();
            int chatStatus = item.getStatus();
            this.addGroupChat(qwDTO, wxChatId, chatStatus, syncDetailFlag);
        }
        // 从企微拉取下一批数据
        if (StringUtils.isNotBlank(cursor)) {
            this.syncGroupChatList(qwDTO, userIdList, cursor, syncDetailFlag);
        }
    }

    /**
     * 新增群记录, 如果是更新,只更新群状态,新增只记录群id和群状态，其他数据都在详情修改维护
     */
    private void addGroupChat(WxEnterpriseQwDTO qwDTO, String wxChatId, int chatStatus, boolean syncDetailFlag) {
        String wxEnterpriseId = qwDTO.getWxEnterpriseId();
        TabGroupChat groupChat = this.groupChatMapper.selectByWxChatId(wxEnterpriseId, wxChatId);
        Long groupChatId = null;
        if (null != groupChat) {
            groupChatId = groupChat.getGroupChatId();
            logger.info("更新群状态,wxchatid={},groupChatId={},新老状态={}-{}", wxChatId, groupChatId, chatStatus,
                    groupChat.getChatStatus());
            if (groupChat.getChatStatus() != chatStatus) {
                this.groupChatMapper.updateChatStatus(groupChatId, chatStatus);
            }
        } else {
            String lockKey = "lock:chat:add:" + wxChatId;
            try {
                RedisUtil.lock(lockKey, 10L);
                groupChat = this.groupChatMapper.selectByWxChatId(wxEnterpriseId, wxChatId);
                if (null == groupChat) {
                    groupChatId = UniqueIdUtils.uniqueLong();
                    TabGroupChat chat = new TabGroupChat();
                    chat.setGroupChatId(groupChatId);
                    chat.setWxEnterpriseId(wxEnterpriseId);
                    String enterpriseId = this.matchGicEnterpriseId(wxEnterpriseId, null, null);
                    chat.setGicFlag(0);
                    if (StringUtils.isNotBlank(enterpriseId)) {
                        chat.setEnterpriseId(enterpriseId);
                        chat.setGicFlag(1);
                    }
                    chat.setWxChatId(wxChatId);
                    if(qwDTO.isSelf()) {
                        chat.setWxChatIdDk(wxChatId);
                    }
                    chat.setChatStatus(chatStatus);
                    chat.setCreateTime(new Date());
                    chat.setUpdateTime(new Date());
                    chat.setDeleteFlag(0);
                    chat.setTotalCount(0);
                    chat.setInitFlag(0);
                    chat.setTotalMemberCount(0);
                    chat.setAddMemberCount(0);
                    chat.setAddCount(0);
                    chat.setQuitCount(0);
                    chat.setQuitMemberCount(0);
                    this.groupChatMapper.insert(chat);
                } else {
                    groupChatId = groupChat.getGroupChatId();
                }
                RedisUtil.unlock(lockKey);
            } catch (Exception e) {
                logger.info("异常",e);
            }
        }
        if (syncDetailFlag) {
            this.updateGroupChatDetail(qwDTO, groupChatId, true);
        }
    }

    private String emoji(String content) {
        return content;
    }

    private void updateGroupChatDetail(WxEnterpriseQwDTO qwDTO, TabGroupChat chat, boolean syncMember) {
        Long groupChatId = chat.getGroupChatId();
        String wxEnterpriseId = chat.getWxEnterpriseId();
        String enterpriseId = chat.getEnterpriseId();
        ServiceResponse<GroupChatDetailDTO> detailResp = this.qywxChatApiService
                    .groupchatDetail(qwDTO.getThirdCorpid(), qwDTO.getSelf3thSecret(), chat.getWxChatId(), 1 , qwDTO.isSelf() , qwDTO.getUrlHost());
     
        logger.info("从企微获取群详情{}={}", chat.getWxChatId(), JSON.toJSON(detailResp));
        if (!detailResp.isSuccess()) {
            logger.info("从企微获取群详情失败");
            String code = detailResp.getCode();
            String msg = detailResp.getMessage();
            if (code.equals("701008")) {
                msg = "该群主未激活账号许可，无法获取群详情";
            } else {
                msg = "企微返回错误,错误码" + code;
            }
            this.groupChatMapper.updateChatErrorRemark(groupChatId, msg);
            return;
        }
        GroupChatDetailDTO detail = detailResp.getResult();
        String owner = detail.getOwner();
        TabHaobanStaff staff = this.staffMapper.selectByUserIdAndEnterpriseId(owner, wxEnterpriseId);
        if (null == staff) {
            logger.info("群主staff查不到,不处理,owner={}", owner);
            return;
        }
        String lockKey = "sync:chat:" + groupChatId;
        try {
            if (!RedisUtil.isLocked(lockKey)) {
                RedisUtil.lock(lockKey, 5L);
                String chatName = this.emoji(detail.getName());
                String notice = this.emoji(detail.getNotice());
                chat.setGroupChatId(groupChatId);
                chat.setChatAddTime(new Date(detail.getCreate_time() * 1000));
                chat.setChatNotice(notice);
                chat.setName(chatName);
                // 匹配GIC商户ID ,如果已经初始化过,不再自动匹配GIC商户
                if (chat.getInitFlag() == 0) {
                    enterpriseId = matchGicEnterpriseId(wxEnterpriseId, enterpriseId, staff);
                    chat.setEnterpriseId(enterpriseId);
                    if (StringUtils.isNotEmpty(chat.getEnterpriseId())) {
                        chat.setGicFlag(1);
                    }
                }
                String oldStaffId = chat.getStaffId();
                String newStaffId = staff.getStaffId();
                chat.setStaffId(staff.getStaffId());
                // 判断是否更新群主
                this.saveOwnerHistory(wxEnterpriseId, groupChatId, newStaffId, oldStaffId);
                if(null != oldStaffId && oldStaffId.equals(newStaffId)) {
                    chat.setOriginalStaffId(chat.getOriginalStaffId());
                }else {
                    chat.setOriginalStaffId(oldStaffId);
                }
                this.groupChatMapper.update(chat);
                this.saveOwner(wxEnterpriseId, staff.getStaffId());
                if(null != chat.getOriginalStaffId()) {
                    this.updateOwnerCount(chat.getOriginalStaffId()) ;
                }
                RedisUtil.unlock(lockKey);
            }
        } catch (Exception e) {
            logger.info("异常",e);
        }
        if (!syncMember) {
            logger.info("不同步群成员");
            return;
        }
        String lockKeyDetail = "sync:chat:detail:" + groupChatId;
        try {
            if (RedisUtil.isLocked(lockKeyDetail)) {
                return;
            }

            String staffId = chat.getStaffId() ;
            String storeName = "";
            if(null != staffId) {
                List<StaffClerkRelationDTO> staffList = this.staffClerkRelationService.listByStaffId(wxEnterpriseId,staffId) ;
                if(CollectionUtils.isNotEmpty(staffList)) {
                    List<String> storeIdList = staffList.stream().filter(o->StringUtils.isNotEmpty(o.getStoreId())).map(o->o.getStoreId()).collect(Collectors.toList()) ;
                    if(CollectionUtils.isNotEmpty(storeIdList)) {
                        String[] arr = new String[storeIdList.size()] ;
                        for(int i=0;i<storeIdList.size();i++) {
                           arr[i] = storeIdList.get(i) ;
                        }
                        List<StoreDTO> storeList = this.storeService.getStores(arr) ;
                        if(CollectionUtils.isNotEmpty(storeList)) {
                           storeName = storeList.stream().map(o->o.getStoreName()).collect(Collectors.joining("、")) ;
                        }
                    }
                }

            }

            RedisUtil.lock(lockKeyDetail, 30L);
            List<GroupChatDetailMemberDTO> qwUserList = detail.getMember_list();
            // 当前群列表
            List<TabGroupChatUser> nowUserList = this.groupChatUserMapper.listAllChatUser(wxEnterpriseId, groupChatId);
            int nowTotalCount = nowUserList.size();
            Map<String, TabGroupChatUser> nowUserMap = nowUserList.stream()
                    .collect(Collectors.toMap(TabGroupChatUser::getUserId, o -> o, ((k1, k2) -> k1)));
            List<TabGroupChatUser> needAddUserList = new ArrayList<>();
            List<GroupChatUserIdDTO> adminList = detail.getAdmin_list();
            List<String> adminIdList = adminList.stream().map(dto -> dto.getUserid()).collect(Collectors.toList());
            int totalMemberCount = 0;
            Map<String, String> invitorMap = new HashMap<>();
            for (GroupChatDetailMemberDTO qwUser : qwUserList) {
                int memberCount = this.saveOrUpdateChatUser(groupChatId, wxEnterpriseId, enterpriseId, owner,
                        nowUserMap, needAddUserList, adminIdList, qwUser, invitorMap);
                totalMemberCount = totalMemberCount + memberCount;
            }
            int addMemberCount = 0;
            for (TabGroupChatUser item : needAddUserList) {
                if (item.getUserType() == 3) {
                    addMemberCount++;
                }
            }
            if (CollectionUtils.isNotEmpty(needAddUserList)) {
                this.groupChatUserMapper.batchInsert(needAddUserList);
                ExecuteServiceUtil.executeService(() -> groupChatActivityInviteLogService.groupChatInviteMQ(needAddUserList), "社群邀请异常");
            }
            // 删除退群的人
            List<Long> deleteIdList = new ArrayList<>();
            List<String> deleteUserIdList = new ArrayList<>();
            List<String> nowQwUserIdList = qwUserList.stream().map(dto -> dto.getUserid()).collect(Collectors.toList());
            for (TabGroupChatUser user : nowUserList) {
                if (!nowQwUserIdList.contains(user.getUserId())) {
                    deleteIdList.add(user.getChatUserId());
                    deleteUserIdList.add(user.getUserId());
                }
            }
            // 总成员数
            int totalCount = qwUserList.size();
            // 本次新增
            int addCount = needAddUserList.size();
            // 流失总数
            int quitCount = 0;
            // 流水会员数
            int quitMemberCount = 0;
            if (CollectionUtils.isNotEmpty(deleteIdList)) {
                this.groupChatUserMapper.dismiss(deleteIdList, chat.getStaffId(),storeName);
                quitCount = deleteIdList.size();
                for (String userId : deleteUserIdList) {
                    TabGroupChatUser user = nowUserMap.get(userId);
                    if (null != user && user.getUserType() == 3) {
                        ++quitMemberCount;
                        this.notice(enterpriseId,user.getMemberId(),0);
                    }
                }
            }
            logger.info("群成员数,当前={},更新后={}", nowTotalCount, totalCount);
            if (totalCount >= offNum && nowTotalCount < offNum) {
                logger.info("群满下线处理,chatid={}", chat.getWxChatId());
                this.chatOff(chat);
            }
            this.updateData(groupChatId, totalCount, totalMemberCount, addMemberCount, addCount, quitCount,
                    quitMemberCount);
        } catch (Exception e) {
            logger.info("异常",e);
        } finally {
            RedisUtil.unlock(lockKeyDetail);
        }
    }

    // 保存更新群成员
    private int saveOrUpdateChatUser(Long groupChatId, String wxEnterpriseId, String enterpriseId, String owner,
            Map<String, TabGroupChatUser> userMap, List<TabGroupChatUser> needAddUserList, List<String> adminIdList,
            GroupChatDetailMemberDTO qwUser, Map<String, String> invitorMap) {
        int totalMemberCount = 0;
        String userName = this.emoji(qwUser.getName());
        String nickName = this.emoji(qwUser.getGroup_nickname());
        String userId = qwUser.getUserid();
        TabGroupChatUser hbUser = userMap.get(userId);
        boolean updateFlag = true;
        boolean needUpdateFlag = false;
        if (null == hbUser) {
            updateFlag = false;
            hbUser = new TabGroupChatUser();
        }
        Integer oldAdminFlag = hbUser.getAdminFlag();
        hbUser.setAdminFlag(0);
        if (null == hbUser.getUserType()) {
            hbUser.setUserType(qwUser.getType());
        }
        if (qwUser.getUserid().equals(owner)) {
            hbUser.setAdminFlag(1);
        } else if (adminIdList.contains(qwUser.getUserid())) {
            hbUser.setAdminFlag(2);
        }
        if (StringUtils.isEmpty(hbUser.getMemberId()) && qwUser.getType() == 2) {
            this.matchGicMember(wxEnterpriseId, enterpriseId, qwUser.getUnionid(), userId, hbUser,groupChatId);
        }
        if (hbUser.getUserType() == 3) {
            totalMemberCount = 1;
        }
        String oldUserName = hbUser.getUserName();
        String oldNick = hbUser.getNickName();
        hbUser.setUserName(userName);
        hbUser.setNickName(nickName);
        if (updateFlag) {
            if (null == oldAdminFlag || !oldAdminFlag.equals(hbUser.getAdminFlag())) {
                needUpdateFlag = true;
            }
            if (this.isDiff(oldUserName, userName)) {
                needUpdateFlag = true;
            }
            if (this.isDiff(oldNick, nickName)) {
                needUpdateFlag = true;
            }
            if (needUpdateFlag) {
                logger.info("更新用户,id={}", userId);
                this.groupChatUserMapper.update(hbUser);
            }
            return totalMemberCount;
        }
        hbUser.setChatUserId(UniqueIdUtils.uniqueLong());
        hbUser.setWxEnterpriseId(wxEnterpriseId);
        hbUser.setEnterpriseId(enterpriseId);
        hbUser.setJoinTime(new Date(qwUser.getJoin_time() * 1000));
        hbUser.setGroupChatId(groupChatId);
        hbUser.setUserId(userId);
        hbUser.setJoinScene(qwUser.getJoin_scene());
        hbUser.setJoinState(qwUser.getState());
        hbUser.setUnionid(qwUser.getUnionid());
        hbUser.setDeleteFlag(0);
        hbUser.setStatusFlag(1);
        hbUser.setCreateTime(new Date());
        hbUser.setUpdateTime(new Date());
        if (null != qwUser.getInvitor()) {
            String invitorId = qwUser.getInvitor().getUserid();
            if (StringUtils.isNotBlank(invitorId)) {
                hbUser.setInvitorUserId(invitorId);
                String invitorUserName = invitorMap.get(invitorId);
                if (null == invitorUserName) {
                    TabHaobanStaff invitor = this.staffMapper.selectByUserIdAndEnterpriseId(invitorId, wxEnterpriseId);
                    if (null != invitor) {
                        invitorMap.put(invitorId, invitor.getStaffName());
                        invitorUserName = invitor.getStaffName();
                    } else {
                        invitorMap.put(invitorId, "");
                    }
                }
                if (StringUtils.isNotBlank(invitorUserName)) {
                    hbUser.setInvitorUserName(invitorUserName);
                }
            }
        }
        needAddUserList.add(hbUser);
        return totalMemberCount;
    }

    // 匹配GIC企业ID
    private String matchGicEnterpriseId(String wxEnterpriseId, String enterpriseId, TabHaobanStaff staff) {
        if (StringUtils.isBlank(enterpriseId)) {
            List<TabHaobanWxEnterpriseRelated> list = this.wxEnterpriseRelatedService
                    .getByWxEnterpriseId(wxEnterpriseId);
            if (CollectionUtils.isNotEmpty(list) && list.size() == 1) {
                logger.info("匹配到群gic商户id,一对一模式,gic={}", list.get(0).getEnterpriseId());
                enterpriseId = list.get(0).getEnterpriseId();
            }
        }
        if (StringUtils.isBlank(enterpriseId) && null != staff) {
            logger.info("匹配群的gic商户id,staffid={}", staff.getStaffId());
            List<StaffClerkRelationDTO> clerkList = this.staffClerkRelationService.listByStaffId(wxEnterpriseId,
                    staff.getStaffId());
            if (CollectionUtils.isNotEmpty(clerkList)) {
                Set<String> enterpriseIdSet = clerkList.stream().map(dto -> dto.getEnterpriseId())
                        .collect(Collectors.toSet());
                logger.info("成员关联导购数={},商户={}", clerkList.size(), enterpriseIdSet);
                if (enterpriseIdSet.size() == 1) {
                    enterpriseId = clerkList.get(0).getEnterpriseId();
                }
            }
        }
        return enterpriseId;
    }

    // 字符串是否有修改
    private boolean isDiff(String a, String b) {
        if (StringUtils.isBlank(a) && StringUtils.isBlank(b)) {
            return false;
        }
        if (StringUtils.isNotBlank(a) && StringUtils.isNotBlank(b) && a.equals(b)) {
            return false;
        }
        return true;
    }

    private void updateData(Long groupChatId, int totalCount, int totalMemberCount, int addMemberCount, int addCount,
            int quitCount, int quitMemberCount) {
        logger.info("更新群的统计,groupChatId={}", groupChatId);
        this.groupChatMapper.updateData(groupChatId, totalCount, totalMemberCount, addMemberCount, addCount, quitCount,
                quitMemberCount);
    }

    // 历任群主
    private void saveOwnerHistory(String wxEnterpriseId, Long groupChatId, String newStaffId, String oldStaffId) {
        if (StringUtils.isEmpty(newStaffId) && StringUtils.isEmpty(oldStaffId)) {
            return;
        }
        if (StringUtils.isNotEmpty(newStaffId) && StringUtils.isNotEmpty(oldStaffId) && newStaffId.equals(oldStaffId)) {
            return;
        }
        if (StringUtils.isNotEmpty(newStaffId)) {
            if (null != this.groupChatOwnerHistoryMapper.getGroupChatNowStaff(groupChatId, newStaffId)) {
                return;
            }
            TabGroupChatOwnerHistory entity = new TabGroupChatOwnerHistory();
            entity.setOwnerHistoryId(UniqueIdUtils.uniqueLong());
            entity.setWxEnterpriseId(wxEnterpriseId);
            entity.setGroupChatId(groupChatId);
            entity.setStaffId(newStaffId);
            entity.setCreateTime(new Date());
            this.groupChatOwnerHistoryMapper.insert(entity);
        }
        if (StringUtils.isNotEmpty(oldStaffId)) {
            this.groupChatOwnerHistoryMapper.updateOwnerEnd(groupChatId, oldStaffId);
        }
    }

    // 初始化群信息-不包括群状态
    private void updateGroupChatDetail(WxEnterpriseQwDTO qwDTO, Long groupChatId, boolean syncMember) {
        TabGroupChat chat = this.groupChatMapper.selectById(groupChatId);
        this.updateGroupChatDetail(qwDTO, chat, syncMember);
    }

    // 匹配群成员-客户
    private void matchGicMember(String wxEnterpriseId, String enterpriseId, String unionid, String externalUserId,
            TabGroupChatUser user , Long groupChatId) {
        logger.info("入群匹配群客户,unionid={},exteruserid={}", unionid, externalUserId);
        if (StringUtils.isBlank(enterpriseId)) {
            return;
        }
        if (StringUtils.isNotBlank(unionid)) {
            MemberDTO member = this.memberService.getMemberByUnionid(unionid, enterpriseId);
            if (null != member) {
                logger.info("匹配群客户,unionid");
                user.setMemberId(member.getMemberId());
                user.setUserType(3);
                this.notice(enterpriseId,member.getMemberId(),1) ;
            }
        } else if (StringUtils.isNotBlank(externalUserId)) {
            TabHaobanExternalClerkRelated related = this.externalClerkRelatedMapper
                    .getMemberForExternalId(wxEnterpriseId, externalUserId);
            if (null != related) {
                logger.info("匹配群客户,externalUserId");
                user.setMemberId(related.getMemberId());
                user.setUserType(3);
                this.notice(enterpriseId,related.getMemberId(),1) ;
                TabGroupChat group = this.groupChatMapper.selectById(groupChatId) ;
                if(null != group) {
                    this.externalMemberService.updateMemberGrowth(related.getEnterpriseId(),related.getMemberId(), GrowthRuleEnum.ADD_HAOBAN_GROUP.getRuleCode(), "群信息",group.getName() + "(" + groupChatId + ")");
                }
            }
        }
    }

    @Override
    public void matchGicMember(String wxEnterpriseId, String enterpriseId, String memberId, String externalUserId) {
        logger.info("加好友匹配群客户,memberId={},externalUserId={}", memberId, externalUserId);
        List<TabGroupChatUser> list = this.groupChatUserMapper.listByExternalUseridForMatch(wxEnterpriseId,
                enterpriseId, externalUserId);
        if (CollectionUtils.isNotEmpty(list)) {
            this.groupChatUserMapper.updateToGicMember(wxEnterpriseId, enterpriseId, externalUserId, memberId);
            Set<Long> groupChatIdList = list.stream().map(dto -> dto.getGroupChatId()).collect(Collectors.toSet());
            groupChatIdList.forEach(groupChatId -> {
                logger.info("群加会员数={}", groupChatId);
                this.notice(enterpriseId,memberId,1) ;
                this.groupChatMapper.addMemberCount(groupChatId);
            });
        }
    }


    public void notice(String enterpriseId,String memberId , int addOrQuit) {
        logger.info("会员群入群通知={},{}",memberId,addOrQuit,addOrQuit);
        if(StringUtils.isBlank(enterpriseId) || StringUtils.isBlank(memberId)) {
            return;
        }
        GroupChatUserNoticeDTO dto = new GroupChatUserNoticeDTO() ;
        dto.setEnterpriseId(enterpriseId);
        dto.setMemberId(memberId);
        dto.setAddOrQuit(addOrQuit);
        try {
            mqClient.sendMessage("qywxAddGroupChatEvent",JSONObject.toJSONString(dto));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    private String getWxEnterpriesId(String corpid) {
        TabHaobanWxEnterprise wxEnterprise = this.wxEnterpriseService.getEnterpriseBycorpId(corpid);
        if (wxEnterprise == null) {
            logger.info("企业不存在,corpid={}", corpid);
            return null;
        }
        return wxEnterprise.getWxEnterpriseId();
    }

    private void updateWxChatIdDk(String wxEnterpriseId, String staffId) {
        logger.info("更新代开wxEid={},staff={}", wxEnterpriseId, staffId);
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        SecretSettingDTO secretSetting = secretSettingService.getSecretSetting(qwDTO.getWxEnterpriseId(),
                SecretTypeEnum.CUSTOMIZED_APP.getVal());
        if (null == secretSetting) {
            logger.info("未配置代开应用,wxEnterpriseId={}",wxEnterpriseId);
            return;
        }
        String secret = secretSetting.getSecretVal();
        TabHaobanStaff stff = this.staffMapper.selectByPrimaryKey(staffId);
        if(null == stff) {
            Log.info("staff不存在,stffid={}",staffId);
            return ;
        }
        String userid = stff.getWxUserId();
        if (qwDTO.needOpenUserIdDk()) {
            userid = stff.getWxOpenUseId();
        }
        this.updateWxChatIdDk(qwDTO, Arrays.asList(userid), null, staffId, secret);
    }

    private void updateWxChatIdDk(WxEnterpriseQwDTO qwDTO, List<String> userIdList, String cursor, String staffId,
            String secret) {
        ServiceResponse<GroupChatListDTO> resp = this.qywxChatApiService.groupchatList(qwDTO.getDkCorpid(), secret,
                userIdList, limit, cursor ,true , qwDTO.getUrlHost());
        if (!resp.isSuccess()) {
            logger.info("拉取群异常={}", JSON.toJSON(resp));
            return;
        }
        GroupChatListDTO dto = resp.getResult();
        cursor = dto.getNext_cursor();
        List<GroupChatListItemDTO> list = dto.getGroup_chat_list();
        for (GroupChatListItemDTO item : list) {
            String wxChatIdDk = item.getChat_id();
            ServiceResponse<GroupChatDetailDTO> detailResp = this.qywxChatApiService
                    .groupchatDetail(qwDTO.getDkCorpid(), secret, wxChatIdDk, 1 , true , qwDTO.getUrlHost());
            if (detailResp.isSuccess()) {
                GroupChatDetailDTO detail = detailResp.getResult();
                Long createTimeLong = detail.getCreate_time() * 1000;
                String name = emoji(detail.getName());
                logger.info("更新代开chatid,staffid={},time={},wxDkid={}", staffId, createTimeLong, wxChatIdDk);
                this.groupChatMapper.updateWxChatIdDk(staffId, name, new Date(createTimeLong), wxChatIdDk);
            }
        }
        if (org.apache.commons.lang3.StringUtils.isNotBlank(cursor)) {
            this.updateWxChatIdDk(qwDTO, userIdList, cursor, staffId, secret);
        }
    }

    /**
     * 
    * @Title: saveOwner
    * @Description: 新增群主表/更新群主群的数量
    * @author xugh
    * @param wxEnterpriseId
    * @param staffId
    * @throws
     */
    private void saveOwner(String wxEnterpriseId, String staffId) {
        int chatCount = this.groupChatMapper.getCountByStaffId(staffId);
        TabGroupChatOwner owner = this.groupChatOwnerMapper.selectByStaffId(staffId);
        if (null != owner) {
            this.groupChatOwnerMapper.updateChatCount(staffId, chatCount);
        } else {
            owner = new TabGroupChatOwner();
            owner.setWxEnterpriseId(wxEnterpriseId);
            owner.setStaffId(staffId);
            owner.setChatCount(chatCount);
            this.groupChatOwnerMapper.insert(owner);
        }
    }

    @Override
    public Page<GroupChatOwnerDTO> listOwnerPage(OwnerSearchQDTO qdto, BasePageInfo basePageInfo) {
        if (StringUtils.isNotBlank(qdto.getSearchParams())) {
            String params = qdto.getSearchParams();
            qdto.setSearchParams("%" + params + "%");
        }
        qdto.setDepartmentIdList(this.setDepartIdList(qdto.getWxEnterpriseId(), qdto.getDepartmentId()));
        PageHelper.startPage(basePageInfo);
        List<GroupChatOwnerDTO> list = this.groupChatOwnerMapper.listOwner(qdto);
        Page<GroupChatOwnerDTO> retPage = PageHelperUtils.changePageHelperToCurrentPage(list, GroupChatOwnerDTO.class);
        // 拼门店名称
        if(CollectionUtils.isNotEmpty(retPage.getResult()) && qdto.getShowStoreNames()==1 && StringUtils.isNotBlank(qdto.getShowNameEnterpriseId())) {
            List<String> staffIdList = retPage.getResult().stream().map(GroupChatOwnerDTO::getStaffId).collect(Collectors.toList());
            List<StaffClerkRelationDTO> staffList = this.staffClerkRelationService.listByWxEnterpriseIdAndStaffId(qdto.getWxEnterpriseId(),staffIdList.stream().collect(Collectors.toSet())) ;
            Map<String,List<StaffClerkRelationDTO>> staffMap = staffList.stream().collect(Collectors.groupingBy(StaffClerkRelationDTO::getStaffId)) ;
            staffList = staffList.stream().filter(o->o.getEnterpriseId().equals(qdto.getShowNameEnterpriseId()) && StringUtils.isNotBlank(o.getStoreId())).collect(Collectors.toList());
            Map<String,String> storeNameMap = new HashMap<>() ;
            if(CollectionUtils.isNotEmpty(staffList)) {
                List<String> storeIdList = staffList.stream().filter(o->StringUtils.isNotEmpty(o.getStoreId())).map(o->o.getStoreId()).collect(Collectors.toList()) ;
                if(CollectionUtils.isNotEmpty(storeIdList)) {
                    String[] arr = new String[storeIdList.size()] ;
                    for(int i=0;i<storeIdList.size();i++) {
                        arr[i] = storeIdList.get(i) ;
                    }
                    List<StoreDTO> storeList = this.storeService.getStores(arr) ;
                    if(CollectionUtils.isNotEmpty(storeList)) {
                        storeNameMap = storeList.stream().collect(Collectors.toMap(StoreDTO::getStoreId, o->o.getStoreName(),(k1,k2)->k1)) ;
                    }
                }
            }
            for(GroupChatOwnerDTO item : retPage.getResult()) {
                String staffId = item.getStaffId() ;
                List<StaffClerkRelationDTO> relationList = staffMap.get(staffId) ;
                List<String> storeNameList = new ArrayList<>() ;
                if(CollectionUtils.isNotEmpty(relationList)) {
                    for (StaffClerkRelationDTO relation : relationList) {
                        if(StringUtils.isNotBlank(relation.getStoreId()) && storeNameMap.containsKey(relation.getStoreId())) {
                            storeNameList.add(storeNameMap.get(relation.getStoreId()));
                        }
                    }
                }
                item.setStoreNames(String.join(",", storeNameList));
            }
        }
        return retPage;
    }

    @Override
    public List<String> setDepartIdList(String wxEnterpriseId, String departmentId) {
        List<String> departmentIdList = new ArrayList<>();
        if (StringUtils.isNotBlank(departmentId)) {
            TabHaobanDepartment department = this.departmentService.selectById(departmentId);
            if (department != null) {
                String parentDepartmentId = department.getParentDepartmentId();
                if (!"0".equals(parentDepartmentId)) {
                    String chainId = department.getChainId() + Constant.ID_SEPARATOR + departmentId;
                    List<TabHaobanDepartment> tabList = departmentService.listByChainId(chainId, wxEnterpriseId);
                    List<String> departmentIds = tabList.stream().map(TabHaobanDepartment::getDepartmentId)
                            .collect(Collectors.toList());
                    departmentIdList.add(departmentId);
                    departmentIdList.addAll(departmentIds);
                }
            }
        }
        return departmentIdList;
    }

    @Override
    public List<GroupChatOwnerHistoryDTO> listOwnerHistory(Long groupChatId, String WxEnterpriseId) {
        TabGroupChat chat = this.groupChatMapper.selectById(groupChatId);
        if (null == chat || org.apache.commons.lang3.StringUtils.isEmpty(chat.getStaffId())) {
            return null;
        }
        List<GroupChatOwnerHistoryDTO> list = this.groupChatOwnerHistoryMapper.listAll(groupChatId, WxEnterpriseId);
        for (GroupChatOwnerHistoryDTO item : list) {
            if (chat.getStaffId().equals(item.getStaffId())) {
                item.setEndTime(null);
            }
        }
        return list;
    }

    @Override
    public ServiceResponse<Void> transfer(String wxEnterpriseId, String staffId, List<Long> groupChatIdList) {
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        if (null == qwDTO) {
            logger.info("wxEnterpriseId不存在,id={}", wxEnterpriseId);
            return ServiceResponse.failure("9999", "企业不存在");
        }
        TabHaobanStaff staff = this.staffMapper.selectByPrimaryKey(staffId);
        String userid = staff.getWxUserId();
        if (qwDTO.needOpenUserId3th()) {
            userid = staff.getWxOpenUseId();
        }
        List<TabGroupChat> list = this.groupChatMapper.listByIdSet(new HashSet<>(groupChatIdList));
        List<String> wxChatIdList = list.stream().map(dto -> dto.getWxChatId()).collect(Collectors.toList());
        ServiceResponse<List<FailChatListDTO>> resp =  this.qywxChatApiService.transfer(qwDTO.getThirdCorpid(),
                qwDTO.getSelf3thSecret(), wxChatIdList, userid,qwDTO.isSelf(),qwDTO.getUrlHost());
        logger.info("群继承,继承人={},{}", JSON.toJSONString(resp), userid);
        if (!resp.isSuccess()) {
            return ServiceResponse.failure("9999", resp.getMessage());
        } else {
            JSONObject json = new JSONObject();
            json.put("groupChatIdList", groupChatIdList);
            this.putMQRefreshChatStatus(JSON.toJSONString(json));
            if (CollectionUtils.isNotEmpty(resp.getResult())) {
                return ServiceResponse.failure("9999", JSON.toJSONString(resp.getResult()));
            }
        }
        return ServiceResponse.success();
    }

    // 如果群的人数达到上限,则群GIC侧的下线,记录状态,且从活码中剔除
    private void chatOff(TabGroupChat chat) {
        Long groupChatId = chat.getGroupChatId();
        // 群下线
        this.groupChatMapper.chatOff(groupChatId);
        // 通知处理群活码
        this.groupChatHmService.handleChatOff(chat.getWxEnterpriseId(), groupChatId);
    }

    @Override
    public void handleHmChatFull(String params) {
        logger.info("企微群定时,群满");
        List<Integer> typeList = Arrays.asList(4);
        Date endTime = new Date();
        Date startTime = DateUtil.addNumForMinute(endTime, -30);
        List<TabChatNotice> list = this.chatNoticeMapper.listAll(typeList, startTime, endTime);
        logger.info("群满处理活码,count={}", list.size());
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        this.chatNoticeMapper.closeAll(typeList, startTime, endTime);
        for (TabChatNotice item : list) {
            String wxEnterpriseId = item.getWxEnterpriseId();
            Long groupChatId = item.getChatId();
            // 通知处理群活码
            try {
                TabGroupChat chat = this.groupChatMapper.selectById(groupChatId);
                if (null == chat || chat.getTotalCount() < offNum) {
                    continue;
                }
                if (chat.getOffTime().getTime() + 1000 * 60 * 60 * 24 * 30 < new Date().getTime()) {
                    logger.info("超过8小时不重试groupChatId={}", groupChatId);
                    continue;
                }
                this.groupChatHmService.handleChatOff(wxEnterpriseId, groupChatId);
            } catch (Exception e) {
                logger.info("异常",e);
            }
        }
    }

    @Override
    public void refreshChatStatus(Long groupChatId) {
        TabGroupChat chat = this.groupChatMapper.selectById(groupChatId);
        if (null != chat) {
            String wxEnterpriseId = chat.getWxEnterpriseId();
            WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
            this.updateChatStatus(qwDTO, groupChatId);
        }
    }
    
    @Override
    public ServiceResponse<Void> initStaffGroupChat(String staffId) {
        TabHaobanStaff staff = this.staffMapper.selectByPrimaryKey(staffId);
        String userId = staff.getWxUserId();
        String wxEnterpriseId = staff.getWxEnterpriseId();
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        if (qwDTO.needOpenUserId3th()) {
            userId = staff.getWxOpenUseId();
        }
        this.syncGroupChatList(qwDTO, Arrays.asList(userId), null, true);
        return null ;
    }

    @Override
    public void repairOwner() {
        List<TabHaobanWxEnterprise> wxEnterpriseList = this.wxEnterpriseMapper.listByIds(null);
        for (TabHaobanWxEnterprise item : wxEnterpriseList) {
            int pageNum = 0;
            if(item.getWxSecurityType() <= 0) {
                continue;
            }
            while (true) {
                List<GroupChatOwnerDTO>  list = this.groupChatOwnerMapper.listOwnerForStatistic(item.getWxEnterpriseId(), pageNum * pageSize, pageSize);
                if (CollectionUtils.isEmpty(list)) {
                    logger.info("无群主记录,不处理,wxeid={}",item.getWxEnterpriseId());
                    break;
                }
                pageNum++;
                for(GroupChatOwnerDTO dto : list) {
                    this.updateOwnerCount(dto.getStaffId());
                }
            }

        }
    }
}