package com.tzld.piaoquan.api.job.wecom;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.odps.data.Record;
import com.google.common.collect.Lists;
import com.tzld.piaoquan.api.service.VideoMultiService;
import com.tzld.piaoquan.growth.common.common.base.CommonResponse;
import com.tzld.piaoquan.growth.common.common.constant.MessageConstant;
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.model.vo.GuaranteedParam;
import com.tzld.piaoquan.growth.common.service.MessageAttachmentService;
import com.tzld.piaoquan.growth.common.service.MessageService;
import com.tzld.piaoquan.growth.common.service.WeComUserService;
import com.tzld.piaoquan.growth.common.utils.*;
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 com.xxl.job.core.log.XxlJobLogger;
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.nio.charset.StandardCharsets;
import java.util.*;
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.TimeConstant.MILLISECOND_DAY;

@Slf4j
@Component
public class WeComMessageDataJob {

    @Autowired
    private WeComUserMapper weComUserMapper;

    @Autowired
    private MessageAttachmentMapper messageAttachmentMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private MessageService messageService;

    @Autowired
    private MessageAttachmentService messageAttachmentService;

    @Autowired
    private StaffWithUserMapper staffWithUserMapper;

    @Autowired
    private StaffMapper staffMapper;

    @Autowired
    private SendMessageMapper sendMessageMapper;

    @Autowired
    private CorpMapper corpMapper;

    @Autowired
    private WeComUserService weComUserService;

    @Autowired
    private VideoMultiService videoMultiService;

    //发送小程序标题限制字节数
    private static final int MAX_BYTES = 64;

    //历史优质视频可推送用户列表
    Map<Long, List<PushMessage>> historicalTopMap = new HashMap<>();

    //保底视频列表
    Map<Long, VideoCombination> guaranteedVideoMap = new HashMap<>();

    Map<String, String> pageMap = new HashMap<>();

