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

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gic.api.base.commons.BusinessException;
import com.gic.api.base.commons.JSONResponse;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.commons.util.UniqueIdUtils;
import com.gic.content.api.utils.MqUtils;
import com.gic.haoban.common.utils.EntityUtil;
import com.gic.haoban.manage.api.dto.anaylsis.ClerkShareGoodsLogDTO;
import com.gic.haoban.manage.api.dto.send.DealQwSendDTO;
import com.gic.haoban.manage.api.enums.contact.ContactFollowTypeEnum;
import com.gic.haoban.manage.api.qdto.contact.ContactFollowBatchQDTO;
import com.gic.haoban.manage.api.service.MemberUnionidRelatedApiService;
import com.gic.haoban.manage.api.service.MessageApiService;
import com.gic.haoban.manage.api.service.content.MaterialShareLogApiService;
import com.gic.haoban.manage.service.dao.mapper.TabHaobanExternalClerkRelatedMapper;
import com.gic.haoban.manage.service.dao.mapper.send.QwSendLogMapper;
import com.gic.haoban.manage.service.dao.mapper.send.QwSendMsgMapper;
import com.gic.haoban.manage.service.entity.TabHaobanExternalClerkRelated;
import com.gic.haoban.manage.service.entity.send.TabQwSendLog;
import com.gic.haoban.manage.service.entity.send.TabQwSendMsg;
import com.gic.haoban.manage.service.pojo.bo.send.GroupSendResultBO;
import com.gic.haoban.manage.service.service.chat.GroupChatPlanService;
import com.gic.haoban.manage.service.service.content.impl.GroupMessageServiceImpl;
import com.gic.haoban.manage.service.service.send.QwSendMsgService;
import com.gic.member.api.constant.MemberExtKeyEnum;
import com.gic.member.api.dto.member.req.MemberExtraPropertyReq;
import com.gic.member.api.service.extra.MemberExtraPropertyApiService;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 企微群发msgid表(TabQwSendMsg)表服务实现类
 *
 * @author makejava
 * @since 2025-03-25 13:48:06
 */
@Service
@Slf4j
public class QwSendMsgServiceImpl implements QwSendMsgService {
    @Autowired
    private QwSendMsgMapper qwSendMsgMapper;
    @Autowired
    private QwSendLogMapper qwSendLogMapper;
    @Autowired
    private TabHaobanExternalClerkRelatedMapper externalClerkRelatedMapper;
    @Autowired
    private GroupChatPlanService groupChatPlanService;
    @Autowired
    private MemberUnionidRelatedApiService memberUnionidRelatedApiService;
    @Autowired
    private MessageApiService messageApiService;
    @Autowired
    private MaterialShareLogApiService materialShareLogApiService;
    @Autowired
    private MemberExtraPropertyApiService memberExtraPropertyApiService;

