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

import com.alibaba.fastjson.JSON;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.commons.util.DateUtil;
import com.gic.commons.util.UniqueIdUtils;
import com.gic.haoban.manage.api.dto.WxEnterpriseQwDTO;
import com.gic.haoban.manage.api.enums.content.ClerkShareMaterialType;
import com.gic.haoban.manage.api.enums.content.ShareBizType;
import com.gic.haoban.manage.service.config.Config;
import com.gic.haoban.manage.service.entity.TabHaobanStaff;
import com.gic.haoban.manage.service.pojo.bo.chat.GroupChatBO;
import com.gic.haoban.manage.service.pojo.bo.chat.GroupChatUserBO;
import com.gic.haoban.manage.service.pojo.bo.content.ClerkShareLogBO;
import com.gic.haoban.manage.service.pojo.bo.content.GroupMessageInfoBo;
import com.gic.haoban.manage.service.pojo.bo.content.TriggerCustomerDetailBO;
import com.gic.haoban.manage.service.pojo.qo.content.ClerkShareLogQO;
import com.gic.haoban.manage.service.service.ExternalClerkRelatedService;
import com.gic.haoban.manage.service.service.StaffService;
import com.gic.haoban.manage.service.service.WxEnterpriseService;
import com.gic.haoban.manage.service.service.chat.GroupChatService;
import com.gic.haoban.manage.service.service.chat.GroupChatUserService;
import com.gic.haoban.manage.service.service.content.ClerkShareLogService;
import com.gic.haoban.manage.service.service.content.GroupMessageService;
import com.gic.haoban.manage.service.service.content.TriggerCustomerDetailService;
import com.gic.haoban.manage.service.service.content.adaptor.MaterialEnterpriseAdaptor;
import com.gic.wechat.api.dto.qdto.group.QywxGroupMessageQDTO;
import com.gic.wechat.api.dto.qdto.group.QywxGroupMsgSendResultQDTO;
import com.gic.wechat.api.dto.qdto.group.QywxMomentInfoQDTO;
import com.gic.wechat.api.dto.qdto.group.QywxMomentSendResultQDTO;
import com.gic.wechat.api.dto.qywx.group.QywxGroupMessageInfoDTO;
import com.gic.wechat.api.dto.qywx.group.QywxGroupMsgResp;
import com.gic.wechat.api.dto.qywx.group.QywxGroupMsgSendResultDTO;
import com.gic.wechat.api.dto.qywx.group.QywxMomentRespDTO;
import com.gic.wechat.api.dto.qywx.group.QywxMomentSendResultRespDTO;
import com.gic.wechat.api.service.qywx.QywxSuiteApiService;
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.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author MUSI
 * @Date 2023/3/19 9:49 PM
 * @Description
 * @Version 企微群发消息处理器
 **/
@Component
public class GroupMessageServiceImpl implements GroupMessageService {

    private static final Logger log = LoggerFactory.getLogger(GroupMessageServiceImpl.class);

    public enum GroupMsgChatType {
        single("single", "发送给客户"),
        group("group", "发送给客户群");

        GroupMsgChatType(String code, String desc) {
            this.code = code;
            this.desc = desc;
        }

        private String code;
        private String desc;

        public String getCode() {
            return code;
        }

        public String getDesc() {
            return desc;
        }
    }

    @Autowired
    private TriggerCustomerDetailService triggerCustomerDetailService;
    @Autowired
    private QywxSuiteApiService qywxSuiteApiService;
    @Autowired
    private ClerkShareLogService clerkShareLogService;
    @Autowired
    private WxEnterpriseService wxEnterpriseService;
    @Autowired
    private GroupChatUserService groupChatUserService;
    @Autowired
    private GroupChatService groupChatService;
    @Autowired
    private Config config;
    @Autowired
    private StaffService staffService;
    @Autowired
    private ExternalClerkRelatedService externalClerkRelatedService;
    @Autowired
    private MaterialEnterpriseAdaptor materialEnterpriseAdaptor;