    //初始化操作
    private void init(List<Long> staffIds) {
        List<PushMessage> list = new ArrayList<>();
        try {
            //历史优质视频获取分页获取
            String countSql = String.format("SELECT count(*) FROM loghubods.history_good_video_can_push_user_list where dt = %s;",
                    DateUtil.getBeforeDayDateString("yyyyMMdd"));
            List<Record> countData = OdpsUtil.getOdpsData(countSql);
            int size = 1;
            if (!CollectionUtils.isEmpty(countData)) {
                int count = Integer.parseInt((String) countData.get(0).get(0));
                if (count > 0) {
                    List<Record> dataList = new ArrayList<>();
                    for (int i = 0; i < count; i += size) {
                        String sql = String.format("SELECT * FROM loghubods.history_good_video_can_push_user_list where dt = %s order by score desc limit %s,%s;",
                                DateUtil.getBeforeDayDateString("yyyyMMdd"), i, size);
                        List<Record> data = OdpsUtil.getOdpsData(sql);
                        if (!CollectionUtils.isEmpty(data)) {
                            dataList.addAll(data);
                        }
                    }
                    for (Record record : dataList) {
                        PushMessage pushMessage = new PushMessage();
                        Long videoId = Long.parseLong((String) record.get(0));
                        Set<Long> videoIds = new HashSet<>();
                        videoIds.add(videoId);
                        Map<Long, VideoDetail> videoDetails = messageAttachmentService.getVideoDetail(videoIds);
                        VideoDetail videoDetail = videoDetails.get(videoId);
                        if (videoDetail == null || StringUtils.isEmpty(videoDetail.getCover()) || StringUtils.isEmpty(videoDetail.getTitle())) {
                            continue;
                        }
                        if (!ImageUrlValidator.isValidImageUrl(videoDetail.getCover())) {
                            continue;
                        }
                        Set<Long> userIds = new HashSet<>(JSONObject.parseArray((String) record.get(1), Long.class));
                        Long staffId = Long.parseLong((String) record.get(2));
                        Double score = Double.parseDouble((String) record.get(3));
                        pushMessage.setVideoId(videoId);
                        pushMessage.setUserIds(userIds);
                        pushMessage.setStaffId(staffId);
                        pushMessage.setScore(score);
                        list.add(pushMessage);
                    }
                }
            }
        } catch (Exception e) {
            log.error("history good video error", e);
        }

        if (CollectionUtils.isEmpty(list)) {
            LarkRobotUtil.sendMessage("历史优质视频为空");
        } else {
            historicalTopMap = list.stream()
                    .collect(Collectors.groupingBy(PushMessage::getStaffId,
                            Collectors.mapping(pushMessage -> pushMessage,
                                    Collectors.toList())))
                    .entrySet()
                    .stream()
                    .collect(Collectors.toMap(
                            Map.Entry::getKey,
                            entry -> entry.getValue().stream()
                                    .sorted(Comparator.comparing(PushMessage::getScore).reversed()) // 根据 score 降序排序
                                    .collect(Collectors.toList())
                    ));

        }
        //保底视频获取
        GuaranteedParam guaranteedParam = messageAttachmentService.getGuaranteedVideo(DateUtil.getThatDayDateString());
        if (guaranteedParam == null
                || CollectionUtils.isEmpty(guaranteedParam.getVideoParamList())) {
            LarkRobotUtil.sendMessage("保底视频获取异常，请检查" + DateUtil.getThatDayDateString());
            throw new RuntimeException();
        }
        Map<Long, VideoCombination> videoMap = new HashMap<>();
        for (VideoParam videoParam : guaranteedParam.getVideoParamList()) {
            if (videoParam.getStaffId() == null) {
                LarkRobotUtil.sendMessage("保底视频获取异常，StaffId为空" + DateUtil.getThatDayDateString());
                continue;
            }
            if (videoParam.getStaffId() != 0) {
                if (!CollectionUtils.isEmpty(staffIds) && !staffIds.contains(videoParam.getStaffId())) {
                    continue;
                }
            }
            //默认组视频不做查询
            if (videoParam.getStaffId() == 0L) {
                if (videoParam.getVideoIds().size() < MAX_VIDEO_NUM) {
                    LarkRobotUtil.sendMessage("默认组视频数量不足" + DateUtil.getThatDayDateString());
                }
                videoMap.put(videoParam.getStaffId(), combination(videoParam.getVideoIds()));
                continue;
            }
            if (CollectionUtils.isEmpty(videoParam.getVideoIds()) || videoParam.getVideoIds().size() < MAX_VIDEO_NUM) {
                LarkRobotUtil.sendMessage("保底视频数量异常，请查看" + guaranteedParam.getDate() + videoParam.getStaffId());
                continue;
            }
            for (Long videoId : videoParam.getVideoIds()) {
                MessageAttachmentExample example = new MessageAttachmentExample();
                example.createCriteria().andMiniprogramVideoIdEqualTo(videoId).andStaffIdEqualTo(videoParam.getStaffId());
                List<MessageAttachment> messageAttachmentList = messageAttachmentMapper.selectByExample(example);
                if (CollectionUtils.isEmpty(messageAttachmentList)) {
                    LarkRobotUtil.sendMessage("保底视频不存在，请查看videoId=" + videoId);
                    continue;
                }
                MessageAttachment messageAttachment = messageAttachmentList.get(0);
                if (messageAttachment.getSendTime() != null
                        && DateUtil.dateDifference(new Date(), messageAttachment.getSendTime()) < 30 * MILLISECOND_DAY) {
                    LarkRobotUtil.sendMessage("保底视频30天内已发送，请查看videoId=" + videoId);
                }
            }
            //重新组合视频id
            videoMap.put(videoParam.getStaffId(), combination(videoParam.getVideoIds()));
        }
        if (!videoMap.containsKey(0L)) {
            LarkRobotUtil.sendMessage("保底视频没有默认组，请查看" + guaranteedParam.getDate());
        }
        log.info("保底数据获取，videoMap={}", videoMap);
        this.guaranteedVideoMap = videoMap;
    }

