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.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.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.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.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.sdk.wxgroup.SendMessageTypeEnum;

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.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;

    @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);
        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个了）")
    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(String content, String weixinGroupId, String userWxId, String robotId, String ip, Integer code) {
        // 刘娜需求 1001282 群不推送关键词
        if (SendMessageTypeEnum.GROUP.getCode().equals(code)) {
            this.sendKeywordMessageToGroup(content, weixinGroupId, userWxId, robotId, ip, code);
            return;
        }
        //个人机器人接收消息的时候，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);
        }
    }

    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 {
            JedisClusterUtils.setJson("BOOK:KEYWORD:" + weixinGroupId + "-" + replyKeywordDTO.getKeywordId(), replyKeywordDTO.getKeywordId(), 10);
            insertBookKeywordRecord(dto, replyKeywordDTO.getKeywordId(), userWxId, weixinGroupId, true);
        }
        return false;
    }

    /**
     * 原有的推送群关键词改为推送个人关键词
     */
    @ParamLog("群关键词消息回复")
    private void sendKeywordMessageToGroup(String content, String weixinGroupId, String userWxId, String robotId, String ip, Integer code) {
        //简单过滤非关键词的词
        if (StringUtil.isEmpty(content) || content.length() > 20) {
            return;
        }
        // 若非之前的机器人则不回复普通关键词
        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;
        }
        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秒内不回复同一关键词
        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);
    }

    /**
     * 关键词应用触发记录
     */
    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);
    }

    @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;
    }

}