    @Override
    public void finishQwSend(DealQwSendDTO.FinishQwSendBO finishQwSendBO,Integer tryCount) {
        String clerkId = finishQwSendBO.getClerkId();
        String staffId = finishQwSendBO.getStaffId();
        Date sendTime = finishQwSendBO.getSendTime();
        String qwMsgId = groupChatPlanService.getQwMsgId(staffId, sendTime, GroupMessageServiceImpl.GroupMsgChatType.single);
        if (StringUtils.isNotBlank(qwMsgId)) {
            TabQwSendMsg qwSendMsg = qwSendMsgMapper.queryByMsgId(qwMsgId);
            if (qwSendMsg != null) {
                log.error("数据已处理过qwMsgId:{}", qwMsgId);
                return;
            }
            qwSendMsg = new TabQwSendMsg();
            qwSendMsg.setId(UniqueIdUtils.uniqueLong());
            qwSendMsg.setClerkId(clerkId);
            qwSendMsg.setStaffId(staffId);
            qwSendMsg.setMsgId(qwMsgId);
            qwSendMsg.setSendTime(sendTime);
            qwSendMsg.setBizType(finishQwSendBO.getBizType());
            qwSendMsg.setWxEnterpriseId(finishQwSendBO.getWxEnterpriseId());
            qwSendMsg.setEnterpriseId(finishQwSendBO.getEnterpriseId());
            qwSendMsgMapper.insert(qwSendMsg);
            DealQwSendDTO dealQwSendDTO = new DealQwSendDTO();
            dealQwSendDTO.setEnterpriseId(finishQwSendBO.getEnterpriseId());
            dealQwSendDTO.setRefreshType(2);
            DealQwSendDTO.QwSendMsgBO qwSendMsgBO = EntityUtil.changeEntityByJSON(DealQwSendDTO.QwSendMsgBO.class, qwSendMsg);
            dealQwSendDTO.setQwSendMsg(qwSendMsgBO);
            dealQwSendDTO.setFinishQwSend(finishQwSendBO);
            MqUtils.sendMessageToMQ("qwSendRefreshByMQ", JSON.toJSONString(dealQwSendDTO), 30);
        }else {
            if (tryCount != null && tryCount >= 5) {
                return;
            }
            if (tryCount == null) {
                tryCount = 0;
            }
            // 重新刷新
            DealQwSendDTO dealQwSendDTO = new DealQwSendDTO();
            dealQwSendDTO.setEnterpriseId(finishQwSendBO.getEnterpriseId());
            dealQwSendDTO.setRefreshType(1);
            dealQwSendDTO.setFinishQwSend(finishQwSendBO);
            dealQwSendDTO.setTryCount(++tryCount);
            MqUtils.sendMessageToMQ("qwSendRefreshByMQ", JSON.toJSONString(dealQwSendDTO), 60);
        }
    }