    private VideoCombination combination(List<Long> videoIds) {
        VideoCombination videoCombination = new VideoCombination();
        videoCombination.setThreeVideoList(combinedVideoList(videoIds, 3));
        videoCombination.setThreeVideoIndex(0);
        videoCombination.setTwoVideoList(combinedVideoList(videoIds, 2));
        videoCombination.setTwoVideoIndex(0);
        videoCombination.setOneVideoList(combinedVideoList(videoIds, 1));
        videoCombination.setOneVideoIndex(0);
        return videoCombination;
    }

    private List<List<Long>> combinedVideoList(List<Long> videoIds, int count) {
        List<List<Long>> res = new ArrayList<>();
        // 此处假设视频的打开率与上下文无关，只保证每个视频在每个位置都有发送
        for (int i = 0; i < videoIds.size(); i++) {
            List<Long> list = new ArrayList<>();
            for (int j = 0; j < count; j++) {
                int index = (i + j) % videoIds.size();
                list.add(videoIds.get(index));
            }
            res.add(list);
        }
        return res;
    }

    @XxlJob("assembleSendMessageJob")
    public ReturnT<String> assembleSendMessage(String param) {
        XxlJobParam xxlJobParam = new XxlJobParam();
        if (StringUtils.isNotEmpty(param)) {
            xxlJobParam = JSONObject.parseObject(param, XxlJobParam.class);
        }
        CorpExample corpExample = new CorpExample();
        if (xxlJobParam.getCorpId() != null) {
            corpExample.createCriteria().andIdEqualTo(xxlJobParam.getCorpId());
        }
        List<Corp> corps = corpMapper.selectByExample(corpExample);
        if (CollectionUtils.isEmpty(corps)) {
            return ReturnT.SUCCESS;
        }
        List<Long> staffIds = new ArrayList<>();
        if (xxlJobParam.getStaffId() != null) {
            staffIds.add(xxlJobParam.getStaffId());
        }
        if (!CollectionUtils.isEmpty(xxlJobParam.getStaffIds())) {
            staffIds.addAll(xxlJobParam.getStaffIds());
        }
        init(staffIds);
        List<Long> filterUserId = weComUserService.getFilterTagUserId();
        for (Corp corp : corps) {
            WeComUserExample weComUserExample = new WeComUserExample();
            WeComUserExample.Criteria criteria = weComUserExample.createCriteria().andExternalUserIdIsNotNull().andCorpIdEqualTo(corp.getId())
                    .andGroupMsgDisabledEqualTo((byte) 0);
            if (xxlJobParam.getUserId() != null) {
                criteria.andIdEqualTo(xxlJobParam.getUserId());
            }
            long count = weComUserMapper.countByExample(weComUserExample);
            int page = 1;
            int pageSize = 1000;
            long totalPageSize = count / pageSize + 1;
            for (; page <= totalPageSize; page++) {
                weComUserExample.setPage(new Page<>(page, pageSize));
                List<WeComUser> weComUserList = weComUserMapper.selectByExample(weComUserExample);
                if (CollectionUtils.isEmpty(weComUserList)) {
                    continue;
                }
                //过滤用户
                List<WeComUser> filtered = weComUserList.stream()
                        .filter(e -> !filterUserId.contains(e.getId())).collect(Collectors.toList());
                //落库逻辑
                List<SendMessage> allSeneMessageList = new ArrayList<>();
                for (WeComUser weComUser : filtered) {
                    List<SendMessage> sendMessageList = getSendMessage(weComUser, staffIds, corp.getId());
                    if (CollectionUtils.isEmpty(sendMessageList)) {
                        continue;
                    }
                    allSeneMessageList.addAll(sendMessageList);
                }
                if (CollectionUtils.isEmpty(allSeneMessageList)) {
                    continue;
                }
                sendMessageMapper.insertList(allSeneMessageList);
            }
        }
        //组装好当天要发送的消息后  记录时间
        saveGuaranteedVideoIdList(staffIds);
        return ReturnT.SUCCESS;
    }

