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

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import com.pcloud.appcenter.app.dto.AppDto;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.biz.BookKeywordWarehouseBiz;
import com.pcloud.book.consumer.app.AppConsr;
import com.pcloud.book.consumer.channel.QrcodeSceneConsr;
import com.pcloud.book.consumer.resource.ProductConsr;
import com.pcloud.book.consumer.wechatgroup.WechatGroupConsr;
import com.pcloud.book.group.biz.BookGroupBiz;
import com.pcloud.book.group.biz.BookGroupClassifyBiz;
import com.pcloud.book.group.biz.GroupQrcodeBiz;
import com.pcloud.book.group.dao.AppTouchRecordDao;
import com.pcloud.book.group.dao.BookGroupClassifyDao;
import com.pcloud.book.group.dao.BookGroupDao;
import com.pcloud.book.group.dao.GroupQrcodeDao;
import com.pcloud.book.group.dao.JoinGroupCipherDao;
import com.pcloud.book.group.dto.BookGroupDTO;
import com.pcloud.book.group.dto.GroupClassifyQrcodeDTO;
import com.pcloud.book.group.dto.JoinGroupCipherDTO;
import com.pcloud.book.group.entity.AppTouchRecord;
import com.pcloud.book.group.entity.GroupQrcode;
import com.pcloud.book.group.entity.JoinGroupCipher;
import com.pcloud.book.group.enums.CipherTypeEnum;
import com.pcloud.book.group.enums.QrcodeStatusEnum;
import com.pcloud.book.group.enums.TouchTypeEnum;
import com.pcloud.book.group.tools.SendWeixinRequestTools;
import com.pcloud.book.group.vo.ClassifyNameVO;
import com.pcloud.book.group.vo.GroupQrcodeBaseInfoVO;
import com.pcloud.book.keywords.biz.BookKeywordBiz;
import com.pcloud.book.keywords.dao.BookKeywordDao;
import com.pcloud.book.keywords.dao.BookKeywordRecordDao;
import com.pcloud.book.keywords.dao.KeywordDao;
import com.pcloud.book.keywords.dto.KeywordDTO;
import com.pcloud.book.keywords.dto.KeywordStatisticsDTO;
import com.pcloud.book.keywords.dto.ReplyKeywordDTO;
import com.pcloud.book.keywords.dto.ServiceResourceDTO;
import com.pcloud.book.keywords.entity.BookKeyword;
import com.pcloud.book.keywords.entity.BookKeywordRecord;
import com.pcloud.book.keywords.entity.Keyword;
import com.pcloud.book.keywords.enums.ReplyTypeEnum;
import com.pcloud.book.keywords.vo.DeleteKeywordVO;
import com.pcloud.book.keywords.vo.KeywordVO;
import com.pcloud.book.keywords.vo.ListKeywordParam;
import com.pcloud.book.keywords.vo.ListKeywordVO;
import com.pcloud.book.keywords.vo.QrWeixinParam;
import com.pcloud.book.keywords.vo.SetKeywordVO;
import com.pcloud.book.keywords.vo.SetRankVO;
import com.pcloud.book.keywords.vo.UpdateKeywordVO;
import com.pcloud.channelcenter.base.constants.ChannelEnum;
import com.pcloud.channelcenter.qrcode.service.QrcodeSceneService;
import com.pcloud.channelcenter.qrcode.vo.MessageBookVO;
import com.pcloud.channelcenter.qrcode.vo.QrWeixinParamVO;
import com.pcloud.channelcenter.wechat.dto.AccountSettingDto;
import com.pcloud.common.constant.CacheConstant;
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.ResponseHandleUtil;
import com.pcloud.common.utils.bean.ResponesUtils;
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.resourcecenter.product.dto.ProductDto;
import com.pcloud.resourcecenter.product.dto.ProductTypeDto;
import com.pcloud.wechatgroup.group.dto.RobotReplyDTO;
import com.pcloud.wechatgroup.message.dto.SendTextDTO;
import com.sdk.wxgroup.ChangeNameVO;
import com.sdk.wxgroup.SendGroupInviteVO;
import com.sdk.wxgroup.SendMessageTypeEnum;
import com.sdk.wxgroup.WxGroupSDK;

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

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import lombok.extern.slf4j.Slf4j;

/**
 * @author lily
 * @date 2019/4/25 10:47
 */
@Slf4j
@Component("bookKeywordBiz")
public class BookKeywordBizImpl implements BookKeywordBiz {
    @Autowired
    private KeywordDao keywordDao;
    @Autowired
    private BookGroupDao bookGroupDao;
    @Autowired
    private BookKeywordDao bookKeywordDao;
    @Autowired
    private BookGroupClassifyBiz bookGroupClassifyBiz;
    @Autowired
    private QrcodeSceneConsr qrcodeSceneConsr;
    @Autowired
    private WechatGroupConsr wechatGroupConsr;
    @Autowired
    private BookKeywordRecordDao bookKeywordRecordDao;
    @Autowired
    private ProductConsr productConsr;
    @Autowired
    private AppConsr appConsr;
    @Autowired
    private AppTouchRecordDao appTouchRecordDao;
    @Autowired
    private GroupQrcodeDao groupQrcodeDao;
    @Resource
    private BookKeywordWarehouseBiz bookKeywordWarehouseBiz;
    @Autowired
    private BookGroupClassifyDao bookGroupClassifyDao;
    @Autowired
    private QrcodeSceneService qrcodeSceneService;
    @Autowired
    private BookGroupBiz bookGroupBiz;
    @Autowired
    private GroupQrcodeBiz groupQrcodeBiz;
    @Autowired
    private JoinGroupCipherDao joinGroupCipherDao;

