package com.tzld.piaoquan.offline.job;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.tzld.piaoquan.growth.common.common.constant.TimeConstant;
import com.tzld.piaoquan.growth.common.common.enums.FieshuTableColumnDataTypeEnum;
import com.tzld.piaoquan.growth.common.common.enums.MessageAttachmentTypeEnum;
import com.tzld.piaoquan.growth.common.component.HttpPoolClient;
import com.tzld.piaoquan.growth.common.component.ProxyHttpPoolClient;
import com.tzld.piaoquan.growth.common.dao.mapper.*;
import com.tzld.piaoquan.growth.common.model.bo.*;
import com.tzld.piaoquan.growth.common.model.po.*;
import com.tzld.piaoquan.growth.common.service.*;
import com.tzld.piaoquan.growth.common.utils.DateUtil;
import com.tzld.piaoquan.growth.common.utils.LarkRobotUtil;
import com.tzld.piaoquan.growth.common.utils.MessageUtil;
import com.tzld.piaoquan.growth.common.utils.page.Page;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.tzld.piaoquan.growth.common.common.constant.MessageConstant.MAX_VIDEO_NUM;
import static com.tzld.piaoquan.growth.common.common.constant.WeComConstant.*;
import static com.tzld.piaoquan.growth.common.common.enums.SourceEnum.HISTORICAL_TOP;
import static com.tzld.piaoquan.growth.common.common.enums.SourceEnum.MANUAL;

@Slf4j
@Component
public class WeComHistoryDataJob {

    @Autowired
    private HttpPoolClient httpPoolClient;

    @Autowired
    private ProxyHttpPoolClient proxyHttpPoolClient;

    @Autowired
    private WeComAccessTokenService weComAccessTokenService;

    @Autowired
    private WeComUserMapper weComUserMapper;

    @Autowired
    private HistoryMessageMapper historyMessageMapper;

    @Autowired
    private HistoryMessageBackupMapper historyMessageBackupMapper;

    @Autowired
    private HistoryMessageService historyMessageService;

    @Autowired
    private MessageAttachmentService messageAttachmentService;

    @Autowired
    private StaffMapper staffMapper;

    @Autowired
    private WeComUserService weComUserService;

    @Autowired
    private CorpMapper corpMapper;

    @Autowired
    private MessageAttachmentMapper messageAttachmentMapper;

    @Autowired
    private SendMsgResultMapper sendMsgResultMapper;

    @Autowired
    private AttachmentWithMsgResultMapper attachmentWithMsgResultMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private WeComSendService weComSendService;

    private static final String START_TIME_KEY = "start_time_key_%s";