    private void saveGuaranteedVideoIdList(List<Long> staffIds) {
        GuaranteedParam guaranteedParam = messageAttachmentService.getGuaranteedVideo(DateUtil.getThatDayDateString());
        if (guaranteedParam == null || CollectionUtils.isEmpty(guaranteedParam.getVideoParamList())) {
            return;
        }
        if (CollectionUtils.isEmpty(staffIds)) {
            Set<Long> videoIdSet = new HashSet<>();
            for (VideoParam videoParam : guaranteedParam.getVideoParamList()) {
                if (CollectionUtils.isEmpty(videoParam.getVideoIds())) {
                    continue;
                }
                videoIdSet.addAll(videoParam.getVideoIds());
            }
            List<Long> videoIdList = new ArrayList<>(videoIdSet);
            MessageAttachmentExample example = new MessageAttachmentExample();
            example.createCriteria().andMiniprogramVideoIdIn(videoIdList).andSendTimeIsNull();
            MessageAttachment updateMessageAttachment = new MessageAttachment();
            updateMessageAttachment.setSendTime(new Date());
            messageAttachmentMapper.updateByExampleSelective(updateMessageAttachment, example);
        } else {
            for (VideoParam videoParam : guaranteedParam.getVideoParamList()) {
                if (!CollectionUtils.isEmpty(staffIds) && staffIds.contains(videoParam.getStaffId())) {
                    if (CollectionUtils.isEmpty(videoParam.getVideoIds())) {
                        continue;
                    }
                    MessageAttachmentExample example = new MessageAttachmentExample();
                    example.createCriteria().andMiniprogramVideoIdIn(videoParam.getVideoIds()).andStaffIdEqualTo(videoParam.getStaffId());
                    MessageAttachment updateMessageAttachment = new MessageAttachment();
                    updateMessageAttachment.setSendTime(new Date());
                    messageAttachmentMapper.updateByExampleSelective(updateMessageAttachment, example);
                }
            }
        }
    }

    private List<SendMessage> getSendMessage(WeComUser weComUser, List<Long> staffIds, Long corpId) {
        StaffWithUserExample example = new StaffWithUserExample();
        StaffWithUserExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(weComUser.getId());
        criteria.andIsDeleteEqualTo(0);
        if (!CollectionUtils.isEmpty(staffIds)) {
            criteria.andStaffIdIn(staffIds);
        }
        List<StaffWithUser> staffWithUserList = staffWithUserMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(staffWithUserList)) {
            return Collections.emptyList();
        }
        List<SendMessage> sendMessageList = new ArrayList<>();
        for (StaffWithUser staffWithUser : staffWithUserList) {
            SendMessage sendMessage = new SendMessage();
            int n = fillHistoricalTopMessages(sendMessage, weComUser.getId(), staffWithUser.getStaffId());
            if (n < MAX_VIDEO_NUM) {
                // 保底数据
                n = fillGuaranteedMessages(sendMessage, staffWithUser.getStaffId(), n);
            }
            if (n < MAX_VIDEO_NUM) {
                LarkRobotUtil.sendMessage("组装数据失败 weComUser=" + weComUser);
                throw new RuntimeException("组装数据失败");
            }
            sendMessage.setCorpId(corpId);
            sendMessage.setStaffId(staffWithUser.getStaffId());
            sendMessage.setUserId(staffWithUser.getUserId());
            sendMessageList.add(sendMessage);
        }