    @Override
    public void refreshQwSendLog(DealQwSendDTO dealQwSendDTO) {
        DealQwSendDTO.QwSendMsgBO qwSendMsg = dealQwSendDTO.getQwSendMsg();
        List<GroupSendResultBO> sendResultList = getSendResultList(qwSendMsg);
        if (CollectionUtils.isEmpty(sendResultList)) {
            return;
        }
        log.info("刷新企微群发结果:{}", qwSendMsg.getMsgId());
        List<TabQwSendLog> entities;
        List<List<GroupSendResultBO>> partition = Lists.partition(sendResultList, 1000);
        for (List<GroupSendResultBO> groupSendResultBOS : partition) {
            List<String> externalUseridList = groupSendResultBOS.stream().map(GroupSendResultBO::getExternalUserid).collect(Collectors.toList());
            List<TabHaobanExternalClerkRelated> list = externalClerkRelatedMapper.listByExternalUserIdList(qwSendMsg.getStaffId(), qwSendMsg.getEnterpriseId(), externalUseridList);
            if (CollectionUtil.isEmpty(list)) {
                continue;
            }
            Map<String, String> map = list.stream().collect(Collectors.toMap(TabHaobanExternalClerkRelated::getExternalUserId, TabHaobanExternalClerkRelated::getMemberId, (e, x) -> e));
            entities = sendResultList.stream().map(o -> {
                String externalUserid = o.getExternalUserid();
                String memberId = map.get(externalUserid);
                if (StringUtils.isBlank(memberId)) {
                    return null;
                }
                TabQwSendLog qwSendLog = new TabQwSendLog();
                qwSendLog.setId(UniqueIdUtils.uniqueLong());
                qwSendLog.setMemberId(memberId);
                qwSendLog.setExternalUserId(externalUserid);
                qwSendLog.setClerkId(qwSendMsg.getClerkId());
                qwSendLog.setStaffId(qwSendMsg.getStaffId());
                qwSendLog.setMsgId(qwSendMsg.getMsgId());
                qwSendLog.setSendStatus(Objects.equals(o.getStatus(), 1) ? 1 : 2);
                qwSendLog.setSendTime(o.getSendTime());
                qwSendLog.setFailReasonType(o.getStatus());
                qwSendLog.setWxEnterpriseId(qwSendMsg.getWxEnterpriseId());
                qwSendLog.setEnterpriseId(qwSendMsg.getEnterpriseId());
                return qwSendLog;
            }).filter(Objects::nonNull).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(entities)) {
                qwSendLogMapper.insertBatch(entities);
                List<ContactFollowBatchQDTO.MemberFollow> memberList = new ArrayList<>();
                entities.forEach(log ->{
                    if (!Objects.equals(log.getSendStatus(), 1)) {
                        return;
                    }
                    if (StringUtils.isBlank(log.getMemberId())) {
                        return;
                    }
                    memberList.add(new ContactFollowBatchQDTO.MemberFollow(log.getMemberId(), log.getExternalUserId(), log.getSendTime()));
                });
                saveFollowMQ(qwSendMsg.getEnterpriseId(),qwSendMsg.getClerkId(), memberList,dealQwSendDTO.getFinishQwSend());
            }
            entities.clear();
        }

    }

    private List<GroupSendResultBO> getSendResultList(DealQwSendDTO.QwSendMsgBO qwSendMsg) {
        String newWxUserId = messageApiService.getNewWxUserIdByStaffId(qwSendMsg.getWxEnterpriseId(), qwSendMsg.getStaffId());
        log.info("查询{},{},{}", qwSendMsg.getWxEnterpriseId(), qwSendMsg.getStaffId(), newWxUserId);
        if (StringUtils.isBlank(newWxUserId)) {
            log.error("未查询到userid");
            return Collections.emptyList();
        }
        List<GroupSendResultBO> sendResultList = getSendResult(qwSendMsg.getWxEnterpriseId(), qwSendMsg.getMsgId(), newWxUserId);
        //判断是否已经发送
        return sendResultList.stream().filter(dto -> !Objects.equals(dto.getStatus(), 0))
                .collect(Collectors.toList());
    }

    public List<GroupSendResultBO> getSendResult(String wxEnterpriseId, String msgId, String userId) {
        List<GroupSendResultBO> sendResultList = new ArrayList<>();
        //油标
        String nextCursor = null;
        //计数器
        int count = 1;
        //循环获取
        while (count <= 20) {
            JSONResponse jsonResponse = memberUnionidRelatedApiService.resultExternalMessage(wxEnterpriseId, msgId, nextCursor, userId);
            List<GroupSendResultBO> groupSendResultList = null;
            try {
                groupSendResultList = this.getUserIdList(jsonResponse);
            } catch (BusinessException e) {
                log.error("获取群发结果异常:{}", e.getMsg());
            }
            if (groupSendResultList != null) {
                sendResultList.addAll(groupSendResultList);
            }
            //游标不存在, 直接结束循环
            if (!jsonResponse.getReturnMap().containsKey("next_cursor")
                    || StringUtils.isBlank(jsonResponse.getReturnMap().get("next_cursor").toString())) {
                break;
            }
            //游标修改
            nextCursor = jsonResponse.getReturnMap().get("next_cursor").toString();
            //计数器递增
            count++;
        }
        return sendResultList;
    }

    private List<GroupSendResultBO> getUserIdList(JSONResponse jsonResponse) throws BusinessException{
        log.info("errorCode:{}, message:{}", jsonResponse.getErrorCode(), jsonResponse.getErrorMessage());
        if (jsonResponse.getErrorCode() == 41063) {
            log.info("异常-群发消息正在被派发中：{}", JSONObject.toJSONString(jsonResponse));
            throw new BusinessException("41063","群发消息正在被派发中，请稍后再试");
        } else if (jsonResponse.getErrorCode() == 45033) {
            log.info("异常-接口超出限制：需要重新执行");
            throw new BusinessException("45033","接口超出限制：需要重新执行");
        } else if (jsonResponse.getErrorCode() == 40003) {
            log.info("该导购已不是企微员工，无法刷新群发结果");
            throw new BusinessException("40003","该导购已不是企微员工，无法刷新群发结果");
        } else if (jsonResponse.getErrorCode() == 60111) {
            log.info("UserID不存在，无法刷新群发结果");
            throw new BusinessException("60111","UserID不存在，无法刷新群发结果");
        } else if(jsonResponse.getErrorCode() == 41047) {
            // 无效的企业群发消息id
            log.info("无效的企业群发消息id");
            throw new BusinessException("41047","无效的企业群发消息id");
        }else if (jsonResponse.getErrorCode() != 0) {
            log.info("异常-：{}", JSONObject.toJSONString(jsonResponse));
            throw new BusinessException("-1","群发消息异常");
        }
        List<?> list = jsonResponse.getList();
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return EntityUtil.changeEntityListByJSON(GroupSendResultBO.class, list);
    }

    private void saveFollowMQ(String enterpriseId,String clerkId,List<ContactFollowBatchQDTO.MemberFollow> memberList,DealQwSendDTO.FinishQwSendBO finishQwSendBO) {
        if (org.apache.commons.collections.CollectionUtils.isEmpty(memberList)) {
            return;
        }
        if (finishQwSendBO == null) {
            return;
        }
        Integer followType = null;
        String followRemark = null;
        Integer bizType = finishQwSendBO.getBizType();
        List<ClerkShareGoodsLogDTO> shareGoodsList = finishQwSendBO.getShareGoodsList();
        if (Objects.equals(bizType, 1)) {
            followType = ContactFollowTypeEnum.MATERIAL.getCode();
            followRemark = "向客户发送了营销素材";
        } else if (Objects.equals(bizType, 2)) {
            followType = ContactFollowTypeEnum.PRODUCT.getCode();
            followRemark = "向客户发送了" + shareGoodsList.size() + "款商品";
        } else {
            return;
        }
        ContactFollowBatchQDTO batchQDTO = new ContactFollowBatchQDTO();
        batchQDTO.setEnterpriseId(enterpriseId);
        batchQDTO.setMemberList(memberList);
        batchQDTO.setClerkId(clerkId);
        batchQDTO.setFollowType(followType);
        batchQDTO.setFollowRemark(followRemark);
        MqUtils.sendMessageToMQ("saveBatchFollowForMQ", JSON.toJSONString(batchQDTO));
        if (Objects.equals(bizType, 2)) {
            saveShareMaterialLog(enterpriseId, shareGoodsList, memberList);
        }
    }

    private void saveShareMaterialLog(String enterpriseId,List<ClerkShareGoodsLogDTO> shareGoodsList,List<ContactFollowBatchQDTO.MemberFollow> memberList) {
        List<ClerkShareGoodsLogDTO> list = Lists.newArrayList();
        for (ContactFollowBatchQDTO.MemberFollow memberInfo : memberList) {
            for (ClerkShareGoodsLogDTO goodsLogDTO : shareGoodsList) {
                ClerkShareGoodsLogDTO temp = EntityUtil.changeEntityByJSON(ClerkShareGoodsLogDTO.class, goodsLogDTO);
                temp.setExternalUserId(memberInfo.getExternalUserId());
                temp.setMemberId(memberInfo.getMemberId());
                list.add(temp);
            }
            //更新会员推荐时间更新
            MemberExtraPropertyReq memberExtraPropertyReq = new MemberExtraPropertyReq();
            memberExtraPropertyReq.setEnterpriseId(enterpriseId);
            memberExtraPropertyReq.setMemberId(memberInfo.getMemberId());
            memberExtraPropertyReq.setExtraKey(MemberExtKeyEnum.MEMBER_GOODS_SUGGEST_TIME.key());
            memberExtraPropertyReq.setExtraValue(memberInfo.getFollowTime().getTime());
            try {
                memberExtraPropertyApiService.updateMemberExtraProperty(memberExtraPropertyReq);
            } catch (Exception e) {
                log.info("更新会员推荐时间更新异常,", e);
            }
        }
        materialShareLogApiService.saveClerkShareRecommendLog(list);
    }
}