    @Override
    public void handlerGroupMessage(GroupMessageInfoBo groupMessageInfoBo) {
        // 获取企业下(当前时间 - 30, 当前时间) 的导购分享日志
        ClerkShareLogQO clerkShareLogQO = new ClerkShareLogQO()
                .setEnterpriseId(groupMessageInfoBo.getEnterpriseId())
                .setStartTime(groupMessageInfoBo.getStartTime())
                .setEndTime(groupMessageInfoBo.getEndTime())
                .setBizType(ShareBizType.MATERIAL.getCode())
                .setShareLogId(groupMessageInfoBo.getShareLogId());
        List<ClerkShareLogBO> shareLogBos = clerkShareLogService.queryClerkShareLog(clerkShareLogQO);
        if (CollectionUtils.isEmpty(shareLogBos)) {
            log.info("时间段内没有导购分享记录 {}", JSON.toJSONString(groupMessageInfoBo));
            return;
        }

        Map<String, List<ClerkShareLogBO>> wxEnterpriseIdMap = shareLogBos
                .stream()
                .collect(Collectors.groupingBy(ClerkShareLogBO::getWxEnterpriseId));
        for (Map.Entry<String, List<ClerkShareLogBO>> entry : wxEnterpriseIdMap.entrySet()) {
            String wxEnterpriseId = entry.getKey();
            List<Long> shareLogIds = this.doHandlerWithOneWxEnterprise(wxEnterpriseId, shareLogBos, groupMessageInfoBo);
            // 标记本批次处理的分享日志为已处理
            clerkShareLogService.markClerkShareDone(groupMessageInfoBo.getEnterpriseId(), shareLogIds);
        }
    }

    /**
     * 查询好办成员信息
     *
     * @param clerkShareLogBos
     * @return
     */
    private Map<String, TabHaobanStaff> queryStaffMapInfo(List<ClerkShareLogBO> clerkShareLogBos) {
        List<String> staffIds = clerkShareLogBos
                .stream()
                .map(ClerkShareLogBO::getStaffId)
                .distinct()
                .collect(Collectors.toList());
        List<TabHaobanStaff> tabHaobanStaffs = staffService.listStaffWithIds(staffIds);
        if (CollectionUtils.isEmpty(tabHaobanStaffs)) {
            log.info("成员不存在 staffIds:{}", JSON.toJSONString(staffIds));
            return Collections.emptyMap();
        }
        return tabHaobanStaffs
                .stream()
                .collect(Collectors.toMap(TabHaobanStaff::getStaffId, Function.identity()));
    }

    /**
     * 企微纬度处理客户触达
     *
     * @param wxEnterpriseId
     * @param clerkShareLogBos
     * @param groupMessageInfoBo
     * @return
     */
    private List<Long> doHandlerWithOneWxEnterprise(String wxEnterpriseId, List<ClerkShareLogBO> clerkShareLogBos, GroupMessageInfoBo groupMessageInfoBo) {
        WxEnterpriseQwDTO qwInfo = wxEnterpriseService.getQwInfo(wxEnterpriseId);
        String corpId = qwInfo.getThirdCorpid();
        Map<String, TabHaobanStaff> staffInfoMap = this.queryStaffMapInfo(clerkShareLogBos);
        List<String> excludeMsgId = new ArrayList<>();
        // 已处理的分享日志
        List<Long> clerkShareLogIds = new ArrayList<>();

        doHandlerWithSend2Customer(clerkShareLogBos, groupMessageInfoBo, qwInfo, corpId, staffInfoMap, excludeMsgId, clerkShareLogIds);
        doHandlerWithSend2Group(wxEnterpriseId, clerkShareLogBos, groupMessageInfoBo, qwInfo, corpId, staffInfoMap, excludeMsgId, clerkShareLogIds);
        if (groupMessageInfoBo.getShareLogId() != null) {
            doHandlerWithSend2PYQ(groupMessageInfoBo, clerkShareLogBos, staffInfoMap, corpId, qwInfo, clerkShareLogIds);
        }
        return clerkShareLogIds;
    }