    @XxlJob("saveHistoryMessageJob1")
    public ReturnT<String> saveHistoryMessageJob1(String param) {
        CorpExample example = new CorpExample();
        List<Corp> corps = corpMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(corps)) {
            return ReturnT.SUCCESS;
        }
        for (Corp corp : corps) {
            String key = String.format(START_TIME_KEY, corp.getId());
            Integer startTimeVal = (Integer) redisTemplate.opsForValue().get(key);
            Long dayStartTime = DateUtil.getBeforeDayStart(0);
            Long startTime;
            if (startTimeVal == null) {
                startTime = DateUtil.getBeforeDayStart(0);
            } else {
                if (dayStartTime > startTimeVal) {
                    startTime = dayStartTime;
                } else {
                    startTime = (long) startTimeVal;
                }
            }
            Long endTime = System.currentTimeMillis() / 1000;
            selectGroupMsgList(startTime, endTime, corp.getId(), null);
            boolean isAllSend = true;
            long notSentCount = newSelectAlertHistoryMessage(startTime, endTime + TimeConstant.HOUR, corp.getId(), corp.getName());
            if (notSentCount > 0) {
                isAllSend = false;
            }
            if (isAllSend) {
                redisTemplate.opsForValue().set(key, endTime, 1, TimeUnit.DAYS);
            }
        }
        return ReturnT.SUCCESS;
    }

    private long newSelectAlertHistoryMessage(Long startTime, Long endTime, Long corpId, String corpName) {
        StaffExample staffExample = new StaffExample();
        staffExample.createCriteria().andCorpIdEqualTo(corpId).andIsDeleteEqualTo(0);
        List<Staff> staffList = staffMapper.selectByExample(staffExample);
        ArrayList<Integer> statusList = Lists.newArrayList(0, 1, 2, 3);
        List<SendDetail> sendDetailList = new ArrayList<>();
        for (Staff staff : staffList) {
            SendDetail sendDetail = new SendDetail();
            sendDetail.setRemark(staff.getRemark());
            sendDetail.setStaffId(staff.getId());
            List<Long> countList = new ArrayList<>();
            for (Integer status : statusList) {
                SendMsgResultExample example = new SendMsgResultExample();
                example.createCriteria().andCreateTimeBetween(new Date(startTime * 1000), new Date(endTime * 1000))
                        .andStaffIdEqualTo(staff.getId())
                        .andStatusEqualTo(status)
                        .andIsDeleteEqualTo(0);
                long l = sendMsgResultMapper.countByExample(example);
                countList.add(l);
            }
            sendDetail.setSendCountList(countList);
            sendDetailList.add(sendDetail);
        }
        long allCount = 0;
        long notSendCount = 0;
        long successSendCount = 0;
        long notFriendCount = 0;
        long failSendCount = 0;
        List<JSONObject> rows = new ArrayList<>();
        for (SendDetail sendDetail : sendDetailList) {
            List<Long> sendCountList = sendDetail.getSendCountList();
            if (CollectionUtils.isEmpty(sendCountList)) {
                continue;
            }
            long count = sendCountList.get(0) + sendCountList.get(1) + sendCountList.get(2) + sendCountList.get(3);
            if (count == 0) {
                continue;
            }
            allCount += count;
            notSendCount += sendCountList.get(0);
            successSendCount += sendCountList.get(1);
            notFriendCount += sendCountList.get(2);
            failSendCount += sendCountList.get(3);
            //if (sendCountList.get(0) > 0 && !specialStaffIdList.contains(sendDetail.getStaffId())) {
            //    LarkRobotUtil.sendMessage(sendDetail.getRemark() + "存在未发送记录，请检查");
            //    LarkRobotUtil.sendTipMessage(sendDetail.getRemark() + "存在未发送记录，请检查");
            //    //8点前报警
            //    if (DateUtil.getHourOfDay() < 9 && (corpId == 1 || corpId == 3)) {
            //        LarkRobotUtil.sendNotPushMessage("<at user_id=\"all\">所有人</at> " + sendDetail.getRemark() + " 存在未发送记录，请检查");
            //    }
            //}

            JSONObject row = new JSONObject();
            row.put("name", sendDetail.getRemark());
            row.put("totalCount", count);
            row.put("notSendCount", sendCountList.get(0));
            row.put("successSendCount", sendCountList.get(1));
            row.put("notFriendCount", sendCountList.get(2));
            row.put("failSendCount", sendCountList.get(3));
            rows.add(row);
        }

        JSONObject row = new JSONObject();
        row.put("name", "TOTAL");
        row.put("totalCount", allCount);
        row.put("notSendCount", notSendCount);
        row.put("successSendCount", successSendCount);
        row.put("notFriendCount", notFriendCount);
        row.put("failSendCount", failSendCount);
        rows.add(row);
        if (allCount > 0) {
            JSONObject bodyParam = buildCheckQWMsg(corpName, rows);
            LarkRobotUtil.sendMessage(bodyParam);
            LarkRobotUtil.sendTipMessage(bodyParam);
            if (DateUtil.getHourOfDay() < 9 && (corpId == 1 || corpId == 3)) {
                LarkRobotUtil.sendNotPushMessage(bodyParam);
            }
        }
        return notSendCount;
    }

    private JSONObject buildCheckQWMsg(String corpName, List<JSONObject> rows) {
        List<FeishuTableDTO.Column> columns = buildCheckQWMsgSendColumns();
        FeishuTableDTO tableDTO = FeishuTableDTO.createTable(corpName, columns, rows, true);
        JSONObject content = JSONObject.parseObject(JSONObject.toJSONString(tableDTO));
        JSONObject bodyParam = new JSONObject();
        bodyParam.put("msg_type", "interactive");
        bodyParam.put("card", content);
        return bodyParam;
    }

    private List<FeishuTableDTO.Column> buildCheckQWMsgSendColumns() {
        List<FeishuTableDTO.Column> columns = new ArrayList<>();
        FeishuTableDTO.Column nameColumn = FeishuTableDTO.createFeishuColumns(
                FieshuTableColumnDataTypeEnum.TEXT.getType(), "name", "账号名称", null);
        columns.add(nameColumn);
        FeishuTableDTO.Column totalCountColumn = FeishuTableDTO.createFeishuColumns(
                FieshuTableColumnDataTypeEnum.TEXT.getType(), "totalCount", "总发送数量", null);
        columns.add(totalCountColumn);
        FeishuTableDTO.Column notSendCountColumn = FeishuTableDTO.createFeishuColumns(
                FieshuTableColumnDataTypeEnum.TEXT.getType(), "notSendCount", "未发送数量", null);
        columns.add(notSendCountColumn);
        FeishuTableDTO.Column successSendCountColumn = FeishuTableDTO.createFeishuColumns(
                FieshuTableColumnDataTypeEnum.TEXT.getType(), "successSendCount", "已发送数量", null);
        columns.add(successSendCountColumn);
        FeishuTableDTO.Column notFriendCountColumn = FeishuTableDTO.createFeishuColumns(
                FieshuTableColumnDataTypeEnum.TEXT.getType(), "notFriendCount", "不是好友发送失败数量", null);
        columns.add(notFriendCountColumn);
        FeishuTableDTO.Column failSendCountColumn = FeishuTableDTO.createFeishuColumns(
                FieshuTableColumnDataTypeEnum.TEXT.getType(), "failSendCount", "已经收到其他群发消息失败发送数量", null);
        columns.add(failSendCountColumn);
        return columns;
    }


    @XxlJob("saveHistoryMessageJob")
    public ReturnT<String> selectHistoryMessageByDay(String param) {
        XxlJobParam xxlJobParam = new XxlJobParam();
        if (StringUtils.isNotEmpty(param)) {
            xxlJobParam = JSONObject.parseObject(param, XxlJobParam.class);
        }
        if (xxlJobParam.getStartTime() == null) {
            HistoryMessageExample example = new HistoryMessageExample();
            example.setOrderByClause("create_time desc");
            example.setPage(new Page<>(1, 1));
            List<HistoryMessage> historyMessages = historyMessageMapper.selectByExample(example);
            if (CollectionUtils.isEmpty(historyMessages)) {
                xxlJobParam.setStartTime(1721404800L);
            } else {
                xxlJobParam.setStartTime(historyMessages.get(0).getCreateTime().getTime() / 1000);
            }

        }
        if (xxlJobParam.getEndTime() == null) {
            xxlJobParam.setEndTime(System.currentTimeMillis() / 1000);
        }
        Long startTime = xxlJobParam.getStartTime();
        Long endTime = xxlJobParam.getEndTime();
        CorpExample example = new CorpExample();
        if (xxlJobParam.getCorpId() != null) {
            example.createCriteria().andIdEqualTo(xxlJobParam.getCorpId());
        }
        List<Corp> corps = corpMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(corps)) {
            return ReturnT.SUCCESS;
        }
        for (Corp corp : corps) {
            for (; startTime < endTime; startTime += TimeConstant.DAY) {
                selectGroupMsgList(startTime, Math.min(startTime + TimeConstant.DAY, endTime), corp.getId(), xxlJobParam.getStaffId());
            }
        }
        if (xxlJobParam.getIsAlert() != null && xxlJobParam.getIsAlert() == 1) {
            for (Corp corp : corps) {
                selectAlertHistoryMessage(xxlJobParam.getStartTime(), xxlJobParam.getEndTime(), corp.getId(), corp.getName());
            }
        }
        return ReturnT.SUCCESS;
    }

    private void selectAlertHistoryMessage(Long startTime, Long endTime, Long corpId, String corpName) {
        StaffExample staffExample = new StaffExample();
        List<Staff> staffList = staffMapper.selectByExample(staffExample);
        ArrayList<Integer> statusList = Lists.newArrayList(0, 1, 2, 3);
        List<SendDetail> sendDetailList = new ArrayList<>();
        for (Staff staff : staffList) {
            SendDetail sendDetail = new SendDetail();
            sendDetail.setRemark(staff.getRemark());
            sendDetail.setStaffId(staff.getId());
            List<Long> countList = new ArrayList<>();
            for (Integer status : statusList) {
                HistoryMessageExample example = new HistoryMessageExample();
                example.createCriteria().andSendTimeBetween(new Date(startTime * 1000), new Date(endTime * 1000))
                        .andStaffIdEqualTo(staff.getId())
                        .andStatusEqualTo(status)
                        .andIsDeleteEqualTo(0)
                        .andCorpIdEqualTo(corpId);
                long l = historyMessageMapper.countByExample(example);
                countList.add(l / MAX_VIDEO_NUM);
            }
            sendDetail.setSendCountList(countList);
            sendDetailList.add(sendDetail);
        }
        List<JSONObject> rows = new ArrayList<>();
        for (SendDetail sendDetail : sendDetailList) {
            List<Long> sendCountList = sendDetail.getSendCountList();
            if (CollectionUtils.isEmpty(sendCountList)) {
                continue;
            }
            long count = sendCountList.get(0) + sendCountList.get(1) + sendCountList.get(2) + sendCountList.get(3);
            if (count == 0) {
                continue;
            }


            //if (count == sendCountList.get(0)) {
            //    //LarkRobotUtil.sendMessage(sendDetail.getRemark() + "存在未发送记录，请检查");
            //    if (sendDetail.getStaffId() == 3) {
            //        //LarkRobotUtil.sendTipMessage(sendDetail.getRemark() + "存在未发送记录，请检查");
            //    } else {
            //        LarkRobotUtil.sendNotPushMessage("<at user_id=\"all\">所有人</at> " + sendDetail.getRemark() + " 存在未发送记录，请检查");
            //    }
            //}
            JSONObject row = new JSONObject();
            row.put("name", sendDetail.getRemark());
            row.put("totalCount", count);
            row.put("notSendCount", sendCountList.get(0));
            row.put("successSendCount", sendCountList.get(1));
            row.put("notFriendCount", sendCountList.get(2));
            row.put("failSendCount", sendCountList.get(3));
            rows.add(row);
        }
        JSONObject bodyParam = buildCheckQWMsg(corpName, rows);
        LarkRobotUtil.sendMessage(bodyParam);
        LarkRobotUtil.sendTipMessage(bodyParam);
        if (DateUtil.getHourOfDay() < 9 && (corpId == 1 || corpId == 3)) {
            LarkRobotUtil.sendNotPushMessage(bodyParam);
        }
    }

    private void selectGroupMsgList(Long startTime, Long endTime, Long corpId, Long staffId) {
        delHistoryMessageList(startTime, endTime, corpId, staffId);
        try {
            String cursor = "";
            do {
                String res = getGroupMsgList(startTime, endTime, cursor, corpId);
                JSONObject jsonObject = JSONObject.parseObject(res);
                Integer errCode = jsonObject.getInteger("errcode");
                if (errCode != 0) {
                    LarkRobotUtil.sendMessage("selectGroupMsgList error startTime = " + startTime + "endTime = " + endTime);
                    log.error("selectGroupMsgList error startTime={}, endTime={}", startTime, endTime);
                    return;
                }
                JSONArray groupMsgList = jsonObject.getJSONArray("group_msg_list");
                if (CollectionUtils.isEmpty(groupMsgList)) {
                    continue;
                }
                for (int i = 0; i < groupMsgList.size(); i++) {
                    JSONObject groupMsg = groupMsgList.getJSONObject(i);
                    JSONArray attachments = groupMsg.getJSONArray("attachments");
                    String msgId = groupMsg.getString("msgid");
                    String textContent = Optional.ofNullable(groupMsg.getJSONObject("text"))
                            .map(textObj -> textObj.getString("content"))
                            .orElse(null);
                    Long createTime = null;
                    if (groupMsg.getLong("create_time") != null) {
                        createTime = groupMsg.getLong("create_time") * 1000;
                    }

                    List<MiniprogramRecord> miniprogramRecordList = new ArrayList<>();
                    List<MessageAttachment> messageAttachmentList = new ArrayList<>();
                    if (!CollectionUtils.isEmpty(attachments)) {
                        for (int j = 0; j < attachments.size(); j++) {
                            MessageAttachment messageAttachment = new MessageAttachment();
                            String msgtype = attachments.getJSONObject(j).getString("msgtype");
                            if (Objects.equals(MessageAttachmentTypeEnum.IMAGE.getType(), msgtype)) {
                                JSONObject image = attachments.getJSONObject(j)
                                        .getJSONObject(MessageAttachmentTypeEnum.IMAGE.getType());
                                messageAttachment.setMediaId(image.getString("media_id"));
                                messageAttachment.setPicUrl(image.getString("pic_url"));
                                messageAttachment.setType(MessageAttachmentTypeEnum.IMAGE.getCode());
                                messageAttachmentList.add(messageAttachment);
                            }

                            if (Objects.equals(MessageAttachmentTypeEnum.LINK.getType(), msgtype)) {
                                JSONObject link = attachments.getJSONObject(j)
                                        .getJSONObject(MessageAttachmentTypeEnum.LINK.getType());

                                messageAttachment.setTitle(link.getString("title"));
                                messageAttachment.setPicUrl(link.getString("picurl"));
                                messageAttachment.setDesc(link.getString("desc"));
                                messageAttachment.setUrl(link.getString("url"));
                                messageAttachment.setType(MessageAttachmentTypeEnum.LINK.getCode());
                                messageAttachmentList.add(messageAttachment);

                            }

                            if (Objects.equals(MessageAttachmentTypeEnum.MINI_PROGRAM.getType(), msgtype)) {
                                JSONObject miniprogram = attachments.getJSONObject(j)
                                        .getJSONObject(MessageAttachmentTypeEnum.MINI_PROGRAM.getType());
                                if (miniprogram == null) {
                                    continue;
                                }
                                MiniprogramRecord miniprogramRecord = new MiniprogramRecord();

                                String title = miniprogram.getString("title");
                                String appid = miniprogram.getString("appid");
                                String page = miniprogram.getString("page");
                                Long videoId = MessageUtil.getVideoId(page);

                                miniprogramRecord.setVideoId(videoId);
                                miniprogramRecord.setAttachmentIdx(j + 1);
                                miniprogramRecordList.add(miniprogramRecord);

                                messageAttachment.setAppid(appid);
                                messageAttachment.setPage(page);
                                messageAttachment.setTitle(title);
                                messageAttachment.setMiniprogramVideoId(videoId);
                                messageAttachment.setType(MessageAttachmentTypeEnum.MINI_PROGRAM.getCode());
                                messageAttachmentList.add(messageAttachment);
                            }
                        }
                    }
                    List<String> carrierIdList = selectGroupMsgTask(msgId, corpId);
                    if (CollectionUtils.isEmpty(carrierIdList)) {
                        continue;
                    }
                    for (String carrierId : carrierIdList) {
                        StaffExample example = new StaffExample();
                        example.createCriteria().andCarrierIdEqualTo(carrierId);
                        List<Staff> staffList = staffMapper.selectByExample(example);
                        if (CollectionUtils.isEmpty(staffList)) {
                            LarkRobotUtil.sendMessage("企微推送报警：carrierId不存在请检查 " + carrierId);
                            continue;
                        }
                        //指定id以后  过滤其他id
                        if (staffId != null) {
                            if (!Objects.equals(staffList.get(0).getId(), staffId)) {
                                continue;
                            }
                        }
                        List<ExternalUser> externalUsers = selectGroupMsgSendResult(msgId, carrierId, corpId);
                        if (CollectionUtils.isEmpty(externalUsers)) {
                            continue;
                        }
                        List<Long> attachmentIds = new ArrayList<>();
                        if (!CollectionUtils.isEmpty(messageAttachmentList)) {
                            for (MessageAttachment messageAttachment : messageAttachmentList) {
                                messageAttachment.setStaffId(staffList.get(0).getId());
                            }
                            attachmentIds = messageAttachmentService
                                    .addMessageAttachment(messageAttachmentList, createTime);
                        }
                        insertHistoryMessageList(msgId, staffList.get(0), externalUsers, miniprogramRecordList,
                                createTime, corpId, startTime, endTime, attachmentIds, textContent);
                    }
                }
                String nextCursor = jsonObject.getString("next_cursor");
                if (cursor.equals(nextCursor)) {
                    break;
                }
                cursor = nextCursor;
            } while (StringUtils.isNotEmpty(cursor));
        } catch (IOException e) {
            LarkRobotUtil.sendMessage("selectGroupMsgList error" + e);
            log.error("selectGroupMsgList error", e);
        }
    }

    private List<ExternalUser> selectGroupMsgSendResult(String msgId, String carrierId, Long corpId) throws IOException {
        List<ExternalUser> resList = new ArrayList<>();
        String cursor = "";
        do {
            String res = getGroupMsgSendResult(msgId, carrierId, cursor, corpId);
            JSONObject jsonObject = JSONObject.parseObject(res);
            Integer errCode = jsonObject.getInteger("errcode");
            if (errCode != 0) {
                String errmsg = jsonObject.getString("errmsg");
                log.error("selectGroupMsgSendResult error msgId={} carrierId={} errCode={} errmsg={}", msgId, carrierId, errCode, errmsg);
                return resList;
            }
            JSONArray sendList = jsonObject.getJSONArray("send_list");
            for (int i = 0; i < sendList.size(); i++) {
                JSONObject send = sendList.getJSONObject(i);
                ExternalUser externalUser = new ExternalUser();
                externalUser.setExternalUserId(send.getString("external_userid"));
                externalUser.setStatus(send.getInteger("status"));
                if (send.getLong("send_time") != null) {
                    externalUser.setSendTime(send.getLong("send_time") * 1000);
                }
                resList.add(externalUser);
            }
            String nextCursor = jsonObject.getString("next_cursor");
            if (cursor.equals(nextCursor)) {
                break;
            }
            cursor = nextCursor;
        } while (StringUtils.isNotEmpty(cursor));
        return resList;
    }

    private String getGroupMsgSendResult(String msgId, String carrierId, String cursor, Long corpId) throws IOException {
        String accessToken = weComAccessTokenService.getWeComAccessToken(corpId);
        String url = POST_WE_COM_GROUP_MSG_SEND_RESULT
                + "?access_token=" + accessToken;
        JSONObject param = new JSONObject();
        param.put("msgid", msgId);
        param.put("userid", carrierId);
        param.put("limit", 1000);
        if (StringUtils.isNotEmpty(cursor)) {
            param.put("cursor", cursor);
        }
        if (corpId == 1L) {
            return httpPoolClient.post(url, param.toJSONString());
        } else {
            return proxyHttpPoolClient.post(url, param.toJSONString());
        }
    }

    private List<String> selectGroupMsgTask(String msgId, Long corpId) throws IOException {
        List<String> resList = new ArrayList<>();
        String cursor = "";
        do {
            String res = getGroupMsgTask(msgId, cursor, corpId);
            if (StringUtils.isEmpty(res)) {
                break;
            }
            JSONObject jsonObject = JSONObject.parseObject(res);
            Integer errCode = jsonObject.getInteger("errcode");
            if (errCode != 0) {
                String errmsg = jsonObject.getString("errmsg");
                log.error("selectGroupMsgTask error msgId={} errCode={} errmsg={}", msgId, errCode, errmsg);
                return resList;
            }
            JSONArray taskList = jsonObject.getJSONArray("task_list");
            for (int i = 0; i < taskList.size(); i++) {
                JSONObject task = taskList.getJSONObject(i);
                String userId = task.getString("userid");
                resList.add(userId);
            }
            String nextCursor = jsonObject.getString("next_cursor");
            if (cursor.equals(nextCursor)) {
                break;
            }
            cursor = nextCursor;
        } while (StringUtils.isNotEmpty(cursor));
        return resList;
    }

    private String getGroupMsgTask(String msgId, String cursor, Long corpId) throws IOException {
        String accessToken = weComAccessTokenService.getWeComAccessToken(corpId);
        String url = POST_WE_COM_GROUP_MSG_TASK
                + "?access_token=" + accessToken;
        JSONObject param = new JSONObject();
        param.put("msgid", msgId);
        param.put("limit", 1000);
        if (StringUtils.isNotEmpty(cursor)) {
            param.put("cursor", cursor);
        }
        if (corpId == 1L) {
            return httpPoolClient.post(url, param.toJSONString());
        } else {
            return proxyHttpPoolClient.post(url, param.toJSONString());
        }
    }

    private void delHistoryMessageList(Long startTime, Long endTime, Long corpId, Long staffId) {
        HistoryMessageExample example = new HistoryMessageExample();
        HistoryMessageExample.Criteria criteria =
                example.createCriteria().andSendTimeBetween(new Date(startTime * 1000), new Date(endTime * 1000))
                        .andCorpIdEqualTo(corpId);
        if (staffId != null) {
            criteria.andStaffIdEqualTo(staffId);
        }
        historyMessageMapper.deleteByExample(example);

    }

    private void insertHistoryMessageList(String msgId, Staff staff, List<ExternalUser> externalUsers,
                                          List<MiniprogramRecord> miniprogramRecordList,
                                          Long createTime, Long corpId, Long startTime, Long endTime,
                                          List<Long> attachmentIds, String textContent) {
        if (CollectionUtils.isEmpty(externalUsers)) {
            return;
        }
        MessageAttachmentExample example = new MessageAttachmentExample();
        example.createCriteria().andStaffIdEqualTo(staff.getId())
                .andSendTimeBetween(new Date(startTime * 1000), new Date(endTime * 1000));
        List<MessageAttachment> messageAttachments = messageAttachmentMapper.selectByExample(example);
        Set<Long> guaranteedSet = new HashSet<>();
        if (!CollectionUtils.isEmpty(messageAttachments)) {
            guaranteedSet = messageAttachments.stream().map(MessageAttachment::getMiniprogramVideoId).collect(Collectors.toSet());
        }
        Long sendTime = externalUsers.stream()
                .map(ExternalUser::getSendTime).filter(Objects::nonNull).findFirst().orElse(null);
        List<HistoryMessage> historyMessageList = new ArrayList<>();
        List<Long> sendMsgResultIds = new ArrayList<>();
        for (ExternalUser externalUser : externalUsers) {
            Long userId = weComUserMapper.selectIdByExternalUserId(externalUser.getExternalUserId());
            if (userId == null) {
                continue;
            }
            Integer status = externalUser.getStatus();
            if (status == 2) {
                weComUserService.delStaffWithUser(userId, staff.getId(), sendTime);
            }
            SendMsgResultExample sendMsgResultExample = new SendMsgResultExample();
            sendMsgResultExample.createCriteria().andMsgIdEqualTo(msgId).andUserIdEqualTo(userId).andStaffIdEqualTo(staff.getId());
            List<SendMsgResult> sendMsgResults = sendMsgResultMapper.selectByExample(sendMsgResultExample);
            if (CollectionUtils.isEmpty(sendMsgResults)) {
                SendMsgResult sendMsgResult = new SendMsgResult();
                sendMsgResult.setMsgId(msgId);
                sendMsgResult.setUserId(userId);
                sendMsgResult.setTextContent(textContent);
                sendMsgResult.setStaffId(staff.getId());
                if (sendTime != null) {
                    sendMsgResult.setSendTime(new Date(sendTime));
                }
                sendMsgResult.setStatus(status);
                sendMsgResultMapper.insertSelective(sendMsgResult);
                sendMsgResultIds.add(sendMsgResult.getId());
            } else {
                SendMsgResult sendMsgResult = sendMsgResults.get(0);
                if (sendTime != null) {
                    sendMsgResult.setSendTime(new Date(sendTime));
                }
                sendMsgResult.setStatus(status);
                sendMsgResultMapper.updateByPrimaryKeySelective(sendMsgResult);
                sendMsgResultIds.add(sendMsgResult.getId());
            }
            //小程序发送历史
            if (!CollectionUtils.isEmpty(miniprogramRecordList)) {
                for (MiniprogramRecord miniprogramRecord : miniprogramRecordList) {
                    HistoryMessage historyMessage = new HistoryMessage();
                    if (externalUser.getSendTime() != null) {
                        historyMessage.setSendTime(new Date(externalUser.getSendTime()));
                    } else {
                        if (sendTime != null) {
                            historyMessage.setSendTime(new Date(sendTime));
                        } else if (createTime != null) {
                            historyMessage.setSendTime(new Date(createTime));
                        }
                    }
                    Long videoId = miniprogramRecord.getVideoId();
                    historyMessage.setAttachmentIdx(miniprogramRecord.getAttachmentIdx());
                    historyMessage.setVideoId(videoId);
                    historyMessage.setUserId(userId);
                    historyMessage.setStaffId(staff.getId());
                    historyMessage.setStatus(status);
                    historyMessage.setCorpId(corpId);
                    if (guaranteedSet.contains(videoId)) {
                        historyMessage.setSource(MANUAL.getName());
                    } else {
                        historyMessage.setSource(HISTORICAL_TOP.getName());
                    }
                    historyMessageList.add(historyMessage);
                }
            }
        }
        historyMessageService.batchInsertHistoryMessage(historyMessageList);
        insertAttachmentWithMsgResult(attachmentIds, sendMsgResultIds);
    }

    private void insertAttachmentWithMsgResult(List<Long> attachmentIds, List<Long> sendMsgResultIds) {
        if (CollectionUtils.isEmpty(attachmentIds) || CollectionUtils.isEmpty(sendMsgResultIds)) {
            return;
        }
        List<AttachmentWithMsgResult> list = new ArrayList<>();
        for (Long attachmentId : attachmentIds) {
            for (Long sendMsgResultId : sendMsgResultIds) {
                AttachmentWithMsgResult attachmentWithMsgResult = new AttachmentWithMsgResult();
                attachmentWithMsgResult.setAttachmentId(attachmentId);
                attachmentWithMsgResult.setMsgResultId(sendMsgResultId);
                list.add(attachmentWithMsgResult);
            }
        }
        List<List<AttachmentWithMsgResult>> partition = Lists.partition(list, 2000);
        for (List<AttachmentWithMsgResult> AttachmentWithMsgResults : partition) {
            attachmentWithMsgResultMapper.insertList(AttachmentWithMsgResults);
        }
    }

    private String getGroupMsgList(Long startTime, Long endTime, String cursor, Long corpId) throws IOException {
        String accessToken = weComAccessTokenService.getWeComAccessToken(corpId);
        String url = POST_WE_COM_GROUP_MSG_LIST_URL
                + "?access_token=" + accessToken;
        JSONObject param = new JSONObject();
        param.put("chat_type", "single");
        param.put("start_time", String.valueOf(startTime));
        param.put("end_time", String.valueOf(endTime));
        param.put("limit", 100);
        if (StringUtils.isNotEmpty(cursor)) {
            param.put("cursor", cursor);
        }
        if (corpId == 1L) {
            return httpPoolClient.post(url, param.toJSONString());
        } else {
            return proxyHttpPoolClient.post(url, param.toJSONString());
        }
    }

    @XxlJob("insetHistoryMessageSourceJob")
    public ReturnT<String> insetHistoryMessageSource(String param) {
        if (StringUtils.isEmpty(param)) {
            return ReturnT.FAIL;
        }
        JSONArray jsonArray = JSONArray.parseArray(param);
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            Long startTime = jsonObject.getLong("startTime");
            Long endTime = jsonObject.getLong("endTime");

            JSONArray videos = jsonObject.getJSONArray("videos");
            List<Long> videoList = videos.stream().map(String::valueOf).map(Long::parseLong).collect(Collectors.toList());
            HistoryMessageExample example = new HistoryMessageExample();
            example.createCriteria().andSendTimeBetween(new Date(startTime), new Date(endTime))
                    .andVideoIdIn(videoList);
            HistoryMessage historyMessage = new HistoryMessage();
            historyMessage.setSource(MANUAL.getName());
            historyMessageMapper.updateByExampleSelective(historyMessage, example);

            HistoryMessageExample example1 = new HistoryMessageExample();
            example1.createCriteria().andSendTimeBetween(new Date(startTime), new Date(endTime))
                    .andVideoIdNotIn(videoList);
            HistoryMessage historyMessage1 = new HistoryMessage();
            historyMessage1.setSource(HISTORICAL_TOP.getName());
            historyMessageMapper.updateByExampleSelective(historyMessage1, example1);
        }
        return ReturnT.SUCCESS;
    }


    @XxlJob("copyHistoryMessageJob")
    public ReturnT<String> copyHistoryMessage(String param) throws InterruptedException {
        while (true) {
            Date daysAgoDate = DateUtil.getDaysAgoDate(7);
            HistoryMessageExample example = new HistoryMessageExample();
            example.createCriteria().andCreateTimeLessThan(daysAgoDate);
            example.setPage(new Page<>(1, 1000));
            example.setOrderByClause("id asc");
            List<HistoryMessage> historyMessages = historyMessageMapper.selectByExample(example);
            log.info("copyHistoryMessageJob historyMessages.size={}", historyMessages.size());
            if (CollectionUtils.isEmpty(historyMessages)) {
                break;
            }
            historyMessageBackupMapper.insertList(historyMessages);
            List<Long> ids = historyMessages.stream().map(HistoryMessage::getId).collect(Collectors.toList());
            historyMessageMapper.deleteByIds(ids);
            Thread.sleep(1000);
        }
        return ReturnT.SUCCESS;
    }
}