        return sendMessageList;
    }

    private int fillHistoricalTopMessages(SendMessage sendMessage, Long userId, Long staffId) {
        List<PushMessage> pushMessages = historicalTopMap.get(staffId);
        if (CollectionUtils.isEmpty(pushMessages)) {
            return 0;
        }
        int n = 0;
        for (PushMessage pushMessage : pushMessages) {
            if (pushMessage.getUserIds().contains(userId)) {
                setVideoId(sendMessage, n, pushMessage.getVideoId());
                n++;
                if (n >= MAX_VIDEO_NUM) {
                    break;
                }
            }
        }
        return n;
    }

    private int fillGuaranteedMessages(SendMessage sendMessage, Long staffId, int currentCount) {
        VideoCombination videoCombination = guaranteedVideoMap.get(staffId);
        if (videoCombination == null) {
            videoCombination = guaranteedVideoMap.get(0L);
        }
        if (videoCombination == null) {
            log.error("保底数据获取失败，staffId={}, guaranteedVideoMap={}", staffId, guaranteedVideoMap);
            LarkRobotUtil.sendMessage("组装数据时，保底数据获取异常");
            throw new RuntimeException("保底数据获取异常");
        }
        if (currentCount < MAX_VIDEO_NUM) {
            switch (currentCount) {
                case 0:
                    currentCount = setVideoId(sendMessage, videoCombination.getThreeVideoList().get(videoCombination.getThreeVideoIndex()),
                            currentCount);
                    videoCombination.setThreeVideoIndex(
                            (videoCombination.getThreeVideoIndex() + 1) % videoCombination.getThreeVideoList().size());
                    break;
                case 1:
                    currentCount = setVideoId(sendMessage, videoCombination.getTwoVideoList().get(videoCombination.getTwoVideoIndex()),
                            currentCount);
                    videoCombination.setTwoVideoIndex(
                            (videoCombination.getTwoVideoIndex() + 1) % videoCombination.getTwoVideoList().size());
                    break;
                case 2:
                    currentCount = setVideoId(sendMessage, videoCombination.getOneVideoList().get(videoCombination.getOneVideoIndex()),
                            currentCount);
                    videoCombination.setOneVideoIndex(
                            (videoCombination.getOneVideoIndex() + 1) % videoCombination.getOneVideoList().size());
                    break;
                default:
                    break;
            }
        }
        return currentCount;
    }

    private int setVideoId(SendMessage sendMessage, List<Long> videoIds, Integer currentCount) {
        for (Long videoId : videoIds) {
            setVideoId(sendMessage, currentCount, videoId);
            currentCount++;
            if (currentCount >= MAX_VIDEO_NUM) {
                break;
            }
        }
        return currentCount;
    }

    private void setVideoId(SendMessage sendMessage, int index, Long videoId) {
        switch (index) {
            case 0:
                sendMessage.setVideoId1(videoId);
                break;
            case 1:
                sendMessage.setVideoId2(videoId);
                break;
            case 2:
                sendMessage.setVideoId3(videoId);
                break;
            default:
                break;
        }
    }


    @XxlJob("pushSendMessageJob")
    public ReturnT<String> pushSendMessage(String param) {
        XxlJobParam xxlJobParam = new XxlJobParam();
        if (StringUtils.isNotEmpty(param)) {
            xxlJobParam = JSONObject.parseObject(param, XxlJobParam.class);
        }
        List<SendMessage> groupList = sendMessageMapper.getGroupList(DateUtil.getThatDayDate(), 0);
        if (xxlJobParam.getCorpId() != null) {
            Long corpId = xxlJobParam.getCorpId();
            groupList = groupList.stream().filter(e -> Objects.equals(e.getCorpId(), corpId)).collect(Collectors.toList());
        }
        if (CollectionUtils.isEmpty(groupList)) {
            return ReturnT.SUCCESS;
        }
        if (xxlJobParam.getStaffId() != null) {
            Long staffId = xxlJobParam.getStaffId();
            groupList = groupList.stream().filter(e -> Objects.equals(e.getStaffId(), staffId)).collect(Collectors.toList());
        }
        if (CollectionUtils.isEmpty(groupList)) {
            return ReturnT.SUCCESS;
        }
        for (SendMessage sendMessage : groupList) {
            pushAndUpdateMessage(sendMessage);
        }
        Map<Long, List<SendMessage>> groupedByStaffId = groupList.stream().collect(Collectors.groupingBy(SendMessage::getStaffId));
        for (Map.Entry<Long, List<SendMessage>> entry : groupedByStaffId.entrySet()) {
            SendMessageExample example = new SendMessageExample();
            example.createCriteria().andStaffIdEqualTo(entry.getKey()).andIsSendEqualTo(0)
                    .andCreateTimeGreaterThan(DateUtil.getThatDayDate());
            long l = sendMessageMapper.countByExample(example);
            //增加重试
            if (l > 0) {
                List<SendMessage> retryGroupList = sendMessageMapper.getGroupList(DateUtil.getThatDayDate(), 0);
                retryGroupList = retryGroupList.stream().filter(e -> Objects.equals(e.getStaffId(), entry.getKey()))
                        .collect(Collectors.toList());
                for (SendMessage sendMessage : retryGroupList) {
                    pushAndUpdateMessage(sendMessage);
                }
            }
        }
        SendMessageExample example = new SendMessageExample();
        example.createCriteria().andIsSendEqualTo(0).andCreateTimeGreaterThan(DateUtil.getThatDayDate());
        long l = sendMessageMapper.countByExample(example);
        if (l > 0) {
            LarkRobotUtil.sendMessage("存在发送失败消息，请检查<at user_id=\"g6732afb\">王云鹏</at>");
        }
        return ReturnT.SUCCESS;
    }

    private void pushAndUpdateMessage(SendMessage sendMessage) {
        sendMessage.setIsSend(0);
        sendMessage.setCreateTime(DateUtil.getThatDayDate());
        List<String> sendUserList = sendMessageMapper.selectExternalUserId(sendMessage);
        boolean flag = pushMessage(sendUserList, sendMessage);
        if (flag) {
            SendMessage updateSendMessage = new SendMessage();
            updateSendMessage.setIsSend(1);
            SendMessageExample example = new SendMessageExample();
            example.createCriteria()
                    .andVideoId1EqualTo(sendMessage.getVideoId1())
                    .andVideoId2EqualTo(sendMessage.getVideoId2())
                    .andVideoId3EqualTo(sendMessage.getVideoId3())
                    .andStaffIdEqualTo(sendMessage.getStaffId())
                    .andCreateTimeGreaterThan(DateUtil.getThatDayDate());
            sendMessageMapper.updateByExampleSelective(updateSendMessage, example);
        }
    }

    private boolean pushMessage(List<String> sendUserList, SendMessage sendMessage) {
        List<JSONObject> pushList = new ArrayList<>();
        StaffExample staffExample = new StaffExample();
        staffExample.createCriteria().andIdEqualTo(sendMessage.getStaffId());
        List<Staff> staffList = staffMapper.selectByExample(staffExample);
        Staff staff = staffList.get(0);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("chat_type", "single");
        JSONObject text = new JSONObject();
        String content = messageService.getMessageText(staff.getId());
        text.put("content", content);
        jsonObject.put("text", text);
        jsonObject.put("sender", staff.getCarrierId());
        JSONArray attachments = new JSONArray();
        List<Long> videoIdList = new ArrayList<>();
        videoIdList.add(sendMessage.getVideoId1());
        videoIdList.add(sendMessage.getVideoId2());
        videoIdList.add(sendMessage.getVideoId3());
        for (Long videoId : videoIdList) {
            JSONObject attachment = new JSONObject();
            attachment.put("msgtype", "miniprogram");
            MessageAttachmentExample example = new MessageAttachmentExample();
            example.createCriteria().andMiniprogramVideoIdEqualTo(videoId);
            List<MessageAttachment> messageAttachmentList = messageAttachmentMapper.selectByExample(example);
            if (CollectionUtils.isEmpty(messageAttachmentList)) {
                log.error("附件信息查询异常");
                return false;
            }
            MessageAttachment messageAttachment = messageAttachmentList.get(0);
            JSONObject miniprogram = new JSONObject();
            miniprogram.put("appid", MessageConstant.appid);
            String title = messageAttachment.getTitle();
            if (title.getBytes(StandardCharsets.UTF_8).length > MAX_BYTES) {
                title = ToolUtils.truncateString(title, MAX_BYTES - 3) + "...";
            }
            miniprogram.put("title", title);
            String picMediaId = messageAttachmentService.getPicMediaId(messageAttachment.getCover(), sendMessage.getCorpId(), messageAttachment.getMiniprogramVideoId());
            if (StringUtils.isEmpty(picMediaId)) {
                log.error("pushMessage getPicMediaId error cover={}", messageAttachment.getCover());
                return false;
            }
            miniprogram.put("pic_media_id", picMediaId);
            String page = "";
            String key = staff.getCarrierId() + "_" + videoId;
            if (pageMap.containsKey(key)) {
                page = pageMap.get(key);
                page = videoMultiService.setVideoMultiTitleCoverPagePath(videoId, page, title, messageAttachment.getCover());
            } else {
                page = messageAttachmentService.getPage("touliu", "tencentqw", staff, videoId, "企微", "日常推送", "位置X", null);
                page = videoMultiService.setVideoMultiTitleCoverPagePath(videoId, page, title, messageAttachment.getCover());
                pageMap.put(key, page);
            }
            if (StringUtils.isEmpty(page)) {
                log.error("pushMessage get page error videoId={} staff={}", videoId, staff);
                return false;
            }
            miniprogram.put("page", page);
            attachment.put("miniprogram", miniprogram);
            attachments.add(0, attachment);
        }
        jsonObject.put("attachments", attachments);
        List<List<String>> lists = Lists.partition(sendUserList, 10000);
        for (List<String> list : lists) {
            JSONArray externalUserIds = JSONArray.parseArray(JSON.toJSONString(list));
            JSONObject newJSONObject = new JSONObject();
            newJSONObject.putAll(jsonObject);
            newJSONObject.put("external_userid", externalUserIds);
            pushList.add(newJSONObject);
        }
        if (CollectionUtils.isEmpty(pushList)) {
            return false;
        }
        for (JSONObject pushJsonObject : pushList) {
            log.info("pushMessage pushJsonObject={}", pushJsonObject);
            boolean flag = messageService.pushWeComMessage(pushJsonObject, sendMessage.getCorpId());
            if (!flag) {
                return flag;
            }
        }
        return true;
    }


    @XxlJob("existGuaranteesJob")
    public ReturnT<String> existGuarantees(String param) {
        //保底视频获取
        GuaranteedParam guaranteedParam = messageAttachmentService.getGuaranteedVideo(DateUtil.getNextDayDateString());
        if (guaranteedParam == null
                || CollectionUtils.isEmpty(guaranteedParam.getVideoParamList())) {
            LarkRobotUtil.sendMessage("<at user_id=\"g6732afb\">王云鹏</at> 保底视频异常，请检查" + DateUtil.getNextDayDateString());
        }
        return ReturnT.SUCCESS;
    }


    @XxlJob("addMessageAttachmentJob")
    public ReturnT<String> addMessageAttachment(String param) {
        String dt = DateUtil.getBeforeDayDateString(-1, "yyyy-MM-dd");
        List<Long> videoIds = getTopThousandVideoIds();
        if (CollectionUtils.isEmpty(videoIds)) {
            XxlJobLogger.log("保底视频查询异常");
            LarkRobotUtil.sendMessage("addMessageAttachmentJob 保底视频添加任务异常，请检查 " + dt
                    + " <at user_id=\"g6732afb\">王云鹏</at>");
            return ReturnT.FAIL;
        }

        List<Long> currentVideoIds = new ArrayList<>();
        int index = 0;

        while (true) {
            while (currentVideoIds.size() < MAX_VIDEO_NUM && index < videoIds.size()) {
                currentVideoIds.add(videoIds.get(index++));
            }
            if (currentVideoIds.size() < MAX_VIDEO_NUM) {
                XxlJobLogger.log("保底视频可用数量不足，无法凑齐3个有效视频");
                LarkRobotUtil.sendMessage("addMessageAttachmentJob 保底视频可用数量不足，无法凑齐3个有效视频，请检查 " + dt
                        + " <at user_id=\"g6732afb\">王云鹏</at>");
                return ReturnT.FAIL;
            }
            GuaranteedParam guaranteedParam = new GuaranteedParam();
            guaranteedParam.setDate(dt);
            guaranteedParam.setVideoParamList(buildVideoParamList(new ArrayList<>(currentVideoIds)));
            CommonResponse<Void> commonResponse = messageAttachmentService.createGuaranteedMiniProgram(guaranteedParam);
            if (commonResponse.isSuccess() && commonResponse.getCode() == 0) {
                return ReturnT.SUCCESS;
            }

            String msg = commonResponse.getMsg();
            if (StringUtils.isNotEmpty(msg) && msg.contains("保底视频30天内已发送，请查看videoId=")) {
                String errorVideoId = msg.substring(msg.indexOf("videoId=") + 8);
                try {
                    Long removeId = Long.parseLong(errorVideoId);
                    currentVideoIds.remove(removeId);
                } catch (Exception e) {
                    XxlJobLogger.log("保底视频异常，解析videoId失败: " + errorVideoId);
                }
            } else {
                XxlJobLogger.log("创建保底视频失败: " + msg);
            }
            if (currentVideoIds.size() == MAX_VIDEO_NUM) {
                currentVideoIds.clear();
            }
        }
    }

    private List<Long> getTopThousandVideoIds() {
        int releaseDays = 1;
        String dt = DateUtil.getBeforeDayDateString(releaseDays, "yyyyMMdd");
        int retryTimes = 3;
        List<Long> videoIds = new ArrayList<>();
        do {
            String sql = String.format("SELECT videoid FROM loghubods.lastday_return WHERE dt=%s limit 2000;", dt);
            List<Record> dataList = OdpsUtil.getOdpsData(sql);
            if (!CollectionUtils.isEmpty(dataList)) {
                for (Record record : dataList) {
                    Long videoId = Long.parseLong((String) record.get(0));
                    videoIds.add(videoId);
                }
                return videoIds;
            }
            retryTimes--;
            releaseDays++;
            dt = DateUtil.getBeforeDayDateString(releaseDays, "yyyyMMdd");
        } while (retryTimes > 0);
        return videoIds;
    }

    private List<VideoParam> buildVideoParamList(List<Long> videoIds) {
        List<VideoParam> videoParamList = new ArrayList<>();
        VideoParam videoParam = new VideoParam();
        videoParam.setStaffIds(Arrays.asList(0L, 3L, 7L, 9L, 10L, 12L, 16L, 17L, 100L, 103L, 104L, 106L, 107L, 108L, 109L, 110L,
                111L, 112L, 113L, 114L, 115L, 116L, 117L, 118L, 119L, 120L, 121L, 122L, 123L));
        videoParam.setVideoIds(videoIds);
        videoParamList.add(videoParam);
        VideoParam videoParam2 = new VideoParam();
        videoParam2.setStaffIds(Arrays.asList(5L, 15L));
        videoParam2.setVideoIds(videoIds);
        videoParamList.add(videoParam2);
        VideoParam videoParam3 = new VideoParam();
        videoParam3.setStaffIds(Arrays.asList(8L, 11L, 13L, 14L));
        videoParam3.setVideoIds(videoIds);
        videoParamList.add(videoParam3);
        return videoParamList;
    }
}