    /**
     * 处理群发到客户
     *
     * @param wxEnterpriseId
     * @param clerkShareLogBos
     * @param groupMessageInfoBo
     * @param qwInfo
     * @param corpId
     * @param staffInfoMap
     * @param excludeMsgId
     * @param clerkShareLogIds
     */
    private void doHandlerWithSend2Group(String wxEnterpriseId, List<ClerkShareLogBO> clerkShareLogBos, GroupMessageInfoBo groupMessageInfoBo,
                                         WxEnterpriseQwDTO qwInfo,
                                         String corpId, Map<String, TabHaobanStaff> staffInfoMap, List<String> excludeMsgId, List<Long> clerkShareLogIds) {

        log.info("doHandlerWithSend2Group 处理群发到群组开始 >>>>>>> ");
        if (groupMessageInfoBo.getStartTime() == null || groupMessageInfoBo.getEndTime() == null) {
            log.info("doHandlerWithSend2Group 处理群发到群组缺少时间参数 {}", JSON.toJSONString(groupMessageInfoBo));
            return;
        }
        // 发送到群
        List<QywxGroupMessageInfoDTO> sendWithGroupMsg = this.queryGroupMsg(corpId, GroupMsgChatType.group,
                groupMessageInfoBo.getStartTime(), groupMessageInfoBo.getEndTime());
        // 匹配msgId
        List<ClerkShareLogBO> shareLogWithGroup = clerkShareLogBos
                .stream()
                .filter(item -> ClerkShareMaterialType.SHARE_GROUP.getCode().equals(item.getShareType()))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(shareLogWithGroup)) {
            log.info("doHandlerWithSend2Group 群发到群, 无该类型分享日志");
            return;
        }
        for (ClerkShareLogBO shareLogInfo : shareLogWithGroup) {
            QywxGroupMessageInfoDTO qywxGroupMessageInfoDTO = matchMshIdWithClerkShareLog(shareLogInfo, sendWithGroupMsg, excludeMsgId);
            if (qywxGroupMessageInfoDTO == null) {
                log.info("匹配导购群发日志失败 {}", JSON.toJSONString(shareLogInfo));
                continue;
            }
            clerkShareLogIds.add(shareLogInfo.getId());
            TabHaobanStaff staff = staffInfoMap.get(shareLogInfo.getStaffId());
            if (staff == null) {
                log.info("doHandlerWithOneWxEnterprise 导购分享日志 成员不存在 staffId:{}", shareLogInfo.getStaffId());
                continue;
            }
            String userId = staff.getWxUserId();
            if (qwInfo.needOpenUserId3th()) {
                userId = staff.getWxOpenUseId();
            }
            String msgId = qywxGroupMessageInfoDTO.getMsgId();
            List<QywxGroupMsgSendResultDTO.GroupMsgSendResultInfo> groupMsgSendResultInfos =
                    this.queryGroupMsgSendResult(corpId, msgId, userId, null);
            if (CollectionUtils.isEmpty(groupMsgSendResultInfos)) {
                log.info("根据msgId: {}查询群发结果异常.staffId: {}", msgId, shareLogInfo.getStaffId());
                continue;
            }
            List<QywxGroupMsgSendResultDTO.GroupMsgSendResultInfo> sendResultInfos = groupMsgSendResultInfos
                    .stream()
                    .filter(item -> StringUtils.isNotBlank(item.getChatId()))
                    .collect(Collectors.toList());
            // 可能是多个群 (批量发送到群)
            for (QywxGroupMsgSendResultDTO.GroupMsgSendResultInfo sendResultInfo : sendResultInfos) {
                String wxChatId = sendResultInfo.getChatId();
                GroupChatBO groupChatInfo = groupChatService.getByWxChatId(wxEnterpriseId, wxChatId);
                if (groupChatInfo == null) {
                    log.info("doHandlerWithOneWxEnterprise 群发到群 不存在, wxGroupChatId:{}", wxChatId);
                    continue;
                }
                List<GroupChatUserBO> groupChatUserBos =
                        groupChatUserService.queryGroupMemberWithChatId(shareLogInfo.getEnterpriseId(), shareLogInfo.getWxEnterpriseId(), groupChatInfo.getGroupChatId());
                if (CollectionUtils.isEmpty(groupChatUserBos)) {
                    continue;
                }
                this.saveTriggerCustomerWithGroup(shareLogInfo, groupChatUserBos);
            }
        }
    }

    /**
     * 处理群发到客户的触达日志
     *
     * @param clerkShareLogBos
     * @param groupMessageInfoBo
     * @param qwInfo
     * @param corpId
     * @param staffInfoMap
     * @param excludeMsgId
     * @param clerkShareLogIds
     */
    private void doHandlerWithSend2Customer(List<ClerkShareLogBO> clerkShareLogBos, GroupMessageInfoBo groupMessageInfoBo, WxEnterpriseQwDTO qwInfo,
                                            String corpId, Map<String, TabHaobanStaff> staffInfoMap, List<String> excludeMsgId, List<Long> clerkShareLogIds) {
        log.info("doHandlerWithSend2Customer 处理群发到客户 开始 >>>>>>>>");
        if (groupMessageInfoBo.getStartTime() == null || groupMessageInfoBo.getEndTime() == null) {
            log.info("doHandlerWithSend2Customer 处理群发到客户 缺少时间参数 {}", JSON.toJSONString(groupMessageInfoBo));
            return;
        }
        // 发送给客户的消息
        List<QywxGroupMessageInfoDTO> sendWithCustomerMsg = this.queryGroupMsg(corpId, GroupMsgChatType.single,
                groupMessageInfoBo.getStartTime(), groupMessageInfoBo.getEndTime());

        List<ClerkShareLogBO> shareLogsWithCustomer = clerkShareLogBos
                .stream()
                .filter(item -> ClerkShareMaterialType.SHARE_CUSTOMER.getCode().equals(item.getShareType()))
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(shareLogsWithCustomer)) {
            log.info("doHandlerWithSend2Group 群发到客户, 无该类型分享日志");
            return;
        }
        for (ClerkShareLogBO shareLogInfo : shareLogsWithCustomer) {
            QywxGroupMessageInfoDTO qywxGroupMessageInfoDTO = matchMshIdWithClerkShareLog(shareLogInfo, sendWithCustomerMsg, excludeMsgId);
            if (qywxGroupMessageInfoDTO == null) {
                log.info("doHandlerWithOneWxEnterprise 导购分享日志匹配msgId未匹配到 {}", JSON.toJSONString(shareLogInfo));
                continue;
            }
            log.info("doHandlerWithOneWxEnterprise 导购分享日志 clerkId:{}, 匹配到msgId:{}", shareLogInfo.getClerkId(), qywxGroupMessageInfoDTO.getMsgId());
            clerkShareLogIds.add(shareLogInfo.getId());
            TabHaobanStaff staff = staffInfoMap.get(shareLogInfo.getStaffId());
            if (staff == null) {
                log.info("doHandlerWithOneWxEnterprise 导购分享日志 成员不存在 staffId:{}", shareLogInfo.getStaffId());
                continue;
            }
            String userId = staff.getWxUserId();
            if (qwInfo.needOpenUserId3th()) {
                userId = staff.getWxOpenUseId();
            }
            List<QywxGroupMsgSendResultDTO.GroupMsgSendResultInfo> groupMsgSendResultInfos =
                    this.queryGroupMsgSendResult(corpId, qywxGroupMessageInfoDTO.getMsgId(), userId, null);
            this.saveTriggerCustomerDetailLogWithSingle(shareLogInfo, groupMsgSendResultInfos);
        }
    }

    /**
     * 处理群发到朋友圈触达客户日志
     *
     * @param clerkShareLogBos
     * @param clerkShareLogIds
     */
    private void doHandlerWithSend2PYQ(GroupMessageInfoBo groupMessageInfoBo, List<ClerkShareLogBO> clerkShareLogBos,
                                       Map<String, TabHaobanStaff> staffInfoMap,
                                       String corpId,
                                       WxEnterpriseQwDTO qwInfo, List<Long> clerkShareLogIds) {
        if (CollectionUtils.isEmpty(clerkShareLogBos)) {
            return;
        }
        List<ClerkShareLogBO> clerkShareLogWithPyq = clerkShareLogBos
                .stream()
                .filter(item -> ClerkShareMaterialType.SHARE_PYQ.getCode().equals(item.getShareType()))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(clerkShareLogWithPyq)) {
            log.info("doHandlerWithSend2PYQ 无分享到朋友圈分享日志");
            return;
        }
        for (ClerkShareLogBO clerkShareLogBo : clerkShareLogWithPyq) {
            clerkShareLogIds.add(clerkShareLogBo.getId());
            TabHaobanStaff staff = staffInfoMap.get(clerkShareLogBo.getStaffId());
            if (staff == null) {
                log.info("doHandlerWithSend2PYQ 导购分享日志成员不存在 staffId:{}", clerkShareLogBo.getStaffId());
                continue;
            }
            String userId = staff.getWxUserId();
            if (qwInfo.needOpenUserId3th()) {
                userId = staff.getWxOpenUseId();
            }
            List<String> externalUserIds = this.queryMomentResult(corpId, userId, clerkShareLogBo.getCreateTime());
            if (CollectionUtils.isEmpty(externalUserIds)) {
                log.info("处理导购群发朋友圈触达客户日志, 成员无好友. staffId:{}", clerkShareLogBo.getStaffId());
                return;
            }
            List<TriggerCustomerDetailBO> customerDetailBos = externalUserIds.stream()
                    .map(item -> this.convertCustomerDetailLog(clerkShareLogBo, item))
                    .collect(Collectors.toList());
            triggerCustomerDetailService.batchSave(customerDetailBos);
        }
    }

    /**
     * 获取与分享日志匹配msgId
     * 根据导购群发成功时间往前30秒内全部的发送记录，取时间距离最近的一条获取群ID；
     * 如没有则往后30秒，找到距离群发成功时间最近的群ID。如仍然没找到，则群人数记为0
     *
     * @param clerkShareLogBo
     * @param qywxGroupMessageInfos
     * @return
     */
    private QywxGroupMessageInfoDTO matchMshIdWithClerkShareLog(ClerkShareLogBO clerkShareLogBo,
                                                                final List<QywxGroupMessageInfoDTO> qywxGroupMessageInfos,
                                                                final List<String> excludeMsgIds) {
        Long createTime = clerkShareLogBo.getCreateTime().getTime() / 1000;
        // 往前找
        Optional<QywxGroupMessageInfoDTO> messageInfoDTO = qywxGroupMessageInfos
                .stream()
                .filter(item -> !excludeMsgIds.contains(item.getMsgId()))
                .filter(item -> item.getCreateTime() - createTime <= 0 && createTime - item.getCreateTime() <= 30)
                .min((first, second) -> (int) (Math.abs(first.getCreateTime() - createTime) - Math.abs(second.getCreateTime() - createTime)));
        if (messageInfoDTO.isPresent()) {
            QywxGroupMessageInfoDTO dto = messageInfoDTO.get();
            excludeMsgIds.add(dto.getMsgId());
            return dto;
        }
        // 往后找
        messageInfoDTO = qywxGroupMessageInfos
                .stream()
                .filter(item -> !excludeMsgIds.contains(item.getMsgId()))
                .filter(item -> item.getCreateTime() - createTime > 0 && item.getCreateTime() - createTime <= 30)
                .min((first, second) -> (int) (Math.abs(first.getCreateTime() - createTime) - Math.abs(second.getCreateTime() - createTime)));
        if (messageInfoDTO.isPresent()) {
            QywxGroupMessageInfoDTO dto = messageInfoDTO.get();
            excludeMsgIds.add(dto.getMsgId());
            return dto;
        }
        return null;
    }

    /**
     * 查询群发消息
     *
     * @param corpid
     * @param groupMsgChatType
     * @param startTime
     * @param endTime
     * @return
     */
    private List<QywxGroupMessageInfoDTO> queryGroupMsg(String corpid, GroupMsgChatType groupMsgChatType, Date startTime, Date endTime) {
        List<QywxGroupMessageInfoDTO> groupMessageInfos = new ArrayList<>();
        QywxGroupMessageQDTO groupMessageQDTO = new QywxGroupMessageQDTO();
        groupMessageQDTO.setCorpid(corpid);
        groupMessageQDTO.setStartTime(startTime.getTime() / 1000);
        groupMessageQDTO.setEndTime(endTime.getTime() / 1000);
        groupMessageQDTO.setSuiteid(config.getWxSuiteid());
        groupMessageQDTO.setChatType(groupMsgChatType.getCode());
        groupMessageQDTO.setPageSize(100);
        ServiceResponse<QywxGroupMsgResp> serviceResponse =
                qywxSuiteApiService.queryQywxGroupMessageList(groupMessageQDTO);
        if (!serviceResponse.isSuccess() || CollectionUtils.isEmpty(serviceResponse.getResult().getGroupMessageInfos())) {
            log.info("获取群发任务记录异常 {}", JSON.toJSONString(serviceResponse));
            return Collections.emptyList();
        }
        QywxGroupMsgResp groupMsgResp = serviceResponse.getResult();
        List<QywxGroupMessageInfoDTO> tempMessageInfos = groupMsgResp.getGroupMessageInfos();
        groupMessageInfos.addAll(tempMessageInfos);
        String cursor = groupMsgResp.getCursor();
        int loopTimes = 0;
        while (StringUtils.isNotBlank(cursor)) {
            loopTimes++;
            log.info("查询群消息 第{}次查询", loopTimes);
            groupMessageQDTO.setCursor(cursor);
            ServiceResponse<QywxGroupMsgResp> tempResponse =
                    qywxSuiteApiService.queryQywxGroupMessageList(groupMessageQDTO);
            if (!tempResponse.isSuccess() || CollectionUtils.isEmpty(tempResponse.getResult().getGroupMessageInfos())) {
                log.info("查询群消息异常 跳出循环 {}", loopTimes);
                break;
            }
            groupMessageInfos.addAll(tempResponse.getResult().getGroupMessageInfos());
            cursor = tempResponse.getResult().getCursor();
        }
        return groupMessageInfos;
    }

    /**
     * 查询企微成员 群发结果
     *
     * @param corpid
     * @param msgId
     * @param userId
     * @param cursor
     */
    private List<QywxGroupMsgSendResultDTO.GroupMsgSendResultInfo> queryGroupMsgSendResult(String corpid, String msgId, String userId, String cursor) {
        QywxGroupMsgSendResultQDTO searchQDTO = new QywxGroupMsgSendResultQDTO();
        searchQDTO.setCorpid(corpid);
        searchQDTO.setSuiteid(config.getWxSuiteid());
        searchQDTO.setPageSize(1000);
        searchQDTO.setMsgId(msgId);
        searchQDTO.setUserId(userId);
        searchQDTO.setCursor(cursor);
        ServiceResponse<QywxGroupMsgSendResultDTO> serviceResponse = qywxSuiteApiService.queryQywxGroupMsgSendResult(searchQDTO);
        if (!serviceResponse.isSuccess() || CollectionUtils.isEmpty(serviceResponse.getResult().getSendResultInfos())) {
            return Collections.emptyList();
        }
        List<QywxGroupMsgSendResultDTO.GroupMsgSendResultInfo> groupMsgSendResultInfos = new ArrayList<>();
        groupMsgSendResultInfos.addAll(serviceResponse.getResult().getSendResultInfos());
        if (StringUtils.isNotBlank(serviceResponse.getResult().getCursor())) {
            log.info("递归获取成员群发结果 >>>>> ");
            String tempCursor = serviceResponse.getResult().getCursor();
            groupMsgSendResultInfos.addAll(this.queryGroupMsgSendResult(corpid, msgId, userId, tempCursor));
        }
        return groupMsgSendResultInfos;
    }


    /**
     * 查询发朋友圈结果
     * @param corpid
     * @param userId
     * @return
     */
    public List<String> queryMomentResult(String corpid, String userId, Date createTime) {

        Date currentTime = new Date();
        QywxMomentInfoQDTO qywxMomentInfoQDTO = new QywxMomentInfoQDTO();
        qywxMomentInfoQDTO.setCorpid(corpid);
        qywxMomentInfoQDTO.setSuiteid(config.getWxSuiteid());
        qywxMomentInfoQDTO.setStartTime(DateUtil.addNumForSecond(currentTime, -60).getTime() / 1000);
        qywxMomentInfoQDTO.setEndTime(currentTime.getTime() / 1000);
        qywxMomentInfoQDTO.setCreatorId(userId);
        qywxMomentInfoQDTO.setPageSize(20);
        ServiceResponse<QywxMomentRespDTO> serviceResponse = qywxSuiteApiService.queryQywxMomentList(qywxMomentInfoQDTO);
        if (!serviceResponse.isSuccess() || CollectionUtils.isEmpty(serviceResponse.getResult().getQywxMomentInfos())) {
            log.info("查询客户发表朋友圈记录失败 {}", JSON.toJSONString(serviceResponse));
            return Collections.emptyList();
        }
        long filterTime = createTime.getTime() / 1000;

        Optional<QywxMomentRespDTO.QywxMomentInfoDTO> min = serviceResponse.getResult().getQywxMomentInfos()
                .stream()
                .min((first, second) -> (int) (Math.abs(first.getCreateTime() - filterTime) - Math.abs(second.getCreateTime() - filterTime)));
        if (min.isPresent()) {
            return this.queryMomentSendResultList(corpid, userId, min.get().getMomentId());
        }
        return Collections.emptyList();
    }

    public List<String> queryMomentSendResultList(String corpid, String userId, String momentId) {
        QywxMomentSendResultQDTO qywxMomentSendResultQDTO = new QywxMomentSendResultQDTO();
        qywxMomentSendResultQDTO.setCorpid(corpid);
        qywxMomentSendResultQDTO.setSuiteid(config.getWxSuiteid());
        qywxMomentSendResultQDTO.setMomentId(momentId);
        qywxMomentSendResultQDTO.setUserId(userId);
        qywxMomentSendResultQDTO.setPageSize(1000);
        ServiceResponse<QywxMomentSendResultRespDTO> serviceResponse = qywxSuiteApiService.queryQywxMomentSendResult(qywxMomentSendResultQDTO);
        if (!serviceResponse.isSuccess() || CollectionUtils.isEmpty(serviceResponse.getResult().getQywxMomentSendResults())) {
            log.info("查询朋友圈发送结果异常 {}", JSON.toJSONString(serviceResponse));
            return Collections.emptyList();
        }
        List<String> result = new ArrayList<>();
        List<String> externalUserIds = serviceResponse.getResult()
                .getQywxMomentSendResults()
                .stream()
                .map(QywxMomentSendResultRespDTO.QywxMomentSendResultDTO::getExternalUserid)
                .collect(Collectors.toList());
        result.addAll(externalUserIds);
        int loopTimes = 0;
        String cursor = serviceResponse.getResult().getCursor();
        while (StringUtils.isNotBlank(cursor)) {
            loopTimes++;
            log.info("查询群消息 第{}次查询", loopTimes);
            qywxMomentSendResultQDTO.setCursor(cursor);
            ServiceResponse<QywxMomentSendResultRespDTO> tempResponse = qywxSuiteApiService.queryQywxMomentSendResult(qywxMomentSendResultQDTO);
            if (!serviceResponse.isSuccess() || CollectionUtils.isEmpty(serviceResponse.getResult().getQywxMomentSendResults())) {
                break;
            }
            if (!tempResponse.isSuccess() || CollectionUtils.isEmpty(tempResponse.getResult().getQywxMomentSendResults())) {
                log.info("查询朋友圈消息异常 跳出循环 {}", loopTimes);
                break;
            }
            List<String> tempUserIds = serviceResponse.getResult()
                    .getQywxMomentSendResults()
                    .stream()
                    .map(QywxMomentSendResultRespDTO.QywxMomentSendResultDTO::getExternalUserid)
                    .collect(Collectors.toList());
            result.addAll(tempUserIds);
            cursor = tempResponse.getResult().getCursor();
        }
        return result;
    }

    /**
     * 保存触达日志明细 群发到客户
     *
     * @param clerkShareLogBO
     * @param groupMsgSendResultInfos
     */
    private void saveTriggerCustomerDetailLogWithSingle(ClerkShareLogBO clerkShareLogBO,
                                                        List<QywxGroupMsgSendResultDTO.GroupMsgSendResultInfo> groupMsgSendResultInfos) {
        if (CollectionUtils.isEmpty(groupMsgSendResultInfos)) {
            return;
        }
        List<TriggerCustomerDetailBO> customerDetailBos = groupMsgSendResultInfos
                .stream()
                .map(item -> this.convertCustomerDetailLog(clerkShareLogBO, item.getExternalUserId()))
                .collect(Collectors.toList());
        triggerCustomerDetailService.batchSave(customerDetailBos);
    }

    /**
     * 保存触达日志明细 群发到群
     *
     * @param clerkShareLogBO
     * @param groupChatUserBos
     */
    private void saveTriggerCustomerWithGroup(ClerkShareLogBO clerkShareLogBO,
                                              final List<GroupChatUserBO> groupChatUserBos) {
        if (CollectionUtils.isEmpty(groupChatUserBos)) {
            return;
        }
        List<TriggerCustomerDetailBO> customerDetailBos = groupChatUserBos
                .stream()
                .map(item -> this.convertCustomerDetailLog(clerkShareLogBO, item.getUserId()))
                .collect(Collectors.toList());
        triggerCustomerDetailService.batchSave(customerDetailBos);
    }

    private TriggerCustomerDetailBO convertCustomerDetailLog(ClerkShareLogBO clerkShareLogBO, String externalUserId) {
        TriggerCustomerDetailBO temp = new TriggerCustomerDetailBO();
        temp.setId(UniqueIdUtils.uniqueLong());
        temp.setEnterpriseId(clerkShareLogBO.getEnterpriseId());
        temp.setWxEnterpriseId(clerkShareLogBO.getWxEnterpriseId());
        temp.setBizId(clerkShareLogBO.getBizId());
        temp.setBizType(clerkShareLogBO.getBizType());
        temp.setClerkId(clerkShareLogBO.getClerkId());
        temp.setStaffId(clerkShareLogBO.getStaffId());
        temp.setStoreId(clerkShareLogBO.getStoreId());
        temp.setChannelType(clerkShareLogBO.getShareType());
        temp.setCustomerId(externalUserId);
        temp.setCreateTime(new Date());
        temp.setUpdateTime(new Date());
        temp.setDeleteFlag(0);
        return temp;
    }

    /**
     * 获取当前时间 有素材权限的商户
     *
     * @return
     */
    @Override
    public List<String> hasMaterialRightEnterprise(Integer level) {

        List<String> enterpriseIds = materialEnterpriseAdaptor.queryHasRightEnterpriseIds(level);
        log.info("有权限的企业信息 level：{}, enterpriseIds:{}", level, JSON.toJSONString(enterpriseIds));
        return enterpriseIds;
    }
}
