package com.pcloud.book.reading.biz.impl;

import com.alibaba.fastjson.JSON;
import com.pcloud.book.advertising.dao.AdvertisingBrandDao;
import com.pcloud.book.advertising.dto.AdvertisingBrandDTO;
import com.pcloud.book.advertising.entity.AdvertisingBrand;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.constant.BookConstant;
import com.pcloud.book.consumer.convert.ConvertConsr;
import com.pcloud.book.consumer.reader.ReaderConsr;
import com.pcloud.book.consumer.wechatgroup.WechatGroupConsr;
import com.pcloud.book.group.biz.GroupQrcodeBiz;
import com.pcloud.book.group.constant.BookBusinessConstants;
import com.pcloud.book.group.dao.BookGroupCipherUserDao;
import com.pcloud.book.group.dao.WeixinQrcodeDao;
import com.pcloud.book.group.dao.WeixinQrcodeGenerationDao;
import com.pcloud.book.group.entity.BookGroupCipherUser;
import com.pcloud.book.group.entity.GroupQrcode;
import com.pcloud.book.group.entity.WeixinQrcode;
import com.pcloud.book.group.entity.WeixinQrcodeGeneration;
import com.pcloud.book.group.tools.QrcodeTools;
import com.pcloud.book.group.tools.SendWeixinRequestTools;
import com.pcloud.book.reading.biz.ReadingActivityBiz;
import com.pcloud.book.reading.constant.ReadingActivityConstant;
import com.pcloud.book.reading.dao.*;
import com.pcloud.book.reading.dto.ActivityUserBookDTO;
import com.pcloud.book.reading.dto.ActivityUserCountDTO;
import com.pcloud.book.reading.dto.AssignGroupDTO;
import com.pcloud.book.reading.dto.GroupingUserDTO;
import com.pcloud.book.reading.dto.ReadingActivityAdditionParamDTO;
import com.pcloud.book.reading.dto.ReadingActivityBaseParamDTO;
import com.pcloud.book.reading.dto.ReadingActivityDTO;
import com.pcloud.book.reading.dto.SendWxMsg4ReadingDTO;
import com.pcloud.book.reading.dto.UserBaseDTO;
import com.pcloud.book.reading.entity.*;
import com.pcloud.book.reading.enums.ContentTypeEnum;
import com.pcloud.book.reading.enums.JoinConditionEnum;
import com.pcloud.book.reading.enums.JoinStateEnum;
import com.pcloud.book.reading.enums.JoinTypeEnum;
import com.pcloud.book.util.common.ThreadPoolUtils;
import com.pcloud.common.constant.UrlConstant;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.page.PageBeanNew;
import com.pcloud.common.page.PageParam;
import com.pcloud.common.utils.DateUtils;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.QrcodeUtils;
import com.pcloud.common.utils.cache.redis.JedisClusterUtils;
import com.pcloud.common.utils.httpclient.UrlUtils;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.common.utils.validate.ValidateUtils;
import com.pcloud.convert.file.entity.FileUploadInfo;
import com.pcloud.facade.quartz.entity.CallBackParam;
import com.pcloud.facade.quartz.entity.ScheduleJob;
import com.pcloud.facade.quartz.service.ScheduleService;
import com.pcloud.wechatgroup.group.dto.GroupRobotDTO;
import com.pcloud.wechatgroup.group.dto.GroupUserDTO;
import com.pcloud.wechatgroup.message.dto.AddWXGroupDTO;
import com.pcloud.wechatgroup.message.dto.SendTextDTO;
import com.sdk.wxgroup.*;
import com.sdk.wxgroup.constant.WxGroupSDKConstants;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

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

import lombok.extern.slf4j.Slf4j;

/**
 * @描述：共读活动
 * @作者：zhuyajie
 * @创建时间：17:44 2020/1/14
 * @版本：1.0
 */
@Slf4j
@Component("readingActivityBiz")
public class ReadingActivityBizImpl implements ReadingActivityBiz{

    @Autowired
    private ReadingActivityDao readingActivityDao;
    @Autowired
    private ReadingInviteDao readingInviteDao;
    @Autowired
    private ReadingUserDao readingUserDao;
    @Autowired
    private WechatGroupConsr wechatGroupConsr;
    @Autowired
    private WeixinQrcodeGenerationDao weixinQrcodeGenerationDao;
    @Autowired
    private ReadingGroupDao readingGroupDao;
    @Autowired
    private ScheduleService scheduleService;
    @Autowired
    private GroupQrcodeBiz groupQrcodeBiz;
    @Autowired
    private BookGroupCipherUserDao bookGroupCipherUserDao;
    @Autowired
    private AdvertisingBrandDao advertisingBrandDao;
    @Autowired
    private BookGroupCollectionDao bookGroupCollectionDao;
    @Autowired
    private ReadingGroupRobotDao readingGroupRobotDao;
    @Autowired
    private ReadingGroupCreateDao readingGroupCreateDao;
    @Autowired
    private ConvertConsr convertConsr;
    @Autowired
    private ReaderConsr readerConsr;
    @Autowired
    private WeixinQrcodeDao weixinQrcodeDao;
    @Value("${system.env}")
    private String envStr;
    /**
     * 读书活动进群的用户集合
     */
    private static final String ACTIVITY_USER_JOIN_GROUP_USERS="BOOK:ACTIVITY_USER_JOIN_GROUP_USERS";
    /**
     * 读书活动进群的欢迎语
     */
    private static final String ACTIVITY_USER_JOIN_GROUP_GUIDE="BOOK:ACTIVITY_USER_JOIN_GROUP_GUIDE";
    /**
     * 活动关联书刊
     */
    private static final String ACTIVITY_USER_BOOK = "BOOK:READING_ACTIVITY:USER_BOOK";