    @Override
    @ParamLog("新增关键词")
    @Transactional(rollbackFor = Exception.class)
    public void insertKeyword(SetKeywordVO setKeywordVO) {
        if (null == setKeywordVO || setKeywordVO.check()) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "应用/作品信息为空");
        }
        if (setKeywordVO.getClassifyId() == null) {
            setKeywordVO.setClassifyId(0L);
        }
        //获取图书相关信息
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(setKeywordVO.getBookGroupId());
        if (bookGroupDTO == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "该社群码不存在！");
        }
        //校验关键词
        checkKeyword(setKeywordVO.getKeywords(), setKeywordVO.getClassifyId(), setKeywordVO.getBookGroupId(), null);
        Integer count = bookKeywordDao.getKeywordCount(setKeywordVO.getBookGroupId(), setKeywordVO.getClassifyId());
        if (count >= 200) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "超出关键词数量限制");
        }
        //新增关键词
        Keyword keyword = new Keyword();
        BeanUtils.copyProperties(setKeywordVO, keyword);
        keyword.setCreateUser(setKeywordVO.getUserId());
        keywordDao.insert(keyword);
        //上架商品
        List<Long> productIds = new ArrayList<>();
        if (ReplyTypeEnum.APP.value.equals(keyword.getReplyType()) && "PRODUCT".equalsIgnoreCase(keyword.getServeType())) {
            productIds.add(keyword.getServeId());
        }
        productConsr.productAutoOnShelves(bookGroupDTO.getChannelId(), productIds);
        //新增关键词与分类或者图书的关系
        //按群创建
        if (setKeywordVO.getSetType() == 1) {
            BookKeyword bookKeyword = new BookKeyword();
            BeanUtils.copyProperties(setKeywordVO, bookKeyword);
            bookKeyword.setKeywordId(keyword.getId());
            bookKeyword.setBookId(bookGroupDTO.getBookId());
            bookKeyword.setChannelId(bookGroupDTO.getChannelId());
            //获取最大排序值
            Integer rank = bookKeywordDao.getMaxRank(setKeywordVO.getBookGroupId(), bookKeyword.getClassifyId());
            bookKeyword.setRank(rank + 1);
            bookKeyword.setCreateUser(setKeywordVO.getUserId());
            if (null != setKeywordVO.getAddWarehouse() && 1 == setKeywordVO.getAddWarehouse()) {
                setKeywordVO.setChannelId(bookGroupDTO.getChannelId());
                final Long warehouseId = bookKeywordWarehouseBiz.addBookKeyword(setKeywordVO);
                bookKeyword.setWarehouseId(warehouseId);
                bookKeyword.setIsWarehouse(1);
            }
            if (null == bookKeyword.getIsWarehouse()) {
                bookKeyword.setIsWarehouse(0);
            }
            if (null == bookKeyword.getWarehouseId()) {
                bookKeyword.setWarehouseId(0L);
            }
            bookKeyword.setIsEdit(1);
            bookKeywordDao.insert(bookKeyword);
        } else {
            //按书创建
            List<ClassifyNameVO> classifyNameVOS = bookGroupClassifyDao.listClassifyByRank(setKeywordVO.getBookGroupId());
            List<BookKeyword> bookKeywords = new ArrayList<>();
            //创建书的记录
            BookKeyword bookKeyword = new BookKeyword();
            BeanUtils.copyProperties(setKeywordVO, bookKeyword);
            bookKeyword.setKeywordId(keyword.getId());
            bookKeyword.setBookId(bookGroupDTO.getBookId());
            bookKeyword.setChannelId(bookGroupDTO.getChannelId());
            //获取最大排序值
            Integer rank = bookKeywordDao.getMaxRank(setKeywordVO.getBookGroupId(), bookKeyword.getClassifyId());
            bookKeyword.setRank(rank + 1);
            bookKeyword.setCreateUser(setKeywordVO.getUserId());
            if (null != setKeywordVO.getAddWarehouse() && 1 == setKeywordVO.getAddWarehouse()) {
                setKeywordVO.setChannelId(bookGroupDTO.getChannelId());
                final Long warehouseId = bookKeywordWarehouseBiz.addBookKeyword(setKeywordVO);
                bookKeyword.setWarehouseId(warehouseId);
                bookKeyword.setIsWarehouse(1);
            }
            //创建群的记录
            if (!ListUtils.isEmpty(classifyNameVOS)) {
                classifyNameVOS.forEach(e -> {
                    BookKeyword cKeyword = new BookKeyword();
                    BeanUtils.copyProperties(setKeywordVO, cKeyword);
                    cKeyword.setKeywordId(keyword.getId());
                    cKeyword.setBookId(bookGroupDTO.getBookId());
                    cKeyword.setChannelId(bookGroupDTO.getChannelId());
                    cKeyword.setClassifyId(e.getId());
                    //获取最大排序值
                    Integer rank1 = bookKeywordDao.getMaxRank(setKeywordVO.getBookGroupId(), cKeyword.getClassifyId());
                    cKeyword.setRank(rank1 + 1);
                    cKeyword.setCreateUser(setKeywordVO.getUserId());
                    if (null != setKeywordVO.getAddWarehouse() && 1 == setKeywordVO.getAddWarehouse()) {
                        // 书入库一遍，同样的就不要入库了
//                        setKeywordVO.setChannelId(bookGroupDTO.getChannelId());
//                        final Long warehouseId = bookKeywordWarehouseBiz.addBookKeyword(setKeywordVO);
                        cKeyword.setWarehouseId(bookKeyword.getWarehouseId());
                        cKeyword.setIsWarehouse(1);
                    }
                    if (null == cKeyword.getIsWarehouse()) {
                        cKeyword.setIsWarehouse(0);
                    }
                    if (null == cKeyword.getWarehouseId()) {
                        cKeyword.setWarehouseId(0L);
                    }
                    if (0 == cKeyword.getClassifyId()) {
                        cKeyword.setIsEdit(1);
                    } else {
                        cKeyword.setIsEdit(0);
                    }
                    bookKeywords.add(cKeyword);
                });
            }
            if (null == bookKeyword.getIsWarehouse()) {
                bookKeyword.setIsWarehouse(0);
            }
            if (null == bookKeyword.getWarehouseId()) {
                bookKeyword.setWarehouseId(0L);
            }
            if (0 == bookKeyword.getClassifyId()) {
                bookKeyword.setIsEdit(1);
            } else {
                bookKeyword.setIsEdit(0);
            }
            bookKeywords.add(bookKeyword);
            bookKeywordDao.insert(bookKeywords);
        }

    }

    @Override
    @ParamLog("批量新增关键词")
    @Transactional(rollbackFor = {Exception.class})
    public void insertKeywords(List<SetKeywordVO> setKeywordVOs, Long partyId) {
        if (CollectionUtils.isEmpty(setKeywordVOs) || null == partyId) {
            log.info("[insertKeywords] : setKeywordVOs:{}, partyId:{}", setKeywordVOs, partyId);
            return;
        }
        for (SetKeywordVO vo : setKeywordVOs) {
            vo.setUserId(partyId);
            this.insertKeyword(vo);
        }
    }

    @ParamLog("校验关键词是否重复")
    private void checkKeyword(String keywords, Long classifyId, Long bookGroupId, Long keywordId) {
        Boolean isHaveKeyword = bookKeywordDao.checkKeyword(keywords, classifyId, bookGroupId, keywordId);
        if (isHaveKeyword) {
            throw new BookBizException(BookBizException.ERROR, "该关键词已存在！");
        }
    }

    @Override
    @ParamLog("更新关键词")
    @Transactional(rollbackFor = Exception.class)
    public void updateKeyword(UpdateKeywordVO updateKeywordVO, Long partyId) {
        checkKeyword(updateKeywordVO.getKeywords(), updateKeywordVO.getClassifyId(), updateKeywordVO.getBookGroupId(), updateKeywordVO.getKeywordId());
        //获取图书相关信息
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(updateKeywordVO.getBookGroupId());
        if (bookGroupDTO == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "该社群码不存在！");
        }
        if (null != updateKeywordVO.getAddWarehouse() && 1 == updateKeywordVO.getAddWarehouse()) {
            SetKeywordVO v = new SetKeywordVO();
            BeanUtils.copyProperties(updateKeywordVO, v);
            if (ChannelEnum.APP.value.equals(updateKeywordVO.getServeType())) {
                final AppDto baseById = appConsr.getBaseById(updateKeywordVO.getServeId());
                if (null == baseById) {
                    throw new BookBizException(BookBizException.ID_NOT_EXIST, "应用不存在");
                }
                v.setTypeCode(baseById.getTypeCode());
            }
            if (ChannelEnum.PRODUCT.value.equals(updateKeywordVO.getServeType())) {
                final ProductDto proBaseById = productConsr.getProBaseById(updateKeywordVO.getServeId());
                if (null == proBaseById) {
                    throw new BookBizException(BookBizException.ID_NOT_EXIST, "作品不存在");
                }
                v.setTypeCode(proBaseById.getProductTypeCode());
            }
            v.setUserId(partyId);
            v.setChannelId(bookGroupDTO.getChannelId());
            final Long warehouseId = this.bookKeywordWarehouseBiz.addBookKeyword(v);
            this.bookKeywordDao.updateIsWarehouse(updateKeywordVO.getBookKeywordId(), warehouseId);
        }
        Keyword keyword = new Keyword();
        BeanUtils.copyProperties(updateKeywordVO, keyword);
        keyword.setId(updateKeywordVO.getKeywordId());
        keyword.setUpdateUser(partyId);
        keywordDao.update(keyword);
        //上架商品
        List<Long> productIds = new ArrayList<>();
        if (ReplyTypeEnum.APP.value.equals(keyword.getReplyType()) && ChannelEnum.PRODUCT.value.equalsIgnoreCase(keyword.getServeType())) {
            productIds.add(keyword.getServeId());
        }
        productConsr.productAutoOnShelves(bookGroupDTO.getChannelId(), productIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @ParamLog("删除关键词")
    public void deleteKeyword(DeleteKeywordVO deleteKeywordVO, Long partyId) {
        if (deleteKeywordVO == null || deleteKeywordVO.getIsEdit() == null || deleteKeywordVO.getKeywordId() == null) {
            throw new BookBizException(BookBizException.ERROR, "缺少必要参数");
        }
        if (deleteKeywordVO.getClassifyId() == null) {
            deleteKeywordVO.setClassifyId(0L);
        }
        if (deleteKeywordVO.getIsEdit() == 1) {
            keywordDao.deleteById(deleteKeywordVO.getKeywordId(), partyId);
            bookKeywordDao.deleteById(deleteKeywordVO.getKeywordId(), partyId);
        } else {
            bookKeywordDao.deleteKeywords(deleteKeywordVO.getKeywordId(), deleteKeywordVO.getBookGroupId(), deleteKeywordVO.getClassifyId(), partyId);
        }

    }

    @Override
    @ParamLog("设置排序值")
    public void setRank(SetRankVO setRankVO, Long partyId) {
        BookKeyword bookKeyword = new BookKeyword();
        bookKeyword.setId(setRankVO.getBookKeywordId());
        bookKeyword.setRank(setRankVO.getRank());
        bookKeyword.setUpdateUser(partyId);
        KeywordVO byBookKeyword = bookKeywordDao.getByBookKeyword(setRankVO.getBookKeywordId());
        if (byBookKeyword != null && (byBookKeyword.getClassifyId() == null || byBookKeyword.getClassifyId() == 0)){
            Long bookGroupId = byBookKeyword.getBookGroupId();
            Long keywordId = byBookKeyword.getKeywordId();
            bookKeywordDao.updateRank(bookGroupId,setRankVO.getRank(),partyId,keywordId);
        }else {
            bookKeywordDao.setRank(bookKeyword);
        }
    }

    @Override
    @ParamLog("获取关键词列表")
    public PageBeanNew<ListKeywordVO> listKeywordsByClassify(ListKeywordParam listKeywordParam) {
        PageParam pageParam = new PageParam(listKeywordParam.getCurrentPage(), listKeywordParam.getNumPerPage());
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("keywords", listKeywordParam.getKeywords());
        paramMap.put("classifyId", listKeywordParam.getClassifyId());
        paramMap.put("bookGroupId", listKeywordParam.getBookGroupId());
        PageBeanNew<ListKeywordVO> keywords = bookKeywordDao.listPageNew(pageParam, paramMap, "listKeywordsByClassify");
        if (keywords == null) {
            return new PageBeanNew<>(listKeywordParam.getCurrentPage(), listKeywordParam.getNumPerPage(), new ArrayList<>());
        }
        final List<Long> appIds = Lists.newArrayList();
        final List<Long> productIds = Lists.newArrayList();
        for (ListKeywordVO vo : keywords.getRecordList()) {
            if ("APP".equalsIgnoreCase(vo.getServeType())) {
                appIds.add(vo.getServeId());
            }
            if ("PRODUCT".equalsIgnoreCase(vo.getServeType())) {
                productIds.add(vo.getServeId());
            }
            if (vo.getIsEdit() == null) {
                vo.setIsEdit(1);
            }
        }
        Map<Long, AppDto> app = Maps.newHashMap();
        if (!CollectionUtils.isEmpty(appIds)) {
            app = appConsr.mapBaseByIds(appIds);
        }
        Map<Long, ProductDto> proBasesByIds = Maps.newHashMap();
        if (!CollectionUtils.isEmpty(productIds)) {
            proBasesByIds = productConsr.getProBasesByIds(productIds);
        }
        final BookGroupDTO dtoById = bookGroupDao.getDTOById(listKeywordParam.getBookGroupId());
        for (ListKeywordVO vo : keywords.getRecordList()) {
            if ("APP".equalsIgnoreCase(vo.getServeType())) {
                final AppDto appDto = app.get(vo.getServeId());
                if (null == appDto) {
                    continue;
                }
                vo.setChannelId(appDto.getChannelId());
                vo.setTypeCode(appDto.getTypeCode());
            }
            if ("PRODUCT".equalsIgnoreCase(vo.getServeType())) {
                final ProductDto productDto = proBasesByIds.get(vo.getServeId());
                if (null == productDto || null == productDto.getProductTypeDto()) {
                    continue;
                }
                vo.setChannelId(dtoById.getChannelId());
                vo.setTypeCode(productDto.getProductTypeDto().getTypeCode());
            }
        }
        return keywords;
    }

    @Override
    @ParamLog("根据关键词标识获取关键词基本信息")
    public KeywordVO getByBookKeyword(Long bookKeywordId) {
        KeywordVO keywordVO = bookKeywordDao.getByBookKeyword(bookKeywordId);
        return keywordVO;
    }

    @Override
    @ParamLog("获取5个关键词（改成10个了,20190911周磊改成不限制了，但是开发要求必须要加限制，所以先限制40个）")
    public List<KeywordDTO> listFiveKeyword(Long classifyId, Long bookGroupId) {
        //获取是否单独设置关键词
        List<KeywordDTO> keywords = bookKeywordDao.listFiveKeyword(classifyId, bookGroupId);
        if (ListUtils.isEmpty(keywords)) {
            keywords = bookKeywordDao.listFiveKeyword(0L, bookGroupId);
        }
        return keywords;
    }

    @Override
    @ParamLog("关键词消息回复")
    public void sendKeywordMessage(SendTextDTO sendTextDTO) {
        if (Objects.isNull(sendTextDTO)) {
            return;
        }
        // 刘娜需求 1001282 群不推送关键词
        final String content = sendTextDTO.getTextContent().trim();
        final String userWxId = sendTextDTO.getWechatUserId();
        final String ip = sendTextDTO.getIp();
        final Integer code = sendTextDTO.getCode();
        String robotId = sendTextDTO.getWxId();
        if (SendMessageTypeEnum.GROUP.getCode().equals(sendTextDTO.getCode())) {
            this.sendKeywordMessageToGroup(sendTextDTO);
            return;
        }
        if (SendMessageTypeEnum.SELF.getCode().equals(sendTextDTO.getCode())) {
            //根据机器人id和wxId和类型获取暗号信息
            List<JoinGroupCipher> joinGroupCiphers = joinGroupCipherDao.getListByAltIdAndWxIdAndType(robotId, userWxId, CipherTypeEnum.BOOK_GROUP_CIPHER.code);
            if (!ListUtils.isEmpty(joinGroupCiphers)) {
                inviteToGroupByKeyword(sendTextDTO, joinGroupCiphers);
            }
        }

        //个人机器人接收消息的时候，weixinGroupId就是userWxId，也就是用户的id，robotId是接收的机器人的id
        //简单过滤非关键词的词
        if (StringUtil.isEmpty(content) || content.length() > 20) {
            return;
        }
        // TODO 根据小号和用户id获取所有相关的分类id，若该关键词存在多本书，则组装成文本加链接一次发送
        final List<JoinGroupCipherDTO> dtos = bookGroupBiz.getClassifyIdsByWxIdAndAltId(userWxId, robotId);
        if (CollectionUtils.isEmpty(dtos)) {
            log.info("[关键词消息回复] classifyIds is null");
            return;
        }
        final Set<Long> cIds = Sets.newHashSet();
        final Set<Long> bIds = Sets.newHashSet();
        Map<Long, Long> classifyToBookGroupMap = new HashMap<>();
        Map<Long, Long> classifyToQrcodeMap = new HashMap<>();
        for (JoinGroupCipherDTO dto : dtos) {
            cIds.add(dto.getClassifyId());
            bIds.add(dto.getBookGroupId());
            classifyToBookGroupMap.put(dto.getClassifyId(), dto.getBookGroupId());
            classifyToQrcodeMap.put(dto.getClassifyId(), dto.getQrcodeId());
        }
        final List<Long> classifyIds = Lists.newArrayList(cIds);
        List<ReplyKeywordDTO> replyKeywordDTOs = new ArrayList<>();
        Map<Long, Long> keywordClassifyIdMap = new HashMap<>();
        List<Long> keywordIds = new ArrayList<>();
        for (Long classifyId : classifyIds) {
            //获取匹配关键词
            ReplyKeywordDTO replyKeywordDTO = bookKeywordDao.getKeywordId(classifyId, classifyToBookGroupMap.get(classifyId), content);
            if (replyKeywordDTO == null) {
                continue;
            }
            keywordClassifyIdMap.put(replyKeywordDTO.getKeywordId(), classifyId);
            //避免一本书下两个分类的关键词重复
            if (!keywordIds.contains(replyKeywordDTO.getKeywordId())) {
                replyKeywordDTOs.add(replyKeywordDTO);
                keywordIds.add(replyKeywordDTO.getKeywordId());
            }
        }
        final List<GroupClassifyQrcodeDTO> qrcodeDTOS = bookGroupClassifyBiz.listClassifyQrcodeInfo(classifyIds);
        if (CollectionUtils.isEmpty(replyKeywordDTOs)) {
            log.info("[关键词消息回复] keywordIds is null");
            return;
        }
        if (CollectionUtils.isEmpty(qrcodeDTOS)) {
            log.info("[关键词消息回复] qrcodeDTOS is null");
            return;
        }
        final Map<Long, GroupClassifyQrcodeDTO> classifyMap = qrcodeDTOS.stream().collect(Collectors.toMap(GroupClassifyQrcodeDTO::getClassifyId, p -> p, (v1, v2) -> v2));
        // 记录循环插入，消息一条发送
        for (ReplyKeywordDTO replyKeywordDTO : replyKeywordDTOs) {
            log.info("[关键词回复原始数据] ： sendKeywordMessage replyKeywordDTO ：{}, robotId:{}, altId:{}", replyKeywordDTO, robotId, userWxId);
            // 处理链接地址
            Long classifyId = keywordClassifyIdMap.get(replyKeywordDTO.getKeywordId());
            final GroupClassifyQrcodeDTO dto = classifyMap.get(classifyId);
            if (null == dto) {
                log.info("[关键词消息回复] 分类信息为空 replyKeywordDTO：{}; classifyMap:{}", replyKeywordDTO, classifyMap);
                continue;
            }
            final boolean isApp = ReplyTypeEnum.APP.value.equals(replyKeywordDTO.getReplyType());
            final boolean isLink = ReplyTypeEnum.LINK.value.equals(replyKeywordDTO.getReplyType());
            Long qrcodeId = classifyToQrcodeMap.get(dto.getClassifyId());
            GroupQrcodeBaseInfoVO qrcodeInfo = groupQrcodeDao.getBaseById(qrcodeId);
            if (isApp || isLink) {
                AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(dto.getChannelId());
                String linkUrl = SendWeixinRequestTools.splitUrlNew(accountSettingDto, replyKeywordDTO.getLinkUrl(), dto.getBookGroupId(), dto.getClassifyId(), qrcodeId);
                replyKeywordDTO.setLinkUrl(linkUrl);
                if (!StringUtil.isEmpty(linkUrl)) {
                    replyKeywordDTO.setShortLinkUrl(UrlUtils.getShortUrl4Own(linkUrl));
                }
            }
            String redisContent = JedisClusterUtils.getJson("BOOK:KEYWORD:" + userWxId + "-" + replyKeywordDTO.getKeywordId(), String.class);
            // 同一群10秒内不回复同一关键词
            if (insertBookKeywordRecord(qrcodeInfo.getWeixinGroupId(), userWxId, replyKeywordDTO, dto, redisContent)) {
                return;
            }
            //获取推送消息机器人
            // 20190704改为收发一体
            if (StringUtil.isBlank(robotId)) {
                log.info("[关键词消息回复] robotId is null content:{}, robotId:{},weixinGroupId:{}", content, robotId, qrcodeInfo.getWeixinGroupId());
                robotId = wechatGroupConsr.getRobotIdByGroupId(qrcodeInfo.getWeixinGroupId());
            }
            log.info("[关键词回复发送数据] ： sendKeywordMessage replyKeywordDTO ：{}, robotId:{}, weixinGroupId:{}", replyKeywordDTO, robotId, qrcodeInfo.getWeixinGroupId());
            //新增关键词触发记录
            addKeywordAppTouchRecord(replyKeywordDTO, qrcodeInfo.getWeixinGroupId(), dto.getClassifyId(), dto.getBookGroupId());
        }
        // 单条还是按原来的发送
        if (replyKeywordDTOs.size() <= 1) {
            SendWeixinRequestTools.sendKeywordMessage(replyKeywordDTOs.get(0), robotId, userWxId, ip, code);
        } else {
            // 多条时文字，应用，链接组装成一条发送
            ReplyKeywordDTO d = new ReplyKeywordDTO();
            final StringBuilder sb = new StringBuilder();
            for (ReplyKeywordDTO dto : replyKeywordDTOs) {
                if (ReplyTypeEnum.APP.value.equals(dto.getReplyType()) || ReplyTypeEnum.LINK.value.equals(dto.getReplyType())) {
                    sb.append(dto.getKeywords()).append(":").append(dto.getShortLinkUrl()).append("\n");
                } else if (ReplyTypeEnum.TEXT.value.equals(dto.getReplyType())) {
                    sb.append(dto.getKeywords()).append(":").append(dto.getContent()).append("\n");
                } else if (ReplyTypeEnum.IMAGE.value.equals(dto.getReplyType())) {
                    SendWeixinRequestTools.sendKeywordMessage(dto, robotId, userWxId, ip, code);
                }
            }
            d.setContent(sb.toString());
            d.setReplyType(ReplyTypeEnum.TEXT.value);
            SendWeixinRequestTools.sendKeywordMessage(d, robotId, userWxId, ip, code);
        }
    }

    @ParamLog("根据关键词判断关键词是否为1V1社群群名称")
    private void inviteToGroupByKeyword(SendTextDTO sendTextDTO, List<JoinGroupCipher> joinGroupCiphers) {
        List<Long> bookGroupIds = joinGroupCiphers.stream().filter(s -> s.getBookGroupId() != null).map(JoinGroupCipher::getBookGroupId).collect(Collectors.toList());
        if (!ListUtils.isEmpty(bookGroupIds)) {
            List<GroupQrcode> groupQrcodes = groupQrcodeDao.getListByBookGroupIds(bookGroupIds);
            if (!ListUtils.isEmpty(groupQrcodes)){
                for (GroupQrcode groupQrcode:groupQrcodes){
                    if (groupQrcode.getGroupName().equals(sendTextDTO.getTextContent())){
                        //发送邀请入群
                        SendGroupInviteVO sendGroupInviteVO = new SendGroupInviteVO();
                        sendGroupInviteVO.setAltId(sendTextDTO.getWxId());
                        sendGroupInviteVO.setWxId(sendTextDTO.getWechatUserId());
                        sendGroupInviteVO.setWxGroupId(groupQrcode.getWeixinGroupId());
                        sendGroupInviteVO.setIp(sendTextDTO.getIp());
                        WxGroupSDK.sendGroupInvite(sendGroupInviteVO);
                        log.info("[同意加好友发送欢迎语] 发送进群链接 sendGroupInviteVO：{}", sendGroupInviteVO);
                    }
                }
            }
        }
    }

    private boolean insertBookKeywordRecord(String weixinGroupId, String userWxId, ReplyKeywordDTO replyKeywordDTO, GroupClassifyQrcodeDTO dto, String redisContent) {
        if (redisContent != null) {
            insertBookKeywordRecord(dto, replyKeywordDTO.getKeywordId(), userWxId, weixinGroupId, false);
            log.info("[关键词消息回复] redisContent:{} insertBookKeywordRecord return", redisContent);
            return true;
        } else {
            // 60s不回复同一关键词 20190916降低消息量方案之一
            JedisClusterUtils.setJson("BOOK:KEYWORD:" + weixinGroupId + "-" + replyKeywordDTO.getKeywordId(), replyKeywordDTO.getKeywordId(), 60);
            insertBookKeywordRecord(dto, replyKeywordDTO.getKeywordId(), userWxId, weixinGroupId, true);
        }
        return false;
    }

    /**
     * 原有的推送群关键词改为推送个人关键词
     */
    @ParamLog("群关键词消息回复")
    private void sendKeywordMessageToGroup(SendTextDTO sendTextDTO) {
        if (Objects.isNull(sendTextDTO)) {
            return;
        }
        final String content = sendTextDTO.getTextContent().trim();
        final String weixinGroupId = sendTextDTO.getWechatGroupId();
        final String userWxId = sendTextDTO.getWechatUserId();
        final String ip = sendTextDTO.getIp();
        final Integer code = sendTextDTO.getCode();
        String robotId = sendTextDTO.getWxId();
        // 若非之前的机器人则不回复普通关键词
        final Boolean groupRobot = wechatGroupConsr.isGroupRobot(robotId);
        log.info("[wechatGroupConsr.isGroupRobot] robotId:{} groupRobot:{}", robotId, groupRobot);
        if (!groupRobot) {
            return;
        }
        //通过群id获取对应基本信息
        GroupClassifyQrcodeDTO classifyQrcodeInfo = bookGroupClassifyBiz.getClassifyQrcodeInfo(weixinGroupId);
        if (classifyQrcodeInfo == null) {
            log.info("[关键词消息回复] classifyQrcodeInfo is null");
            return;
        }
        //简单过滤非关键词的词
        if (StringUtil.isEmpty(content) || content.length() > 20) {
            return;
        }
        ReplyKeywordDTO replyKeywordDTO;
        final boolean equals = "群主，来个抽奖".equals(content);
        if (equals) {
            replyKeywordDTO = keywordDao.getByKeyword("群主，来个抽奖");
        } else {
            //获取匹配关键词
            replyKeywordDTO = bookKeywordDao.getKeywordId(classifyQrcodeInfo.getClassifyId(), classifyQrcodeInfo.getBookGroupId(), content);
        }
        if (replyKeywordDTO == null) {
            log.info("[关键词消息回复] replyKeywordDTO is null");
            return;
        }
        log.info("[关键词回复原始数据] ： sendKeywordMessage replyKeywordDTO ：{}, robotId:{}, weixinGroupId:{}", replyKeywordDTO, robotId, weixinGroupId);
        // 处理链接地址
        final boolean isApp = ReplyTypeEnum.APP.value.equals(replyKeywordDTO.getReplyType());
        final boolean isLink = ReplyTypeEnum.LINK.value.equals(replyKeywordDTO.getReplyType());
        if (isApp || isLink) {
            AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(classifyQrcodeInfo.getChannelId());
            String linkUrl = SendWeixinRequestTools.splitUrlNew(accountSettingDto, replyKeywordDTO.getLinkUrl(), classifyQrcodeInfo.getBookGroupId(), classifyQrcodeInfo.getClassifyId(), classifyQrcodeInfo.getGroupQrcodeId());
            replyKeywordDTO.setLinkUrl(linkUrl);
        }
        String redisContent = JedisClusterUtils.getJson("BOOK:KEYWORD:" + weixinGroupId + "-" + replyKeywordDTO.getKeywordId(), String.class);
        // 同一群10秒内不回复同一关键词，60s不回复同一关键词 20190916降低消息量方案之一
        if (insertBookKeywordRecord(weixinGroupId, userWxId, replyKeywordDTO, classifyQrcodeInfo, redisContent)) {
            return;
        }
        //获取推送消息机器人
        // 20190704改为收发一体
        if (StringUtil.isBlank(robotId)) {
            log.info("[关键词消息回复] robotId is null content:{}, robotId:{},weixinGroupId:{}", content, robotId, weixinGroupId);
            robotId = wechatGroupConsr.getRobotIdByGroupId(weixinGroupId);
        }
        log.info("[关键词回复发送数据] ： sendKeywordMessage replyKeywordDTO ：{}, robotId:{}, weixinGroupId:{}", replyKeywordDTO, robotId, weixinGroupId);
        SendWeixinRequestTools.sendKeywordMessage(replyKeywordDTO, robotId, weixinGroupId, ip, code);
        //新增关键词触发记录
        addKeywordAppTouchRecord(replyKeywordDTO, weixinGroupId, classifyQrcodeInfo.getClassifyId(), classifyQrcodeInfo.getBookGroupId());
        //第一推送关键词消息埋点
        String keywordsKey = "BOOK:FIRSTKEYWORD:" + DateUtils.getShortDateStr() + "-" + weixinGroupId;
        Boolean isSend = JedisClusterUtils.getJson(keywordsKey, Boolean.class);
        if (isSend != null && isSend) {
            return;
        }
        JedisClusterUtils.setJson(keywordsKey, true);
        JedisClusterUtils.expire(keywordsKey, 86400);
        RobotReplyDTO robotReplyDTO = new RobotReplyDTO();
        robotReplyDTO.setKeyWord(content);
        robotReplyDTO.setWxGroupId(weixinGroupId);
        robotReplyDTO.setWxUserId(userWxId);
        wechatGroupConsr.addFirstRobotReplyRecord(robotReplyDTO);
    }

    /**
     * 更新群人数
     */
    @Override
    public void updateGroupPeopleCount(String wxGroupId, Integer memberCount, Integer changeNumber, Long weixinQrcodeId, Long groupQrcodeId) {
        log.info("[更新群人数] updateGroupPeopleCount wxGroupId:{} memberCount:{} changeNumber：{} weixinQrcodeId：{} groupQrcodeId：{}", wxGroupId, memberCount, changeNumber, weixinQrcodeId, groupQrcodeId);
        if (Objects.isNull(memberCount) || StringUtil.isBlank(wxGroupId) || memberCount <= 0) {
            return;
        }
        String key = CacheConstant.BOOK + "groupPeopleCount:";
        String groupPeopleCount = JedisClusterUtils.hget(key, wxGroupId);
        log.info("[更新群人数] updateGroupPeopleCount groupPeopleCount:{}", groupPeopleCount);
        // 如果没有缓存或者有缓存但是人数与缓存不一致，代表有更新，则更新数据库
        final boolean update = StringUtil.isBlank(groupPeopleCount) || StringUtil.isNotBlank(groupPeopleCount) && !groupPeopleCount.equals(memberCount + "");
        if (update) {
            JedisClusterUtils.hset(key, wxGroupId, memberCount + "");
            // 将二维码改为已满群BookKeywordBizImpl
            if (memberCount >= changeNumber) {
                groupQrcodeDao.changeQrcodeState(groupQrcodeId, QrcodeStatusEnum.OVER_NUMBER.value);
                log.info("[更新群人数] 触发更新大于等于状态 wxGroupId:{} memberCount:{} changeNumber：{} weixinQrcodeId：{} groupQrcodeId：{}", wxGroupId, memberCount, changeNumber, weixinQrcodeId, groupQrcodeId);
            } else {
                groupQrcodeDao.changeQrcodeStateForNotOver(groupQrcodeId, QrcodeStatusEnum.ON_USE.value);
                log.info("[更新群人数] 触发更新小于状态 wxGroupId:{} memberCount:{} changeNumber：{} weixinQrcodeId：{} groupQrcodeId：{}", wxGroupId, memberCount, changeNumber, weixinQrcodeId, groupQrcodeId);
            }
            if (memberCount >= 100) {
                groupQrcodeBiz.changeToOverNumber(weixinQrcodeId, groupQrcodeId);
                log.info("[更新群人数] 触发更新满群状态 wxGroupId:{} memberCount:{} changeNumber：{} weixinQrcodeId：{} groupQrcodeId：{}", wxGroupId, memberCount, changeNumber, weixinQrcodeId, groupQrcodeId);
                groupQrcodeDao.changeQrcodeState(groupQrcodeId, QrcodeStatusEnum.OVER_NUMBER.value);
            } else {
                groupQrcodeBiz.changeToNotOverNumber(weixinQrcodeId, groupQrcodeId);
                log.info("[更新群人数] 触发更新未满群状态 wxGroupId:{} memberCount:{} changeNumber：{} weixinQrcodeId：{} groupQrcodeId：{}", wxGroupId, memberCount, changeNumber, weixinQrcodeId, groupQrcodeId);
            }
            groupQrcodeBiz.updateGroupCount(wxGroupId, memberCount);
            log.info("[成功更新群人数] updateGroupPeopleCount wxGroupId:{} memberCount:{}", wxGroupId, memberCount);
        }
    }

    /**
     * 修改群名称
     */
    @Override
    public void checkGroupName(String weixinGroupId, String groupName, String robotId, String ip) {
        log.info("[checkGroupName] weixinGroupId:{} groupName:{} robotId:{} ip:{} groupQrcodeDTO:{}", weixinGroupId, groupQrcodeDao, robotId, ip);
        if (StringUtil.isBlank(weixinGroupId) || StringUtil.isBlank(groupName) || StringUtil.isBlank(robotId) || StringUtil.isBlank(ip)) {
            return;
        }
        String key = CacheConstant.BOOK + "CHECKGROUPNAME:";
        String s = JedisClusterUtils.hget(key, weixinGroupId);
        log.info("[修改群名称] checkGroupName s:{}", s);
        if (StringUtil.isBlank(s)) {
            ChangeNameVO vo = new ChangeNameVO();
            vo.setName(groupName);
            vo.setAltId(robotId);
            vo.setWxGroupId(weixinGroupId);
            vo.setIp(ip);
            WxGroupSDK.changeGroupName(vo);
            // 改过名之后七天不再改名
            JedisClusterUtils.hset(key, weixinGroupId, "1");
            JedisClusterUtils.expire(key, 60 * 60 * 24 * 31);
            log.info("[修改群名称] checkGroupName vo:{}", vo);
        }
    }

    /**
     * 关键词应用触发记录
     */
    private void addKeywordAppTouchRecord(ReplyKeywordDTO replyKeywordDTO, String weixinGroupId, Long classifyId, Long bookGroupId) {
        if (ReplyTypeEnum.APP.value.equals(replyKeywordDTO.getReplyType())) {
            Keyword keyword = keywordDao.getById(replyKeywordDTO.getKeywordId());
            if (keyword != null) {
                AppTouchRecord appTouchRecord = new AppTouchRecord();
                appTouchRecord.setServeId(keyword.getServeId());
                appTouchRecord.setServeType(keyword.getServeType());
                appTouchRecord.setTouchType(TouchTypeEnum.KEYWORD.value);
                appTouchRecord.setBookGroupId(bookGroupId);
                appTouchRecord.setClassifyId(classifyId);
                GroupQrcode groupQrcode = groupQrcodeDao.getGroupQrcodeByGroupId(weixinGroupId);
                if (groupQrcode != null) {
                    appTouchRecord.setQrcodeId(groupQrcode.getId());
                }
                appTouchRecord.setWeixinGroupId(weixinGroupId);
                appTouchRecordDao.insert(appTouchRecord);
            }
        }
    }

    private void insertBookKeywordRecord(GroupClassifyQrcodeDTO classifyQrcodeInfo, Long keywordId, String userWxId, String weixinGroupId, Boolean isSend) {
        BookKeywordRecord bookKeywordRecord = new BookKeywordRecord();
        BeanUtils.copyProperties(classifyQrcodeInfo, bookKeywordRecord);
        bookKeywordRecord.setKeywordId(keywordId);
        bookKeywordRecord.setUserWxId(userWxId);
        bookKeywordRecord.setWeixinGroupId(weixinGroupId);
        bookKeywordRecord.setSend(isSend);
        if (bookKeywordRecord.getGroupQrcodeId() == null) {
            GroupQrcode groupQr = groupQrcodeDao.getGroupQrcodeByGroupId(weixinGroupId);
            if (groupQr != null) {
                bookKeywordRecord.setGroupQrcodeId(groupQr.getId());
            }
        }
        bookKeywordRecordDao.insert(bookKeywordRecord);
    }

    @Override
    public PageBeanNew<KeywordStatisticsDTO> getKeywordStatistics(Integer currentPage, Integer numPerPage, Long bookGroupId, String weixinGroupId) {
        PageParam pageParam = new PageParam(currentPage, numPerPage);
        Map<String, Object> map = new HashMap<>();
        map.put("bookGroupId", bookGroupId);
        if (!StringUtil.isEmpty(weixinGroupId)) {
            GroupQrcode groupQrcode = groupQrcodeDao.getGroupQrcodeByGroupId(weixinGroupId);
            if (groupQrcode != null) {
                map.put("classifyId", groupQrcode.getClassifyId());
            }
        }
        //分页获取关键词，创建时间，名称信息
        PageBeanNew<KeywordStatisticsDTO> pageBeanNew = bookKeywordDao.listPageNew(pageParam, map, "getKeywordInfoByBookGroupId");
        List<KeywordStatisticsDTO> keywordStatisticsDTOS = pageBeanNew.getRecordList();
        if (ListUtils.isEmpty(keywordStatisticsDTOS)) {
            return pageBeanNew;
        }
        List<Long> keywordIds = keywordStatisticsDTOS.stream().filter(s -> s.getKeywordId() != null).map(KeywordStatisticsDTO::getKeywordId).collect(Collectors.toList());
        //获取关键词累计触发次数，最近一次触发时间
        List<KeywordStatisticsDTO> keywordStatisticsDTOSForOther = bookKeywordRecordDao.getKeywordStatistics(bookGroupId, weixinGroupId, keywordIds);
        Map<Long, KeywordStatisticsDTO> otherMap = new HashMap<>();
        if (!ListUtils.isEmpty(keywordStatisticsDTOSForOther)) {
            for (KeywordStatisticsDTO in : keywordStatisticsDTOSForOther) {
                otherMap.put(in.getKeywordId(), in);
            }
        }
        //获取最近7天的触发次数
        Date startDate = DateUtils.addDay(new Date(), -7);
        List<KeywordStatisticsDTO> keywordStatisticsDTOSForTime = bookKeywordRecordDao.getKeywordStatisticsByTime(bookGroupId, weixinGroupId, keywordIds, startDate);
        Map<Long, Integer> weekTouchCountMap = new HashMap<>();
        if (!ListUtils.isEmpty(keywordStatisticsDTOSForOther)) {
            for (KeywordStatisticsDTO in : keywordStatisticsDTOSForTime) {
                weekTouchCountMap.put(in.getKeywordId(), in.getWeekTouchCount());
            }
        }
        for (KeywordStatisticsDTO keywordStatisticsDTO : keywordStatisticsDTOS) {
            Long keywordId = keywordStatisticsDTO.getKeywordId();
            KeywordStatisticsDTO other = otherMap.get(keywordId);
            if (other == null) {
                //如果记录表里面没有就填充0
                keywordStatisticsDTO.setTouchCount(0);
                keywordStatisticsDTO.setWeekTouchCount(0);
                keywordStatisticsDTO.setAvgDayTouchCount(0D);
            } else {
                //计算，填充
                keywordStatisticsDTO.setTouchCount(other.getTouchCount());
                keywordStatisticsDTO.setLastTouchTime(other.getLastTouchTime());
                keywordStatisticsDTO.setWeekTouchCount(weekTouchCountMap.get(keywordId));
                Date createDate = keywordStatisticsDTO.getKeywordCreateDate();
                int days = (int) (DateUtils.getDayEnd(new Date()).getTime() - DateUtils.getDayEnd(createDate).getTime()) / 1000 / 60 / 60 / 24;
                if (days <= 0) {
                    days = 1;
                }
                Double avgTouchCount = (double) keywordStatisticsDTO.getTouchCount() / (double) days;
                keywordStatisticsDTO.setAvgDayTouchCount(new BigDecimal(avgTouchCount).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
            }
        }
        return pageBeanNew;
    }

    @Override
    public Integer getKeywordCount(Long bookGroupId, Long classifyId) {
        if (bookGroupId == null) {
            throw new BookBizException(BookBizException.ERROR, "缺少参数bookGroupId");
        }
        return bookKeywordDao.getKeywordCount(bookGroupId, classifyId);
    }


    @Override
    public List<ServiceResourceDTO> getServiceByWeixinGroup(QrWeixinParam qrWeixinParam, Long classifyId, Long qrcodeId) {
        Map<String, Object> map = new HashMap<>();
        map.put("bookGroupId", qrWeixinParam.getBookGroupId());
        List<ServiceResourceDTO> serviceResourceDTOS = ResponesUtils.list(bookKeywordDao.listBy(map, "getServiceByWeixinGroup"), ServiceResourceDTO.class);
        if (ListUtils.isEmpty(serviceResourceDTOS)) {
            return new ArrayList<>();
        }
        for (ServiceResourceDTO serviceResourceDTO : serviceResourceDTOS) {
            AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(serviceResourceDTO.getChannelId());
            String linkUrl = SendWeixinRequestTools.splitUrlNew(accountSettingDto, serviceResourceDTO.getUrl(), qrWeixinParam.getBookGroupId(), classifyId, qrcodeId);
            serviceResourceDTO.setUrl(linkUrl);
        }
        List<Long> appIds = serviceResourceDTOS.stream().filter(s -> ("APP").equals(s.getTypeCode())).map(ServiceResourceDTO::getFromId).collect(Collectors.toList());
        Map<Long, AppDto> appMap = appConsr.getBaseByIds(appIds);
        if (!MapUtils.isEmpty(appMap)) {
            for (ServiceResourceDTO serviceResourceDTO : serviceResourceDTOS) {
                AppDto appDto = appMap.get(serviceResourceDTO.getFromId());
                if (appDto != null && serviceResourceDTO.getTypeCode().equals("APP")) {
                    serviceResourceDTO.setFromType(appDto.getTypeCode());
                    serviceResourceDTO.setTitle(appDto.getTitle());
                    serviceResourceDTO.setShortName(appDto.getTypeName());
                }
            }
        }
        List<Long> productIds = serviceResourceDTOS.stream().filter(s -> ("PRODUCT").equals(s.getTypeCode())).map(ServiceResourceDTO::getFromId).collect(Collectors.toList());
        Map<Long, ProductDto> productMap = productConsr.getProBasesByIds(productIds);
        if (!MapUtils.isEmpty(productMap)) {
            for (ServiceResourceDTO serviceResourceDTO : serviceResourceDTOS) {
                ProductDto productDto = productMap.get(serviceResourceDTO.getFromId());
                if (productDto != null && serviceResourceDTO.getTypeCode().equals("PRODUCT")) {
                    ProductTypeDto productTypeDto = productDto.getProductTypeDto();
                    if (productTypeDto != null) {
                        serviceResourceDTO.setFromType(productTypeDto.getTypeCode());
                        serviceResourceDTO.setTitle(productDto.getProductName());
                        serviceResourceDTO.setShortName(productTypeDto.getTypeName());
                    }
                }
            }
        }
        if (serviceResourceDTOS != null && !StringUtil.isEmpty(qrWeixinParam.getTypeCode()) && qrWeixinParam.getServeId() != null) {
            serviceResourceDTOS.removeIf(vo -> (qrWeixinParam.getTypeCode().equals(vo.getTypeCode()) && qrWeixinParam.getServeId().equals(vo.getFromId())));
        }
        List<ServiceResourceDTO> uniqueResources = serviceResourceDTOS.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getFromId() + ";" + o.getTypeCode()))), ArrayList::new)
        );
        return uniqueResources;
    }

    @Override
    public List<ServiceResourceDTO> getServiceByChannel(QrWeixinParam qrWeixinParam, Long wechatUserId) {
        QrWeixinParamVO qrWeixinParamVO = new QrWeixinParamVO();
        BeanUtils.copyProperties(qrWeixinParam, qrWeixinParamVO);
        List<MessageBookVO> messageBookVOS = ResponseHandleUtil.parseListResponse(qrcodeSceneService.getQrMessage4Book(qrWeixinParamVO, wechatUserId), MessageBookVO.class);
        return ResponesUtils.list(messageBookVOS, ServiceResourceDTO.class);
    }

    @ParamLog("根据社群码id获取关键词列表")
    @Override
    public List<KeywordDTO> getListByBookGroupId(Long bookGroupId) {
        return bookKeywordDao.getListByBookGroupId(bookGroupId);
    }

    @Override
    public ReplyKeywordDTO getReplyKeyword(String content, String weixinGroupId, String wexinGroupName) {
        ReplyKeywordDTO replyKeywordDTO = null;
        if (StringUtil.isEmpty(weixinGroupId) && StringUtil.isEmpty(wexinGroupName)) {
            return new ReplyKeywordDTO();
        }
        GroupClassifyQrcodeDTO classifyQrcodeInfo = null;
        if (!StringUtil.isEmpty(weixinGroupId)) {
            //通过群id获取对应基本信息
            classifyQrcodeInfo = bookGroupClassifyBiz.getClassifyQrcodeInfo(weixinGroupId);
        }
        if (classifyQrcodeInfo == null && !StringUtil.isEmpty(wexinGroupName)) {
            classifyQrcodeInfo = bookGroupClassifyDao.getClassifyQrcodeInfoByName((wexinGroupName));
        }
        if (classifyQrcodeInfo == null) {
            log.info("[关键词消息回复] classifyQrcodeInfo is null");
            return new ReplyKeywordDTO();
        }
        final boolean equals = "群主，来个抽奖".equals(content);
        if (equals) {
            replyKeywordDTO = keywordDao.getByKeyword("群主，来个抽奖");
        } else {
            //获取匹配关键词
            replyKeywordDTO = bookKeywordDao.getKeywordId(classifyQrcodeInfo.getClassifyId(), classifyQrcodeInfo.getBookGroupId(), content);
        }
        if (replyKeywordDTO == null) {
            return new ReplyKeywordDTO();
        }
        // 处理链接地址
        if (ReplyTypeEnum.APP.value.equals(replyKeywordDTO.getReplyType()) || ReplyTypeEnum.LINK.value.equals(replyKeywordDTO.getReplyType())) {
            AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(classifyQrcodeInfo.getChannelId());
            String linkUrl = SendWeixinRequestTools.splitUrlNew(accountSettingDto, replyKeywordDTO.getLinkUrl(), classifyQrcodeInfo.getBookGroupId(), classifyQrcodeInfo.getClassifyId(), classifyQrcodeInfo.getGroupQrcodeId());
            replyKeywordDTO.setLinkUrl(linkUrl);
            if (!StringUtil.isEmpty(linkUrl)) {
                replyKeywordDTO.setShortLinkUrl(UrlUtils.getShortUrl4Own(linkUrl));
            }
        }
        return replyKeywordDTO;
    }

}