    @ParamLog("[receiveMoney]")
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public void receiveMoney(CollectionVO vo) {
        if (Objects.isNull(vo) || StringUtils.isBlank(vo.getTransferId())
                || StringUtils.isBlank(vo.getAltId())
                || StringUtils.isBlank(vo.getWxId())
                || Objects.isNull(vo.getAmount())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "接收转账信息失败，参数为空");
        }
        BookGroupCollection byTransferId = this.bookGroupCollectionDao.getByTransferId(vo.getTransferId());
        ReadingActivity byTheme = readingActivityDao.getByThemeAndJoinCondition(vo.getRemark(),JoinConditionEnum.TRANSFER.value);
        // 处理收款消息
        if (WxGroupSDKConstants.PaySubTypeEnum.RECEIVE_COLLECTION_MESSAGE.getCode().equals(vo.getPaySubType())) {
            this.processReceiveCollectionMessage(vo, byTransferId, byTheme);
        }
        // 收款成功
        if (WxGroupSDKConstants.PaySubTypeEnum.COLLECTION.getCode().equals(vo.getPaySubType())) {
            this.processCollection(vo, byTransferId, byTheme);
        }
    }

    /**
     * 处理收款消息
     */
    @Transactional(rollbackFor = {Exception.class})
    public void processReceiveCollectionMessage(CollectionVO vo, BookGroupCollection byTransferId, ReadingActivity byTheme) {
        SendTextMessageVO sendText = new SendTextMessageVO();
        // 转账说明不正确
        if (Objects.isNull(byTheme)) {
            sendText.setContent("您的转账说明不对，请填写正确金额和转账说明（活动主题）之后重新转账，此笔转账将会在24小时后自动退回。");
            sendText.setAltId(vo.getAltId());
            sendText.setWxGroupId(vo.getWxId());
            sendText.setIp(getIP(vo.getAltId()));
            // TODO sdk.message
                wechatGroupConsr.sendMessage(JSON.toJSONString(sendText));
            return;
        }
        // 转账金额不正确
        if (byTheme.getJoinAmount().compareTo(vo.getAmount()) != 0) {
            sendText.setContent("您的转账金额不对，请填写正确金额和转账说明（活动主题）之后重新转账，此笔转账将会在24小时后自动退回。");
            sendText.setAltId(vo.getAltId());
            sendText.setWxGroupId(vo.getWxId());
            sendText.setIp(getIP(vo.getAltId()));
            // TODO sdk.message
                wechatGroupConsr.sendMessage(JSON.toJSONString(sendText));
            return;
        }
        if (Objects.isNull(byTransferId)) {
            // 插入收款中记录
            BookGroupCollection bookGroupCollection = BookGroupCollection.builder().amount(vo.getAmount())
                    .collectionRobotId(vo.getAltId()).transferId(vo.getTransferId()).status(BookBusinessConstants.CollectionStatus.RECEIVING.getCode())
                    .createUser(vo.getWxId()).createTime(new Date()).updateUser(vo.getWxId()).updateTime(new Date()).build();
            this.bookGroupCollectionDao.insert(bookGroupCollection);
        } else {
            log.info("[processReceiveCollectionMessage] byTransferId 已存在 vo:{}; byTransferId:{}", vo, byTransferId);
        }
        // 收款
        ReceiptMoneyVO receiptMoneyVO = new ReceiptMoneyVO();
        receiptMoneyVO.setTransferId(vo.getTransferId());
        receiptMoneyVO.setAltId(vo.getAltId());
        receiptMoneyVO.setWxId(vo.getWxId());
        receiptMoneyVO.setIp(getIP(vo.getAltId()));
        WxGroupSDK.receiptMoney(receiptMoneyVO);
    }

    /**
     * 收款
     */
    @Transactional(rollbackFor = {Exception.class})
    public void processCollection(CollectionVO vo, BookGroupCollection byTransferId, ReadingActivity byTheme) {
        if (Objects.isNull(byTransferId)) {
            // 直接插入收款成功的数据
            log.info("[processCollection] 转账记录不存在时收款，直接插入转账成功 vo:{}", vo);
            BookGroupCollection bookGroupCollection = BookGroupCollection.builder().amount(vo.getAmount())
                    .collectionRobotId(vo.getAltId()).transferId(vo.getTransferId()).status(BookBusinessConstants.CollectionStatus.COLLECTION_SUCCESSFUL.getCode())
                    .createUser(vo.getWxId()).createTime(new Date()).updateUser(vo.getWxId()).updateTime(new Date()).build();
            this.bookGroupCollectionDao.insert(bookGroupCollection);
        } else {
            // 修改收款状态为成功
            byTransferId.setStatus(BookBusinessConstants.CollectionStatus.COLLECTION_SUCCESSFUL.getCode());
            this.bookGroupCollectionDao.update(byTransferId);
        }
        String messageGroupId = UUID.randomUUID().toString();
        //发群规
        SendWxMsg4ReadingDTO sendWxMsg4ReadingDTO = new SendWxMsg4ReadingDTO();
        sendWxMsg4ReadingDTO.setCounts(1);
        sendWxMsg4ReadingDTO.setIndex(0);
        sendWxMsg4ReadingDTO.setMessageGroupId(messageGroupId);
        sendWxMsg4ReadingDTO.setRobotProcessTypeEnum(RobotProcessTypeEnum.READING_ACTIVITY);
        sendWxMsg4ReadingDTO.setSendMessageType(SendMessageTypeEnum.SELF.getCode());
        sendWxMsg4ReadingDTO.setRuleType(byTheme.getRuleType());
        sendWxMsg4ReadingDTO.setRobotId(vo.getAltId());
        sendWxMsg4ReadingDTO.setWxUserId(vo.getWxId());
        sendWxMsg4ReadingDTO.setContent(byTheme.getRule());
        sendWxMsg4ReadingDTO.setResourceId( byTheme.getRuleResourceId());
        sendWxMsg4ReadingDTO.setWxGroupId(null);
        this.sendWxMsg(sendWxMsg4ReadingDTO);
        // 发送邀请进群链接

        String messageGroupId4Link = UUID.randomUUID().toString();
        if (JoinTypeEnum.LINK.value.equals(byTheme.getJoinType())) {
            List<ReadingGroup> groupList = readingGroupDao.getByActivityId(byTheme.getId());
            if (CollectionUtils.isEmpty(groupList)) {
                throw new BookBizException(BookBizException.ID_NOT_EXIST, "活动没有可用群");
            }
            Map<String, Integer> groupUserNum = groupQrcodeBiz.getGroupUserNum(groupList.stream().map(ReadingGroup::getWxGroupId).collect(Collectors.toList()));
            String min = null;
            Integer num = 500;
            for (ReadingGroup group : groupList) {
                Integer integer = groupUserNum.get(group.getWxGroupId());
                if (integer < num) {
                    num = integer;
                    min = group.getWxGroupId();
                }
            }
            SendGroupInviteVO inviteVO = new SendGroupInviteVO();
            inviteVO.setWxGroupId(min);
            inviteVO.setAltId(vo.getAltId());
            inviteVO.setWxId(vo.getWxId());
            inviteVO.setIp(getIP(vo.getAltId()));
            WxGroupSDK.sendGroupInvite(inviteVO);
//            inviteVO.setMessageGroupId(messageGroupId4Link);
//            inviteVO.setCounts(1);
//            inviteVO.setIndex(0);
//            inviteVO.setRobotProcessType(RobotProcessTypeEnum.READING_ACTIVITY);
//            wechatGroupConsr.sendMessage(JSON.toJSONString(inviteVO));
        }
        // 发送群二维码图片
        if (JoinTypeEnum.QRCODE.value.equals(byTheme.getJoinType())) {
            SendPicMessageVO picMessageVO = new SendPicMessageVO();
            picMessageVO.setAltId(vo.getAltId());
            picMessageVO.setWxGroupId(vo.getWxId());
            picMessageVO.setPicUrl(byTheme.getJoinQrcodePic());
            picMessageVO.setIp(getIP(vo.getAltId()));
            picMessageVO.setCounts(1);
            picMessageVO.setIndex(0);
            picMessageVO.setMessageGroupId(messageGroupId);
            picMessageVO.setRobotProcessType(RobotProcessTypeEnum.READING_ACTIVITY);
            wechatGroupConsr.sendMessage(JSON.toJSONString(picMessageVO));
        }
    }

    @Override
    @ParamLog("创建共读活动")
    @Transactional(rollbackFor = Exception.class)
    public Long add(ReadingActivityBaseParamDTO readingActivityBaseParamDTO) {
        Boolean themeExist = readingActivityDao.themeExist(readingActivityBaseParamDTO.getTheme());
        if (themeExist){
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "活动主题名称已存在");
        }
        //活动创建
        Date inviteTime = DateUtils.getDateByStr(readingActivityBaseParamDTO.getInviteTime());
        Date startTime = null;
        Date endTime = null;
        if (JoinTypeEnum.LINK.value.equals(readingActivityBaseParamDTO.getJoinType())){
            startTime = DateUtils.getDateByStr(readingActivityBaseParamDTO.getStartTime());
            endTime = DateUtils.getDateByStr(readingActivityBaseParamDTO.getEndTime());
        }
        ReadingActivity readingActivity = new ReadingActivity();
        BeanUtils.copyProperties(readingActivityBaseParamDTO, readingActivity);
        readingActivity.setStartTime(startTime);
        readingActivity.setEndTime(endTime);
        readingActivity.setClockOpen(false);
        readingActivity.setClockResultOpen(false);
        readingActivity.setRiddleOpen(false);
        readingActivity.setAwardOpen(false);
        readingActivityDao.insert(readingActivity);
        Long activityId = readingActivity.getId();
        //邀请语
        List<ReadingInvite> inviteList = readingActivityBaseParamDTO.getInviteList();
        inviteList.forEach(readingInvite -> {
            readingInvite.setInviteTime(inviteTime);
            readingInvite.setActivityId(activityId);
            readingInvite.setCreateUser(readingActivityBaseParamDTO.getCreateUser());
        });
        readingInviteDao.insert(inviteList);
        //邀请用户
        List<ReadingUser> userList = readingActivityBaseParamDTO.getUserList();
        for (ReadingUser readingUser : userList) {
            readingUser.setActivityId(activityId);
            readingUser.setCreateUser(readingActivityBaseParamDTO.getCreateUser());
            if (StringUtil.isEmpty(readingUser.getAltId())) {
                BookGroupCipherUser bookGroupCipherUser = bookGroupCipherUserDao.getByWxUserId(readingUser.getWxUserId());
                if (null == bookGroupCipherUser) {
                    continue;
                }
                readingUser.setAltId(bookGroupCipherUser.getAltId());
            }
            if (JoinConditionEnum.NO.value.equals(readingActivity.getJoinCondition())) {
                readingUser.setJoinState(JoinStateEnum.JOIN.value);
            } else {
                readingUser.setJoinState(JoinStateEnum.NOT_JOIN.value);
            }
        }
        readingUserDao.insert(userList);
        //添加定时任务
        this.addQuartz(activityId, readingActivityBaseParamDTO);
        //根据人数建群
        this.createGroup(userList, readingActivity);
        return activityId;
    }

    @Override
    @ParamLog("修改共读活动基本设置")
    @Transactional(rollbackFor = Exception.class)
    public void update(ReadingActivityBaseParamDTO readingActivityBaseParamDTO) {
        Long activityId = readingActivityBaseParamDTO.getId();
        ReadingActivity originActivity = readingActivityDao.getById(activityId);
        Boolean themeUpdate = false;
        if (!readingActivityBaseParamDTO.getTheme().equals(originActivity.getTheme())){//修改了活动主题
            themeUpdate = true;
            Boolean themeExist = readingActivityDao.themeExist(readingActivityBaseParamDTO.getTheme());
            if (themeExist){
                throw new BookBizException(BookBizException.PARAM_IS_NULL, "活动主题名称已存在");
            }
        }
        //基本设置更新
        Date inviteTime = DateUtils.getDateByStr(readingActivityBaseParamDTO.getInviteTime());
        Date startTime = null;
        Date endTime = null;
        if (JoinTypeEnum.LINK.value.equals(readingActivityBaseParamDTO.getJoinType())){
            startTime = DateUtils.getDateByStr(readingActivityBaseParamDTO.getStartTime());
            endTime = DateUtils.getDateByStr(readingActivityBaseParamDTO.getEndTime());
        }
        ReadingActivity readingActivity = new ReadingActivity();
        BeanUtils.copyProperties(readingActivityBaseParamDTO, readingActivity);
        readingActivity.setStartTime(startTime);
        readingActivity.setEndTime(endTime);
        readingActivityDao.update(readingActivity);
        if (themeUpdate){
            //更新群名称
            List<ReadingGroup> groupList = readingGroupDao.getAllByActivityId(activityId);
            for (ReadingGroup group:groupList){
                String suffix = group.getWxGroupName().substring(group.getWxGroupName().length()-3);
                String groupNewName = readingActivityBaseParamDTO.getTheme() + suffix;
                readingGroupDao.updateGroupName(groupNewName, group.getId());
                if (!StringUtil.isEmpty(group.getWxGroupId())){//微信群已创建
                    String masterId = readingGroupRobotDao.getMasterRobotByWxGroupId(group.getWxGroupId());
                    SendWeixinRequestTools.changeGroupName(masterId,group.getWxGroupId(),groupNewName,getIP(masterId));
                }
            }
        }
        if (JoinTypeEnum.LINK.value.equals(readingActivityBaseParamDTO.getJoinType())){
            //删除开场语结束语定时任务
            deleteQuartzJob(ReadingActivityConstant.JOB_NAME_START, activityId);
            deleteQuartzJob(ReadingActivityConstant.JOB_NAME_END, activityId);
        }
        //删除邀请设置
        readingInviteDao.deleteByActivityId(activityId);
        //删除邀请语定时任务
        deleteQuartzJob(ReadingActivityConstant.JOB_NAME_INVITE, activityId);
        //新增邀请语设置
        List<ReadingInvite> inviteList = readingActivityBaseParamDTO.getInviteList();
        inviteList.forEach(readingInvite -> {
            readingInvite.setInviteTime(inviteTime);
            readingInvite.setActivityId(activityId);
            readingInvite.setCreateUser(readingActivityBaseParamDTO.getCreateUser());
        });
        readingInviteDao.insert(inviteList);
        //新增开场语结束语邀请语定时任务
        addQuartz(activityId, readingActivityBaseParamDTO);
    }

    @ParamLog("删除定时任务")
    private void deleteQuartzJob(String jobName, Long activityId) {
        try {
            scheduleService.deleteJob(jobName + activityId, ReadingActivityConstant.JOB_GROUP);
        } catch (Exception e) {
            log.error("删除定时任务失败,jobName=" + jobName + "+activityId+" + activityId);
        }
    }

    @Override
    @ParamLog("添加高级配置")
    @Transactional(rollbackFor = Exception.class)
    public void updateAdditionSetting(ReadingActivityAdditionParamDTO readingActivityAdditionParamDTO) {
        if (readingActivityAdditionParamDTO.getClockOpen()) {
            //添加打卡每日提醒定时任务
            deleteQuartzJob(ReadingActivityConstant.JOB_NAME_CLOCK_REMIND,readingActivityAdditionParamDTO.getId());
            addClockRemindQuartz(readingActivityAdditionParamDTO.getId(), readingActivityAdditionParamDTO.getClockRemindTime());
        }
        ReadingActivity readingActivity = new ReadingActivity();
        BeanUtils.copyProperties(readingActivityAdditionParamDTO, readingActivity);
        readingActivity.setId(readingActivityAdditionParamDTO.getId());
        readingActivityDao.updateAdditionSetting(readingActivity);
    }

    @ParamLog("添加打卡每日提醒定时任务")
    private void addClockRemindQuartz(Long id, String sendtime) {
        String cron;
        try {
            int hour = Integer.parseInt(sendtime.substring(0, 2));
            int minute = Integer.parseInt(sendtime.substring(3, 5));
            int second = Integer.parseInt(sendtime.substring(6, 8));
            cron = second + " " + minute + " " + hour + " * * ?";
        } catch (Exception e) {
            throw new BookBizException(BookBizException.ERROR, "时间格式错误");
        }
        ScheduleJob scheduleJob = new ScheduleJob();
        scheduleJob.setJobGroup(ReadingActivityConstant.JOB_GROUP);
        scheduleJob.setJobName(ReadingActivityConstant.JOB_NAME_CLOCK_REMIND + id);
        scheduleJob.setCronExpression(cron);

        CallBackParam callBackParam = new CallBackParam();
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("activityId", id);
        callBackParam.setParamMap(paramMap);
        callBackParam.setMethodName("sendClockRemind");
        callBackParam.setBeanName("readingActivityService");

        Map<String, Object> scheduleMap = new HashMap<>();
        scheduleMap.put("scheduleJob", scheduleJob);
        scheduleMap.put("callBackParam", callBackParam);
        try {
            scheduleService.addCronJob(scheduleMap);
        } catch (Exception e) {
            log.error("【共读活动】设置定时任务失败" + e.getMessage(), e);
        }
    }

    @ParamLog("创建定时任务")
    public void addQuartz(Long activityId,ReadingActivityBaseParamDTO readingActivityBaseParamDTO) {
        //邀请语定时任务
        this.addSendQuartzJob(activityId, DateUtils.getDateByStr(readingActivityBaseParamDTO.getInviteTime()), ReadingActivityConstant.JOB_NAME_INVITE, "sendInviteMsg");
        //群链接方式入群
        if (JoinTypeEnum.LINK.value.equals(readingActivityBaseParamDTO.getJoinType())) {
            //开场语定时任务
            this.addSendQuartzJob(activityId, DateUtils.getDateByStr(readingActivityBaseParamDTO.getStartTime()), ReadingActivityConstant.JOB_NAME_START, "sendStartMsg");
            //结束语定时任务
            this.addSendQuartzJob(activityId, DateUtils.getDateByStr(readingActivityBaseParamDTO.getEndTime()), ReadingActivityConstant.JOB_NAME_END, "sendEndMsg");
        }
    }

    @ParamLog("添加定时任务")
    public void addSendQuartzJob(Long activityId, Date sendTime, String jobName, String methodName) {
        Map<String, Object> map = new HashMap<>();
        map.put("activityId", activityId);
        ScheduleJob scheduleJob = new ScheduleJob();
        scheduleJob.setJobGroup(ReadingActivityConstant.JOB_GROUP);
        scheduleJob.setJobName(jobName + activityId);

        Long second = (sendTime.getTime() - System.currentTimeMillis()) / 1000;
        scheduleJob.setStartTime(second.intValue());
        scheduleJob.setStartTimeFormat("ss");
        scheduleJob.setRepeatCount(0);
        scheduleJob.setIntervalTime(0);
        scheduleJob.setIntervalTimeFormat("dd");

        CallBackParam callBackParam = new CallBackParam();
        callBackParam.setBeanName("readingActivityService");
        callBackParam.setMethodName(methodName);
        callBackParam.setParamMap(map);
        Map<String, Object> scheduleMap = new HashMap<>();
        scheduleMap.put("scheduleJob", scheduleJob);
        scheduleMap.put("callBackParam", callBackParam);
        try {
            scheduleService.addSimpleJob(scheduleMap);
        } catch (Exception e) {
            log.error("【共读活动】添加定时任务失败" + e.getMessage(), e);
        }
    }

    @ParamLog("创建群")
    public void createGroup(List<ReadingUser> userList, ReadingActivity readingActivity) {
        if (!JoinTypeEnum.LINK.value.equals(readingActivity.getJoinType())){
            return;
        }
        List<String> robotIdList = userList.stream().filter(s -> s.getAltId() != null).map(ReadingUser::getAltId).distinct().collect(Collectors.toList());
        if (ListUtils.isEmpty(robotIdList) || robotIdList.size()<3){
            log.info("小号数量小于3个，取其他号补充");
            Integer need = 3 - robotIdList.size();//所需数量
            if ("pro".equalsIgnoreCase(envStr)){
                List<String> altIds = wechatGroupConsr.getSelfRobotByRobotType(null);
                altIds.removeAll(robotIdList);
                if (need == 1) {
                    robotIdList.add(altIds.get(0));
                }else {
                    robotIdList.add(altIds.get(0));
                    robotIdList.add(altIds.get(1));
                }
            }else {
                String alt1="wxid_lw4vjnxjg45d22";//zyj
                // String alt2="p867263500";//dawei
                String alt2="wxid_uiydtw9ztp9x12";
                if (need == 1){
                    robotIdList.add(alt1);
                }else {
                    robotIdList.add(alt1);
                    robotIdList.add(alt2);
                }
            }
        }
        Integer groupCount = (userList.size()+robotIdList.size())/500 + 1;//每个群最多人数
        for (int i=1; i<=groupCount; i++){
            //根据小号创建群,初始微信群id为空，创建完后更新wxgroupid
            ReadingGroup readingGroup = new ReadingGroup();
            readingGroup.setWxGroupId(null);
            readingGroup.setActivityId(readingActivity.getId());
            readingGroup.setWxGroupName(readingActivity.getTheme() + "-"+ i +"群");
            readingGroup.setCreateUser(readingActivity.getCreateUser());
            readingGroupDao.insert(readingGroup);
            Long groupId = readingGroup.getId();
            List<ReadingGroupRobot> readingGroupRobots = new ArrayList<>();
            for (String altId : robotIdList) {
                ReadingGroupRobot readingGroupRobot = new ReadingGroupRobot();
                readingGroupRobot.setWxGroupId(null);
                readingGroupRobot.setIsMaster(false);
                readingGroupRobot.setAltId(altId);
                readingGroupRobot.setGroupId(groupId);
                readingGroupRobots.add(readingGroupRobot);
            }
            readingGroupRobotDao.insert(readingGroupRobots);
            String altId = robotIdList.get(0);//群主
            robotIdList.remove(0);//成员列表
            CreateGroupVO createGroupVO = new CreateGroupVO();
            createGroupVO.setMembers(robotIdList);
            createGroupVO.setAltId(altId);
            createGroupVO.setCode(SendMessageTypeEnum.GROUP.getCode());
            createGroupVO.setWxId(altId);
            createGroupVO.setIp(getIP(altId));
            WxGroupSDK.createGroup(createGroupVO);
            log.info("请求建群 createGroupVO：{}", createGroupVO);
        }
    }

    @Override
    @ParamLog("共读活动定时任务回调")
    public void sendQuartzMsg(String methodType, Long activityId) {
        ReadingActivity readingActivity = readingActivityDao.getById(activityId);
        if (null == readingActivity) {
            return;
        }
        //给用户发邀请语，群链接/二维码
        if ("invite".equals(methodType)) {
            sendInviteToUser(activityId);
            return;
        }
        //活动开始
        if ("start".equals(methodType)) {
            //群链接入群才能发群消息
            if (JoinTypeEnum.LINK.value.equals(readingActivity.getJoinType())) {
                //开场语
                sendToGroup(activityId, readingActivity.getStartSloganType(), readingActivity.getStartSlogan(), readingActivity.getStartResourceId());
            }
            return;
        }
        //活动结束
        if ("end".equals(methodType)) {
            //群链接入群才能发群消息
            if (JoinTypeEnum.LINK.value.equals(readingActivity.getJoinType())) {
                //结束语
                sendToGroup(activityId, readingActivity.getEndSloganType(), readingActivity.getEndSlogan(), readingActivity.getEndResourceId());
                //发送打卡成果
                sendClockResultToGroup(readingActivity);
                try {
                    Thread.sleep(2*60*1000);
                } catch (InterruptedException e) {
                    log.error("线程休眠2min失败"+e.getMessage());
                }
                //小号退群
                exitGroup(activityId);
            }
            //给用户发送活动奖励
            sendAwardToUser(readingActivity);
            return;
        }
    }

    @ParamLog("小号退群")
    private void exitGroup(Long activityId) {
        List<ReadingGroupRobot> groupRobotList = readingGroupRobotDao.getByActivityId(activityId);
        if (ListUtils.isEmpty(groupRobotList)) {
            log.error("没有可用的群");
            return;
        }
        ThreadPoolUtils.SEND_MESSAGE_THREAD_POOL.execute(() -> {
            for (ReadingGroupRobot groupRobot : groupRobotList) {
                String wxGroupId = groupRobot.getWxGroupId();
                String altId = groupRobot.getAltId();
                ExitGroupVO exitGroupVO = new ExitGroupVO();
                exitGroupVO.setAltId(altId);
                exitGroupVO.setCode(SendMessageTypeEnum.GROUP.getCode());
                exitGroupVO.setIp(getIP(altId));
                exitGroupVO.setWxGroupId(wxGroupId);
                exitGroupVO.setWxId(altId);
                WxGroupSDK.exitGroup(exitGroupVO);
                log.info("小号退群 exitGroupVO：{}", exitGroupVO);
            }
        });
    }

    @ParamLog("给用户发邀请语")
    public void sendInviteToUser(Long activityId) {
        ReadingActivity readingActivity = readingActivityDao.getById(activityId);
        if (null == readingActivity){
            return;
        }
        List<ReadingUser> userList = readingUserDao.getByActivityId(activityId, null);
        if (ListUtils.isEmpty(userList)) {
            return;
        }
        List<ReadingInvite> inviteList = readingInviteDao.getByActivityId(activityId);
        if (ListUtils.isEmpty(inviteList)) {
            return;
        }
        ThreadPoolUtils.SEND_MESSAGE_THREAD_POOL.execute(() -> {
            for (ReadingUser readingUser : userList) {
                String altId = readingUser.getAltId();
                String wxUserId = readingUser.getWxUserId();
                //邀请语
                String messageGroupId4invite = UUID.randomUUID().toString();
                Integer counts4invite = inviteList.size();
                Integer index4invite = 0;
                for (ReadingInvite invite : inviteList) {
                    SendWxMsg4ReadingDTO sendWxMsg4ReadingDTO = new SendWxMsg4ReadingDTO();
                    sendWxMsg4ReadingDTO.setCounts(counts4invite);
                    sendWxMsg4ReadingDTO.setIndex(index4invite);
                    sendWxMsg4ReadingDTO.setMessageGroupId(messageGroupId4invite);
                    sendWxMsg4ReadingDTO.setRobotProcessTypeEnum(RobotProcessTypeEnum.READING_ACTIVITY);
                    sendWxMsg4ReadingDTO.setSendMessageType(SendMessageTypeEnum.SELF.getCode());
                    sendWxMsg4ReadingDTO.setRuleType(invite.getInviteType());
                    sendWxMsg4ReadingDTO.setRobotId(altId);
                    sendWxMsg4ReadingDTO.setWxUserId(wxUserId);
                    sendWxMsg4ReadingDTO.setContent(invite.getInviteContent());
                    sendWxMsg4ReadingDTO.setResourceId(invite.getInviteResourceId());
                    sendWxMsg4ReadingDTO.setWxGroupId(null);
                    sendWxMsg(sendWxMsg4ReadingDTO);
                    index4invite++;
                }
                //无进群条件
                if (JoinConditionEnum.NO.value.equals(readingActivity.getJoinCondition())){
                    //发群规
                    SendWxMsg4ReadingDTO sendWxMsg4ReadingDTO = new SendWxMsg4ReadingDTO();
                    sendWxMsg4ReadingDTO.setCounts(1);
                    sendWxMsg4ReadingDTO.setIndex(0);
                    sendWxMsg4ReadingDTO.setMessageGroupId(UUID.randomUUID().toString());
                    sendWxMsg4ReadingDTO.setRobotProcessTypeEnum(RobotProcessTypeEnum.READING_ACTIVITY);
                    sendWxMsg4ReadingDTO.setSendMessageType(SendMessageTypeEnum.SELF.getCode());
                    sendWxMsg4ReadingDTO.setRuleType(readingActivity.getRuleType());
                    sendWxMsg4ReadingDTO.setRobotId(altId);
                    sendWxMsg4ReadingDTO.setWxUserId(wxUserId);
                    sendWxMsg4ReadingDTO.setContent(readingActivity.getRule());
                    sendWxMsg4ReadingDTO.setResourceId(readingActivity.getRuleResourceId());
                    sendWxMsg4ReadingDTO.setWxGroupId(null);
                    this.sendWxMsg(sendWxMsg4ReadingDTO);
                    //发群链接/群二维码
                    sendGroupInviteToUser(altId, wxUserId, readingActivity);
                }
                //关键词入群
                else if (JoinConditionEnum.KEYWORD.value.equals(readingActivity.getJoinCondition())){
                    String content = "请回复：“" + readingActivity.getJoinKeyword() + "”，我会将入群链接发送给您。";
                    SendWxMsg4ReadingDTO sendWxMsg4ReadingDTO = new SendWxMsg4ReadingDTO();
                    sendWxMsg4ReadingDTO.setCounts(1);
                    sendWxMsg4ReadingDTO.setIndex(0);
                    sendWxMsg4ReadingDTO.setMessageGroupId(UUID.randomUUID().toString());
                    sendWxMsg4ReadingDTO.setRobotProcessTypeEnum(RobotProcessTypeEnum.READING_ACTIVITY);
                    sendWxMsg4ReadingDTO.setSendMessageType(SendMessageTypeEnum.SELF.getCode());
                    sendWxMsg4ReadingDTO.setRuleType(ContentTypeEnum.TEXT.value);
                    sendWxMsg4ReadingDTO.setRobotId(altId);
                    sendWxMsg4ReadingDTO.setWxUserId(wxUserId);
                    sendWxMsg4ReadingDTO.setContent(content);
                    sendWxMsg4ReadingDTO.setResourceId(null);
                    sendWxMsg4ReadingDTO.setWxGroupId(null);
                    this.sendWxMsg(sendWxMsg4ReadingDTO);
                }
                //转账入群
                else if (JoinConditionEnum.TRANSFER.value.equals(readingActivity.getJoinCondition())){
                    String content = "活动名称：" + readingActivity.getTheme() + "\n活动费用：￥" + readingActivity.getJoinAmount()+
                            "\n若想参加本次活动，可直接转账给我，转账说明请填写活动名称。当转账金额与活动名称都符合时，我才会接受转账，" +
                            "接受后我将发送入群链接（若人数较多，可能会有延迟）。";
                    SendWxMsg4ReadingDTO sendWxMsg4ReadingDTO = new SendWxMsg4ReadingDTO();
                    sendWxMsg4ReadingDTO.setCounts(1);
                    sendWxMsg4ReadingDTO.setIndex(0);
                    sendWxMsg4ReadingDTO.setMessageGroupId(UUID.randomUUID().toString());
                    sendWxMsg4ReadingDTO.setRobotProcessTypeEnum(RobotProcessTypeEnum.READING_ACTIVITY);
                    sendWxMsg4ReadingDTO.setSendMessageType(SendMessageTypeEnum.SELF.getCode());
                    sendWxMsg4ReadingDTO.setRuleType(ContentTypeEnum.TEXT.value);
                    sendWxMsg4ReadingDTO.setRobotId(altId);
                    sendWxMsg4ReadingDTO.setWxUserId(wxUserId);
                    sendWxMsg4ReadingDTO.setContent(content);
                    sendWxMsg4ReadingDTO.setResourceId(null);
                    sendWxMsg4ReadingDTO.setWxGroupId(null);
                    this.sendWxMsg(sendWxMsg4ReadingDTO);
                }
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    log.error("线程休眠3s失败"+e.getMessage());
                }
            }
        });
    }

    @ParamLog("发送打卡成果")
    public void sendClockResultToGroup(ReadingActivity readingActivity) {
        if (!readingActivity.getClockResultOpen()){
            return;
        }
        String text = "本期活动结束了，有没有收获很大呢，快来看看我的成绩报告吧\n——> ";
        String clockLink = readingActivity.getClockLink();
        String originLink = UrlUtils.getUrl4Own(clockLink.replaceAll(UrlConstant.OWN_SHORT_URL, ""));
        // 原链接类似：https://app10035515.raysyun.com/clock/W35515/C35515/A1018656/custom/sign?isPreview=1&adviserId=12829
        String resultLink = originLink.replace("/sign","/report").concat("&readingActivityId=" + readingActivity.getId());
        String shortUrl4Own = UrlUtils.getShortUrl4Own(resultLink);
        sendToGroup(readingActivity.getId(),ContentTypeEnum.TEXT.value,text.concat(shortUrl4Own),null);
    }

    @ParamLog("发送活动奖励")
    public void sendAwardToUser(ReadingActivity readingActivity) {
        if (!readingActivity.getAwardOpen()) {
            return;
        }
        List<ReadingUser> userList = readingUserDao.getByActivityId(readingActivity.getId(), JoinStateEnum.JOIN.value);
        if (ListUtils.isEmpty(userList)) {
            return;
        }
        List<ReadingUser> readingUserList = new ArrayList<>();
        readingUserList.addAll(userList);
        ThreadPoolUtils.SEND_MESSAGE_THREAD_POOL.execute(() -> {
            for (ReadingUser readingUser : readingUserList) {
                String altId = readingUser.getAltId();
                String wxUserId = readingUser.getWxUserId();
                if (!StringUtil.isEmpty(readingActivity.getAwardText())) {
                    SendWxMsg4ReadingDTO sendWxMsg4ReadingDTO = new SendWxMsg4ReadingDTO();
                    sendWxMsg4ReadingDTO.setCounts(1);
                    sendWxMsg4ReadingDTO.setIndex(0);
                    sendWxMsg4ReadingDTO.setMessageGroupId(UUID.randomUUID().toString());
                    sendWxMsg4ReadingDTO.setRobotProcessTypeEnum(RobotProcessTypeEnum.READING_ACTIVITY);
                    sendWxMsg4ReadingDTO.setSendMessageType(SendMessageTypeEnum.SELF.getCode());
                    sendWxMsg4ReadingDTO.setRuleType( ContentTypeEnum.TEXT.value);
                    sendWxMsg4ReadingDTO.setRobotId(altId);
                    sendWxMsg4ReadingDTO.setWxUserId(wxUserId);
                    sendWxMsg4ReadingDTO.setContent(readingActivity.getAwardText());
                    sendWxMsg4ReadingDTO.setResourceId(null);
                    sendWxMsg4ReadingDTO.setWxGroupId(null);
                    sendWxMsg(sendWxMsg4ReadingDTO);
                }
                if (!StringUtil.isEmpty(readingActivity.getAwardPic())) {
                    sendSelfPic(altId, wxUserId, readingActivity.getAwardPic());
                }
            }
        });
    }

    @ParamLog("给群发送消息")
    public void sendToGroup(Long activityId, Integer contentType, String content, String resourceId) {
        List<ReadingGroup> groupList = readingGroupDao.getByActivityId(activityId);
        if (ListUtils.isEmpty(groupList)) {
            log.error("没有可用的群");
            return;
        }
        ThreadPoolUtils.SEND_MESSAGE_THREAD_POOL.execute(() -> {
            for (ReadingGroup group : groupList) {
                String wxGroupId = group.getWxGroupId();
                String altId = readingGroupRobotDao.getMasterRobotByWxGroupId(wxGroupId);
                if (StringUtil.isEmpty(altId)) {
                    continue;
                }
                SendWxMsg4ReadingDTO sendWxMsg4ReadingDTO = new SendWxMsg4ReadingDTO();
                sendWxMsg4ReadingDTO.setCounts(1);
                sendWxMsg4ReadingDTO.setIndex(0);
                sendWxMsg4ReadingDTO.setMessageGroupId(UUID.randomUUID().toString());
                sendWxMsg4ReadingDTO.setRobotProcessTypeEnum(RobotProcessTypeEnum.READING_ACTIVITY);
                sendWxMsg4ReadingDTO.setSendMessageType(SendMessageTypeEnum.GROUP.getCode());
                sendWxMsg4ReadingDTO.setRuleType( contentType);
                sendWxMsg4ReadingDTO.setRobotId(altId);
                sendWxMsg4ReadingDTO.setWxUserId(null);
                sendWxMsg4ReadingDTO.setContent(content);
                sendWxMsg4ReadingDTO.setResourceId(resourceId);
                sendWxMsg4ReadingDTO.setWxGroupId(wxGroupId);
                this.sendWxMsg(sendWxMsg4ReadingDTO);
            }
        });
    }

    @ParamLog("发送文本或文件")
    public void sendWxMsg(SendWxMsg4ReadingDTO readingDTO) {
        String ip = getIP(readingDTO.getRobotId());
        if (ContentTypeEnum.TEXT.value.equals(readingDTO.getRuleType())) {
            SendTextMessageVO sendTextMessageVO = new SendTextMessageVO();
            sendTextMessageVO.setContent(readingDTO.getContent());
            sendTextMessageVO.setAltId(readingDTO.getRobotId());
            if (SendMessageTypeEnum.SELF.getCode().equals(readingDTO.getSendMessageType())) {
                sendTextMessageVO.setWxGroupId(readingDTO.getWxUserId());
            } else if (SendMessageTypeEnum.GROUP.getCode().equals(readingDTO.getSendMessageType())) {
                sendTextMessageVO.setWxGroupId(readingDTO.getWxGroupId());
            }
            sendTextMessageVO.setIp(ip);
            sendTextMessageVO.setCode(readingDTO.getSendMessageType());
            sendTextMessageVO.setCounts(readingDTO.getCounts());
            sendTextMessageVO.setIndex(readingDTO.getIndex());
            sendTextMessageVO.setMessageGroupId(readingDTO.getMessageGroupId());
            sendTextMessageVO.setRobotProcessType(readingDTO.getRobotProcessTypeEnum());
            wechatGroupConsr.sendMessage(JSON.toJSONString(sendTextMessageVO));
            log.info("发送文本 sendTextMessageVO：{}", sendTextMessageVO);
            return;
        }
        if (ContentTypeEnum.FILE.value.equals(readingDTO.getRuleType())) {
            SendFileVO sendFileVO = new SendFileVO();
            FileUploadInfo fileUploadInfo = convertConsr.getByFileId(readingDTO.getResourceId());
            if (null == fileUploadInfo) {
                log.error("文件路径为空,resourceId"+readingDTO.getResourceId());
                return;
            }
            String fileName = fileUploadInfo.getName();
            String fileType = fileUploadInfo.getExt();
            log.info("fileName="+fileName+"+fileType+"+fileType);
            if (!StringUtil.isEmpty(fileType) && fileName.contains(fileType)){//去掉后缀
                fileName = fileName.substring(0, fileName.indexOf(fileType)-1);
            }
            sendFileVO.setFileName(fileName);
            sendFileVO.setFileUrl(fileUploadInfo.getUrl());
            sendFileVO.setIp(ip);
            sendFileVO.setAltId(readingDTO.getRobotId());
            if (SendMessageTypeEnum.SELF.getCode().equals(readingDTO.getSendMessageType())) {
                sendFileVO.setWxId(readingDTO.getWxUserId());
            } else if (SendMessageTypeEnum.GROUP.getCode().equals(readingDTO.getSendMessageType())) {
                sendFileVO.setWxGroupId(readingDTO.getWxGroupId());
                sendFileVO.setWxId(readingDTO.getWxGroupId());
            }
            sendFileVO.setCode(readingDTO.getSendMessageType());
            sendFileVO.setCounts(readingDTO.getCounts());
            sendFileVO.setIndex(readingDTO.getIndex());
            sendFileVO.setMessageGroupId(readingDTO.getMessageGroupId());
            sendFileVO.setRobotProcessType(readingDTO.getRobotProcessTypeEnum());
            wechatGroupConsr.sendMessage(JSON.toJSONString(sendFileVO));
            log.info("发送文件 sendFileVO：{}", sendFileVO);
            return;
        }
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
           log.error("线程休眠3s失败"+e.getMessage());
        }
    }

    @Override
    @ParamLog("关键词进群校验")
    public void receiveKeyWord(SendTextDTO sendTextDTO) {
        //个人号收到的消息
        if (SendMessageTypeEnum.SELF.getCode().equals(sendTextDTO.getCode())){
            String textContent = sendTextDTO.getTextContent().trim();
            String wxUserId = sendTextDTO.getWechatUserId();
            String wxId = sendTextDTO.getWxId();
            //关键词是否正确
            ReadingActivity readingActivity = readingActivityDao.getJoinActivityByKeyword(wxId, wxUserId, textContent);
            if (null != readingActivity){
                List<ReadingInvite> inviteList = readingInviteDao.getByActivityId(readingActivity.getId());
                Date inviteTime = new Date();
                if (!ListUtils.isEmpty(inviteList)){
                    inviteTime = inviteList.get(0).getInviteTime();
                }
                if (inviteTime.after(new Date())){
                    return;
                }
                //发群规
                SendWxMsg4ReadingDTO sendWxMsg4ReadingDTO = new SendWxMsg4ReadingDTO();
                sendWxMsg4ReadingDTO.setCounts(1);
                sendWxMsg4ReadingDTO.setIndex(0);
                sendWxMsg4ReadingDTO.setMessageGroupId(UUID.randomUUID().toString());
                sendWxMsg4ReadingDTO.setRobotProcessTypeEnum(RobotProcessTypeEnum.READING_ACTIVITY);
                sendWxMsg4ReadingDTO.setSendMessageType(SendMessageTypeEnum.SELF.getCode());
                sendWxMsg4ReadingDTO.setRuleType(readingActivity.getRuleType());
                sendWxMsg4ReadingDTO.setRobotId(wxId);
                sendWxMsg4ReadingDTO.setWxUserId(wxUserId);
                sendWxMsg4ReadingDTO.setContent(readingActivity.getRule());
                sendWxMsg4ReadingDTO.setResourceId(readingActivity.getRuleResourceId());
                sendWxMsg4ReadingDTO.setWxGroupId(null);
                this.sendWxMsg(sendWxMsg4ReadingDTO);
                //入群链接/群二维码
                this.sendGroupInviteToUser(wxId, wxUserId, readingActivity);
            }
        }
    }

    @ParamLog("个人号发送进群链接/群二维码")
    private void sendGroupInviteToUser(String altId, String userWxId, ReadingActivity readingActivity) {
        if (JoinTypeEnum.LINK.value.equals(readingActivity.getJoinType())){
            List<ReadingGroup> groupList = readingGroupDao.getByActivityId(readingActivity.getId());
            if (CollectionUtils.isEmpty(groupList)) {
                log.error("活动没有可用群,activityId=" + readingActivity.getId());
            }
            Map<String, Integer> groupUserNum = groupQrcodeBiz.getGroupUserNum(groupList.stream().map(ReadingGroup::getWxGroupId).collect(Collectors.toList()));
            String min = null;
            Integer num = 500;
            for (ReadingGroup group : groupList) {
                Integer integer = groupUserNum.get(group.getWxGroupId());
                if (integer < num) {
                    num = integer;
                    min = group.getWxGroupId();
                }
            }
            SendGroupInviteVO sendGroupInviteVO = new SendGroupInviteVO();
            sendGroupInviteVO.setAltId(altId);
            sendGroupInviteVO.setWxId(userWxId);
            sendGroupInviteVO.setWxGroupId(min);
            sendGroupInviteVO.setIp(getIP(altId));
            WxGroupSDK.sendGroupInvite(sendGroupInviteVO);
//            sendGroupInviteVO.setCounts(1);
//            sendGroupInviteVO.setIndex(0);
//            sendGroupInviteVO.setMessageGroupId(UUID.randomUUID().toString());
//            sendGroupInviteVO.setRobotProcessType(RobotProcessTypeEnum.READING_ACTIVITY);
//            wechatGroupConsr.sendMessage(sendGroupInviteVO);
            log.info("发送进群链接 sendGroupInviteVO：{}", sendGroupInviteVO);
            return;
        }
        if (JoinTypeEnum.QRCODE.value.equals(readingActivity.getJoinType())){
            this.sendSelfPic(altId, userWxId, readingActivity.getJoinQrcodePic());
            return;
        }
    }

    @ParamLog("个人号发送图片")
    private void sendSelfPic(String altId, String userWxId, String pic) {
        SendPicMessageVO sendPicMessageVO = new SendPicMessageVO();
        sendPicMessageVO.setCode(SendMessageTypeEnum.SELF.getCode());
        sendPicMessageVO.setAltId(altId);
        sendPicMessageVO.setWxGroupId(userWxId);
        sendPicMessageVO.setPicUrl(pic);
        sendPicMessageVO.setIp(getIP(altId));
        sendPicMessageVO.setCounts(1);
        sendPicMessageVO.setIndex(0);
        sendPicMessageVO.setMessageGroupId(UUID.randomUUID().toString());
        sendPicMessageVO.setRobotProcessType(RobotProcessTypeEnum.READING_ACTIVITY);
        wechatGroupConsr.sendMessage(JSON.toJSONString(sendPicMessageVO));
        log.info("发送图片sendPicMessage:"+sendPicMessageVO);
    }

    /**
     * 根据小号获取ip
     */
    @Override
    public String getIP(String altId) {
        String ip = null;
        GroupRobotDTO groupRobotDTO = wechatGroupConsr.getGroupRobotByWxId(altId);
        if (null != groupRobotDTO) {
            WeixinQrcodeGeneration weixinQrcodeGeneration = weixinQrcodeGenerationDao.getByGeneration(groupRobotDTO.getVersion());
            if (null != weixinQrcodeGeneration) {
                ip = weixinQrcodeGeneration.getWechatGroupIp();
            }
        }
        return ip;
    }

    @Override
    public ReadingActivityDTO getById(Long id) {
        ReadingActivity readingActivity = readingActivityDao.getById(id);
        if (null == readingActivity) {
            return new ReadingActivityDTO();
        }
        ReadingActivityDTO activityDTO = new ReadingActivityDTO();
        BeanUtils.copyProperties(readingActivity, activityDTO);
        List<ReadingInvite> inviteList = readingInviteDao.getByActivityId(id);
        List<ReadingUser> userList = readingUserDao.getByActivityId(id, null);
        AdvertisingBrandDTO advertisingBrandDTO = advertisingBrandDao.getBrandById(readingActivity.getBrandId());
        if (null != advertisingBrandDTO) {
            activityDTO.setBrandName(advertisingBrandDTO.getBrandName());
        }
        //填充活动资源
        setActivityResource(readingActivity, activityDTO);
        //填充邀请资源
        setInviteResource(inviteList, activityDTO);
        //小号用户分类
        setGroupingUser(userList, activityDTO);
        activityDTO.setUserList(userList);
        //邀请时间
        Date inviteTime = inviteList.get(0).getInviteTime();
        activityDTO.setInviteTime(inviteTime);
        return activityDTO;
    }

    /**
     * 小号用户分类
     */
    private void setGroupingUser(List<ReadingUser> userList, ReadingActivityDTO activityDTO) {
        List<String> altIds = userList.stream().filter(s -> s.getAltId() != null).map(ReadingUser::getAltId).distinct().collect(Collectors.toList());
        if (ListUtils.isEmpty(altIds)) {
            return;
        }
        Map<String, GroupUserDTO> baseInfoDTOMap = wechatGroupConsr.mapRobotInfoByIdList(altIds);
        List<GroupingUserDTO> groupingUserDTOList = new ArrayList<>();
        for (String altId : altIds) {
            GroupingUserDTO groupingUserDTO = new GroupingUserDTO();
            groupingUserDTO.setAltId(altId);
            if (!MapUtils.isEmpty(baseInfoDTOMap) && baseInfoDTOMap.containsKey(altId)) {
                GroupUserDTO baseInfoDTO = baseInfoDTOMap.get(altId);
                groupingUserDTO.setAltNickName(baseInfoDTO.getNickName());
                groupingUserDTO.setAltHeadPic(baseInfoDTO.getHeadPic());
                groupingUserDTO.setAltSex(baseInfoDTO.getSex());
            }
            //小号对应的各用户
            List<String> userIdList = userList.stream().filter(s -> s.getAltId().equals(altId)).map(ReadingUser::getWxUserId).distinct().collect(Collectors.toList());
            Map<String, GroupUserDTO> userDTOMap = wechatGroupConsr.mapWxUserInfoByWxIdList(userIdList);
            List<UserBaseDTO> userBaseDTOS = new ArrayList<>();
            for (String wxUserId : userIdList) {
                UserBaseDTO userBaseDTO = new UserBaseDTO();
                userBaseDTO.setWxUserId(wxUserId);
                if (!MapUtils.isEmpty(userDTOMap) && userDTOMap.containsKey(wxUserId)) {
                    GroupUserDTO userDTO = userDTOMap.get(wxUserId);
                    BeanUtils.copyProperties(userDTO, userBaseDTO);
                }
                userBaseDTOS.add(userBaseDTO);
            }
            groupingUserDTO.setUserBaseDTOS(userBaseDTOS);
            groupingUserDTOList.add(groupingUserDTO);
        }
        activityDTO.setGroupingUserList(groupingUserDTOList);
    }

    /**
     * 填充邀请资源
     */
    private void setInviteResource(List<ReadingInvite> inviteList, ReadingActivityDTO activityDTO) {
        for (ReadingInvite invite : inviteList) {
            if (ContentTypeEnum.FILE.value.equals(invite.getInviteType())){
                FileUploadInfo fileUploadInfo = convertConsr.getByFileId(invite.getInviteResourceId());
                if (null == fileUploadInfo) {
                    continue;
                }
                invite.setInviteResourceSize(fileUploadInfo.getUploadedSize());
                invite.setInviteResourceName(fileUploadInfo.getName());
            }
        }
        activityDTO.setInviteList(inviteList);
    }

    /**
     * 填充活动资源
     */
    private void setActivityResource(ReadingActivity readingActivity, ReadingActivityDTO activityDTO) {
        if (ContentTypeEnum.FILE.value.equals(readingActivity.getRuleType())) {
            FileUploadInfo fileUploadInfo = convertConsr.getByFileId(readingActivity.getRuleResourceId());
            if (null != fileUploadInfo){
                activityDTO.setRuleResourceSize(fileUploadInfo.getUploadedSize());
                activityDTO.setRuleResourceName(fileUploadInfo.getName());
            }
        }
        if (JoinTypeEnum.LINK.value.equals(readingActivity.getJoinType())) {
            if (null != readingActivity.getStartSloganType() && ContentTypeEnum.FILE.value.equals(readingActivity.getStartSloganType())) {
                FileUploadInfo fileUploadInfo = convertConsr.getByFileId(readingActivity.getStartResourceId());
                if (null != fileUploadInfo){
                    activityDTO.setStartResourceSize(fileUploadInfo.getUploadedSize());
                    activityDTO.setStartResourceName(fileUploadInfo.getName());
                }
            }
            if (null != readingActivity.getEndSloganType() && ContentTypeEnum.FILE.value.equals(readingActivity.getEndSloganType())) {
                FileUploadInfo fileUploadInfo = convertConsr.getByFileId(readingActivity.getEndResourceId());
                if (null != fileUploadInfo){
                    activityDTO.setEndResourceSize(fileUploadInfo.getUploadedSize());
                    activityDTO.setEndResourceName(fileUploadInfo.getName());
                }
            }
        }
    }


    @Override
    public void sendClockRemind(Long activityId) {
        ReadingActivity readingActivity = readingActivityDao.getById(activityId);
        if (null == readingActivity) {
            return;
        }
        if (!JoinTypeEnum.LINK.value.equals(readingActivity.getJoinType()) || !readingActivity.getClockOpen()) {
            return;
        }
        Date startTime = readingActivity.getStartTime();
        Date endTime = readingActivity.getEndTime();
        if (startTime != null && new Date().before(startTime)) {
            return;
        }
        if (endTime != null && new Date().after(endTime)) {
            deleteQuartzJob(ReadingActivityConstant.JOB_NAME_CLOCK_REMIND, activityId);
            return;
        }
        String text = readingActivity.getClockRemindContent();
        // 先将打卡短链转长链
        String hex = readingActivity.getClockLink().replaceAll(UrlConstant.OWN_SHORT_URL, "");
        String originLink = UrlUtils.getUrl4Own(hex);
        // 补充参数
        if(originLink.indexOf("?")>-1){
            originLink = originLink.concat("&readingActivityId="+readingActivity.getId());
        } else {
            originLink = originLink.concat("?readingActivityId="+readingActivity.getId());
        }
        text = text + "\n打卡链接：" + UrlUtils.getShortUrl4Own(originLink);;
        //发送提醒内容+打卡链接
        sendToGroup(activityId, ContentTypeEnum.TEXT.value, text, null);
    }

    @ParamLog("获取活动列表")
    @Override
    public PageBeanNew<ReadingActivityDTO> getList(Integer currentPage, Integer numPerPage) {
        if (currentPage < 0 || numPerPage <= 0) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "分页参数有误！");
        }
        PageBeanNew<ReadingActivityDTO> page = readingActivityDao.listPageNew(new PageParam(currentPage,numPerPage), new HashMap<>(), "getList");
        if (!ListUtils.isEmpty(page.getRecordList())) {
            List<Long> brandIds = new ArrayList<>();
            List<Long> activityIds = new ArrayList<>();
            for (ReadingActivityDTO readingActivityDTO : page.getRecordList()) {
                if (!brandIds.contains(readingActivityDTO.getBrandId())) {
                    brandIds.add(readingActivityDTO.getBrandId());
                }
                if (!activityIds.contains(readingActivityDTO.getId())) {
                    activityIds.add(readingActivityDTO.getId());
                }
            }
            Map<Long, AdvertisingBrand> brandMap = advertisingBrandDao.getMapByIds(brandIds);
            List<ActivityUserCountDTO> userCountDTOS = readingUserDao.getUserCountsByActivityIds(activityIds);
            //书刊缓存
            Boolean exist = JedisClusterUtils.exists(ACTIVITY_USER_BOOK);
            Map<Long, List<ActivityUserBookDTO>> userBookDTOSMap = new HashMap<>();
            if (!exist){
                ThreadPoolUtils.OTHER_THREAD_POOL.execute(()->{
                    this.setReadingActivityRedis();
                });
                List<ActivityUserBookDTO> userBookDTOS = readingUserDao.getBooksByActivityIds(activityIds);
                userBookDTOSMap = userBookDTOS.stream().collect(Collectors.groupingBy(ActivityUserBookDTO::getActivityId));
            }
            Map<Long, Integer> userCountMap = new HashMap<>();
            for (ActivityUserCountDTO activityUserCountDTO : userCountDTOS) {
                userCountMap.put(activityUserCountDTO.getActivityId(), activityUserCountDTO.getCount());
            }
            for (ReadingActivityDTO readingActivityDTO : page.getRecordList()) {
                AdvertisingBrand advertisingBrand = brandMap.get(readingActivityDTO.getBrandId());
                if (advertisingBrand != null) {
                    readingActivityDTO.setBrandName(advertisingBrand.getBrandName());
                }
                readingActivityDTO.setUserCount(userCountMap.get(readingActivityDTO.getId()));
                List<ActivityUserBookDTO> bookDTOS;
                if (!exist){
                    bookDTOS = userBookDTOSMap.get(readingActivityDTO.getId());
                }else {
                    bookDTOS = JedisClusterUtils.hgetJson2List(ACTIVITY_USER_BOOK,readingActivityDTO.getId().toString(),ActivityUserBookDTO.class);
                }
                if (ListUtils.isEmpty(bookDTOS)){
                    bookDTOS = readingUserDao.getBooksByActivityIds(Arrays.asList(readingActivityDTO.getId()));
                    JedisClusterUtils.hset2Json(ACTIVITY_USER_BOOK, readingActivityDTO.getId().toString(), bookDTOS);
                }
                readingActivityDTO.setActivityUserBookDTOS(bookDTOS);
            }
        }
        return page;
    }

    @Override
    @ParamLog("建群后进行分配")
    @Transactional(rollbackFor = Exception.class)
    public void assignGroup(AssignGroupDTO assignGroupDTO) {
        String wxGroupId = assignGroupDTO.getWxGroupId();
        String masterId = assignGroupDTO.getMasterId();
        ReadingGroupCreate groupCreate = new ReadingGroupCreate();
        groupCreate.setWxGroupId(wxGroupId);
        groupCreate.setMasterId(masterId);
        groupCreate.setUseState(0);
        readingGroupCreateDao.insert(groupCreate);
        ThreadPoolUtils.OTHER_THREAD_POOL.execute(()->{
            //群分配给活动
            this.assignGroupToActivity(wxGroupId, masterId);
        });
    }

    @ParamLog("群分配给活动")
    private void assignGroupToActivity(String wxGroupId, String masterId) {
        //最近建的无群id的群
        ReadingGroup readingGroup =  readingGroupDao.getLatestNullGroup(masterId);
        if (null == readingGroup){
            return;
        }
        Long aimGroupId = readingGroup.getId();
        List<ReadingGroupRobot> robots = readingGroupRobotDao.getByGroupId(aimGroupId);
        //更新wxgroupId
        readingGroupRobotDao.updateWxGroupByGroupId(wxGroupId, aimGroupId);
        readingGroupRobotDao.setMaster(masterId, aimGroupId);
        readingGroupDao.updateWxGroupIdById(wxGroupId, aimGroupId);
        readingGroupCreateDao.updateStateByWxGroupId(wxGroupId,1);
        //修改群名称
        SendWeixinRequestTools.changeGroupName(masterId,wxGroupId,readingGroup.getWxGroupName(),getIP(masterId));
        //上传到weixin_qrcode表
        String qrcodeUrl ="https://oss.5rs.me/oss/upload/image/png/0055b00c5c504a65951a850d6cf48c08.png";//过期码
        WeixinQrcode weixinQrcode = new WeixinQrcode();
        weixinQrcode.setCreateUser(0L);
        weixinQrcode.setQrcodeUrl(qrcodeUrl);
        weixinQrcode.setWeixinGroupId(wxGroupId);
        weixinQrcode.setRobotWxId(masterId);
        GroupRobotDTO groupRobotDTO = wechatGroupConsr.getGroupRobotByWxId(masterId);
        if (groupRobotDTO != null){
            weixinQrcode.setRobotId(Long.valueOf(groupRobotDTO.getId()));
        }else {
            log.error("getGroupRobotByWxId获取小号信息失败=" + masterId);
            weixinQrcode.setRobotId(0L);
        }
        weixinQrcode.setUpdateState(2);
        weixinQrcode.setUseState(1);
        weixinQrcode.setGeneration(6);
        Long qrcodeId = weixinQrcodeDao.insert(weixinQrcode);
        //添加到bookGroupQrcode
        GroupQrcode groupQrcode = new GroupQrcode();
        groupQrcode.setWeixinGroupId(wxGroupId);
        groupQrcode.setQrcodeUrl(qrcodeUrl);
        groupQrcode.setCreateUser(0L);
        groupQrcode.setWeixinQrcodeId(qrcodeId);
        groupQrcode.setUserNumber(robots.size()>3?robots.size():3);
        groupQrcode.setGroupSeq(1);
        groupQrcode.setGroupName(readingGroup.getWxGroupName());
        groupQrcode.setClassifyId(0L);
        groupQrcode.setQrcodeHeadUrl(readerConsr.getNineHeadUrl());
        groupQrcodeBiz.insert(groupQrcode);
    }

    @ParamLog("活动用户进群之后")
    @Override
    public void activityUserJoinGroup(AddWXGroupDTO addWXGroupDTO) {
        String weixinGroupId=addWXGroupDTO.getWechatGroupId();
        ReadingGroup readingGroup = readingGroupDao.getByWxGroupId(weixinGroupId);
        if (readingGroup!=null){
            List<String> nickNames = JedisClusterUtils.getJson(ACTIVITY_USER_JOIN_GROUP_USERS + weixinGroupId, List.class);
            if (nickNames == null) {
                nickNames = new ArrayList<>();
            }
            nickNames.add(addWXGroupDTO.getNickName());
            log.info("活动用新用户进群"+nickNames);
            JedisClusterUtils.setJson(ACTIVITY_USER_JOIN_GROUP_USERS + weixinGroupId, nickNames, 600);
            String value = JedisClusterUtils.getJson(ACTIVITY_USER_JOIN_GROUP_GUIDE + weixinGroupId, String.class);
            if (StringUtil.isEmpty(value)) {
                JedisClusterUtils.setJson(ACTIVITY_USER_JOIN_GROUP_GUIDE + weixinGroupId, weixinGroupId, 10);
                String nameStr = "";
                int i = 0;
                List<String> names = new ArrayList<>();
                for (String name : nickNames) {
                    if (i == 5) {
                        break;
                    }
                    names.add(name);
                    i++;
                }
                for (String nickName : names) {
                    nickNames.remove(nickName);
                    if (StringUtils.isNotEmpty(nickName)) {
                        nameStr=nameStr+"@"+nickName+" ";
                    }
                }
                JedisClusterUtils.setJson(ACTIVITY_USER_JOIN_GROUP_USERS + weixinGroupId, nickNames, 600);
                if (!StringUtil.isEmpty(nameStr)){
                    SendTextMessageVO sendTextMessageVO = new SendTextMessageVO();
                    sendTextMessageVO.setContent(nameStr+"，欢迎加入本群。");
                    sendTextMessageVO.setAltId(addWXGroupDTO.getWxId());
                    sendTextMessageVO.setWxGroupId(weixinGroupId);
                    sendTextMessageVO.setIp(addWXGroupDTO.getIp());
                    sendTextMessageVO.setCounts(1);
                    sendTextMessageVO.setIndex(0);
                    sendTextMessageVO.setMessageGroupId(UUID.randomUUID().toString());
                    sendTextMessageVO.setRobotProcessType(RobotProcessTypeEnum.READING_ACTIVITY);
                    wechatGroupConsr.sendMessage(JSON.toJSONString(sendTextMessageVO));
                }
            }
        }
    }

    @Override
    public Boolean isKeyWord(SendTextDTO sendTextDTO) {
        if (!SendMessageTypeEnum.SELF.getCode().equals(sendTextDTO.getCode())) {
            return false;
        }
        String textContent = sendTextDTO.getTextContent().trim();
        ReadingActivity readingActivity = readingActivityDao.getJoinActivityByKeyword(sendTextDTO.getWxId(), sendTextDTO.getWechatUserId(), textContent);
        if (null == readingActivity){
            return false;
        }
        List<ReadingInvite> inviteList = readingInviteDao.getByActivityId(readingActivity.getId());
        Date inviteTime = new Date();
        if (!ListUtils.isEmpty(inviteList)){
            inviteTime = inviteList.get(0).getInviteTime();
        }
        //在邀请时间之后
        if (inviteTime.before(new Date())){
            return true;
        }else {
            return false;
        }
    }

    @Override
    public ReadingActivityDTO getReadingActivityByWxGroupId(String wxGroupId) {
        return readingGroupDao.getDetailByWxGroupId(wxGroupId);
    }


    @Override
    public Long getReadingActivityDays4Wechat(Long readingActivityId) {
        ReadingActivity readingActivity = readingActivityDao.getById(readingActivityId);
        if (!ValidateUtils.isEmpty(readingActivity.getStartTime()) && !ValidateUtils.isEmpty(readingActivity.getEndTime())) {
            Long timeDiff = readingActivity.getEndTime().getTime() - readingActivity.getStartTime().getTime();
            return timeDiff / 86400000L + (timeDiff % 86400000L > 0 ? 1 : 0);
        } else {
            return 0L;
        }
    }

    /**
     * 添加书刊缓存
     */
    public void setReadingActivityRedis() {
        List<Long> activityIds = readingActivityDao.getAllActivityIds();
        if (ListUtils.isEmpty(activityIds)){
            return;
        }
        List<ActivityUserBookDTO> userBookDTOS = readingUserDao.getBooksByActivityIds(activityIds);
        if (ListUtils.isEmpty(userBookDTOS)){
            return;
        }
        Map<Long, List<ActivityUserBookDTO>> userBookDTOSMap = userBookDTOS.stream().collect(Collectors.groupingBy(ActivityUserBookDTO::getActivityId));
        for (Map.Entry<Long,List<ActivityUserBookDTO>> entrySet: userBookDTOSMap.entrySet()){
            JedisClusterUtils.hset2Json(ACTIVITY_USER_BOOK, entrySet.getKey().toString(), entrySet.getValue());
        }
    }
}
