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

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

import com.alibaba.fastjson.JSONObject;
import com.pcloud.analysisengine.browse.dto.GroupBrowseStatisticVO;
import com.pcloud.appcenter.app.dto.AppDto;
import com.pcloud.appcenter.base.dto.AppPriceCacheDTO;
import com.pcloud.appcenter.cache.service.AppPriceCacheService;
import com.pcloud.audioapp.audioLesson.service.AudioLessonService;
import com.pcloud.book.applet.biz.AppletUserBookcaseBiz;
import com.pcloud.book.applet.entity.AppletUserBookcase;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.biz.BookBiz;
import com.pcloud.book.book.dao.BookAdviserDao;
import com.pcloud.book.book.dao.BookDao;
import com.pcloud.book.book.dao.BookLabelDao;
import com.pcloud.book.book.dao.BookRaysClassifyDao;
import com.pcloud.book.book.dto.BookAdviserDto;
import com.pcloud.book.book.dto.BookDto;
import com.pcloud.book.book.entity.Book;
import com.pcloud.book.book.entity.BookLabel;
import com.pcloud.book.book.set.BookSet;
import com.pcloud.book.consumer.analysisengine.BrowseRecordConsr;
import com.pcloud.book.consumer.app.AppConsr;
import com.pcloud.book.consumer.channel.QrcodeSceneConsr;
import com.pcloud.book.consumer.common.ExportConsr;
import com.pcloud.book.consumer.content.ResourceConsr;
import com.pcloud.book.consumer.message.MessageConsr;
import com.pcloud.book.consumer.raystask.MainLineConsr;
import com.pcloud.book.consumer.resource.ProductConsr;
import com.pcloud.book.consumer.settlement.BookConsr;
import com.pcloud.book.consumer.settlement.SettlementConsr;
import com.pcloud.book.consumer.trade.TradeConsr;
import com.pcloud.book.consumer.user.AdviserConsr;
import com.pcloud.book.consumer.user.AgentConsr;
import com.pcloud.book.consumer.wechat.WechatConsr;
import com.pcloud.book.consumer.wechatgroup.WechatGroupConsr;
import com.pcloud.book.group.biz.BookGroupAppBiz;
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.*;
import com.pcloud.book.group.dto.*;
import com.pcloud.book.group.entity.*;
import com.pcloud.book.group.enums.AppAndProductTypeEnum;
import com.pcloud.book.group.enums.ChangeOriginTypeEnum;
import com.pcloud.book.group.enums.CipherTypeEnum;
import com.pcloud.book.group.enums.JoinGroupTypeEnum;
import com.pcloud.book.group.enums.LargeTempletEnum;
import com.pcloud.book.group.set.GroupSet;
import com.pcloud.book.group.tools.SendWeixinRequestTools;
import com.pcloud.book.group.vo.BookGroupAnalysisParam;
import com.pcloud.book.group.vo.BookGroupAnalysisVO;
import com.pcloud.book.group.vo.ClassifyAndGroupCountVO;
import com.pcloud.book.group.vo.ClassifyQrcodeVO;
import com.pcloud.book.group.vo.FriendsVO;
import com.pcloud.book.group.vo.GroupIncomeStaticParamVO;
import com.pcloud.book.group.vo.GroupScanTrendParamVO;
import com.pcloud.book.group.vo.GroupScanTrendVO;
import com.pcloud.book.group.vo.GroupStatisticVO;
import com.pcloud.book.group.vo.ListBook4ChannelVO;
import com.pcloud.book.group.vo.ListBookGroup4ChannelParamVO;
import com.pcloud.book.group.vo.ResourceClickVO;
import com.pcloud.book.group.vo.ResourcesStatisticVO;
import com.pcloud.book.group.vo.StatisticVO;
import com.pcloud.book.group.vo.TotalRescourceDataVO;
import com.pcloud.book.group.vo.UserBookInfoItemVO;
import com.pcloud.book.group.vo.UserBookInfoVO;
import com.pcloud.book.group.vo.WxGroupStatisticVO;
import com.pcloud.book.keywords.biz.BookKeywordBiz;
import com.pcloud.book.keywords.biz.SelfRobotKeywordBiz;
import com.pcloud.book.keywords.dao.BookKeywordDao;
import com.pcloud.book.keywords.dto.KeywordDTO;
import com.pcloud.book.keywords.enums.ReplyTypeEnum;
import com.pcloud.book.keywords.vo.ListKeywordVO;
import com.pcloud.book.pcloudkeyword.biz.PcloudRobotBiz;
import com.pcloud.book.pcloudkeyword.entity.PcloudRobot;
import com.pcloud.book.push.enums.AltTypeEnum;
import com.pcloud.book.reading.dao.ReadingUserDao;
import com.pcloud.book.rightsSetting.biz.RightsSettingBiz;
import com.pcloud.book.rightsSetting.dto.RightsSettingDto;
import com.pcloud.book.util.common.ThreadPoolUtils;
import com.pcloud.channelcenter.base.constants.ChannelConstants;
import com.pcloud.channelcenter.qrcode.dto.GroupQrcodeVO;
import com.pcloud.channelcenter.qrcode.dto.QrcodeSceneDto;
import com.pcloud.channelcenter.wechat.dto.AccountSettingDto;
import com.pcloud.channelcenter.wechat.dto.MessageDto;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.core.constant.ProductTypeConstant;
import com.pcloud.common.core.constant.SystemCode;
import com.pcloud.common.core.enums.NotifyOriginTypeEnum;
import com.pcloud.common.dto.ResponseDto;
import com.pcloud.common.dto.StoreFlowInfoDto;
import com.pcloud.common.entity.UploadResultInfo;
import com.pcloud.common.enums.AppTypeEnum;
import com.pcloud.common.exceptions.BizException;
import com.pcloud.common.page.PageBean;
import com.pcloud.common.page.PageBeanNew;
import com.pcloud.common.page.PageParam;
import com.pcloud.common.utils.BeanUtils;
import com.pcloud.common.utils.DateUtils;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.QrcodeUtils;
import com.pcloud.common.utils.ResponseHandleUtil;
import com.pcloud.common.utils.UUIDUitl;
import com.pcloud.common.utils.export.excel.ExcelExportor;
import com.pcloud.common.utils.httpclient.UrlUtils;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.common.utils.zip.CompressUtils;
import com.pcloud.contentcenter.resource.dto.ResourceDTO;
import com.pcloud.facade.tradecenter.dto.ClassifyPayDetailDto;
import com.pcloud.facade.tradecenter.dto.GroupIncomeSearchDto;
import com.pcloud.facade.tradecenter.dto.GroupMoneyDto;
import com.pcloud.facade.tradecenter.dto.ProductSaleDetailDto;
import com.pcloud.facade.tradecenter.dto.SpeWechatGroupDto;
import com.pcloud.facade.tradecenter.dto.WechatGroupDto;
import com.pcloud.labelcenter.label.service.LabelService;
import com.pcloud.liveapp.live.dto.ProductIdSearchDto;
import com.pcloud.liveapp.live.service.TimeTableService;
import com.pcloud.resourcecenter.product.dto.AddAppProductParamDTO;
import com.pcloud.resourcecenter.product.dto.ProductDto;
import com.pcloud.resourcecenter.product.dto.ProductTypeDto;
import com.pcloud.resourcecenter.product.dto.SpecificationDto;
import com.pcloud.resourcecenter.product.dto.UpdateAppProductParamDTO;
import com.pcloud.resourcecenter.product.entity.Product;
import com.pcloud.resourcecenter.product.service.ProductService;
import com.pcloud.resourcecenter.store.constants.StoreCons;
import com.pcloud.settlementcenter.record.dto.GetGroupClassifyIncomeDTO;
import com.pcloud.settlementcenter.record.dto.GetGroupQrcodeIncomeDTO;
import com.pcloud.settlementcenter.record.dto.GroupRescourceIncomeParamDTO;
import com.pcloud.settlementcenter.record.dto.ProductStaticUnderAppMapDTO;
import com.pcloud.settlementcenter.record.service.SettlementService;
import com.pcloud.usercenter.party.adviser.dto.AdviserBaseInfoDto;
import com.pcloud.videolesson.schedule.service.ScheduleService;
import com.pcloud.wechatgroup.base.exception.WechatGroupBizException;
import com.pcloud.wechatgroup.group.dto.GroupMemberStatisDTO;
import com.pcloud.wechatgroup.group.dto.GroupRobotDTO;
import com.pcloud.wechatgroup.group.dto.GroupUserCountDTO;
import com.pcloud.wechatgroup.group.service.GroupMemberService;
import com.pcloud.wechatgroup.message.dto.GroupMsgCountDTO;
import com.pcloud.wechatgroup.message.dto.SendTextDTO;
import com.pcloud.wechatgroup.message.dto.UserChatCountDTO;
import com.pcloud.wechatgroup.selfrobot.dto.AltAndUserDTO;
import com.pcloud.wechatgroup.selfrobot.dto.AltAndUserResultDTO;
import com.pcloud.wechatgroup.selfrobot.dto.AvailableRobotParamDTO;
import com.pcloud.wechatgroup.selfrobot.dto.RobotBaseInfoDTO;
import com.pcloud.wechatgroup.selfrobot.dto.SelfRobotDTO;
import com.pcloud.wechatgroup.selfrobot.dto.UserRobotDTO;
import com.pcloud.wechatgroup.selfrobot.enums.SelfRobotTypeEnum;
import com.sdk.wxgroup.SendMessageTypeEnum;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
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.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Description 社群书群二维码业务逻辑层接口实现类
 * Created by PENG on 2019/4/17.
 */
@Component("bookGroupBiz")
public class BookGroupBizImpl implements BookGroupBiz {
    private static final Logger LOGGER = LoggerFactory.getLogger(BookGroupBizImpl.class);

    private final static String DEFAULT_PRODUCT_COVER_IMG = "https://oss.5rs.me/oss/uploadfe/png/1c5da08d2c9598a5f0b0252acb84d8b8.png";

    @Value("${book.group.qrcode.domain}")
    private String bookGroupQrcodeDomain;

    @Autowired
    private BookGroupDao bookGroupDao;
    @Autowired
    private LabelService labelService;
    @Autowired
    private ProductService productService;
    @Autowired
    private AdviserConsr adviserConsr;
    @Autowired
    private BookBiz bookBiz;
    @Autowired
    private BookSet bookSet;
    @Autowired
    private BookDao bookDao;
    @Autowired
    private SettlementService settlementService;
    @Autowired
    private BookGroupClassifyBiz bookGroupClassifyBiz;
    @Autowired
    private GroupMemberService groupMemberService;
    @Autowired
    private QrcodeSceneConsr qrcodeSceneConsr;
    @Autowired
    private AppTouchRecordDao appTouchRecordDao;
    @Autowired
    private AppClickRecordDao appClickRecordDao;
    @Autowired
    private SettlementConsr settlementConsr;
    @Autowired
    private TradeConsr tradeConsr;
    @Autowired
    private AppConsr appConsr;
    @Autowired
    private ProductConsr productConsr;
    @Autowired
    private MainLineConsr mainLineConsr;
    @Autowired
    private BookGroupClassifyDao bookGroupClassifyDao;
    @Autowired
    private BookKeywordDao bookKeywordDao;
    @Autowired
    private AudioLessonService audioLessonService;
    @Autowired
    private ScheduleService scheduleService;
    @Autowired
    private TimeTableService timeTableService;
    @Autowired
    private AppPriceCacheService appPriceCacheService;
    @Autowired
    private TempletRelevanceDao templetRelevanceDao;
    @Autowired
    private JoinGroupCipherDao joinGroupCipherDao;
    @Autowired
    private WechatGroupConsr wechatGroupConsr;
    @Autowired
    private WeixinQrcodeDao weixinQrcodeDao;
    @Autowired
    private BookConsr bookConsr;
    @Autowired
    private GroupQrcodeBiz groupQrcodeBiz;
    @Autowired
    private BookGroupServeDao bookGroupServeDao;
    @Autowired
    private GroupQrcodeDao groupQrcodeDao;
    @Autowired
    private BookGroupCipherUserDao bookGroupCipherUserDao;
    @Autowired
    private GroupSet groupSet;
    @Autowired
    private MessageConsr messageConsr;
    @Autowired
    private PushBookGroupUpdateDao pushBookGroupUpdateDao;
    @Autowired
    private BookKeywordBiz bookKeywordBiz;
    @Autowired
    private WeixinQrcodeGenerationDao weixinQrcodeGenerationDao;
    @Autowired
    private AgentConsr agentConsr;
    @Autowired
    private BookGroupAppBiz bookGroupAppBiz;
    @Autowired
    private BookGroupAgentRecordDao bookGroupAgentRecordDao;
    @Autowired
    private BookGroupAppDao bookGroupAppDao;
    @Autowired
    private CopyCipherRecordDao copyCipherRecordDao;
    @Autowired
    private BrowseRecordConsr browseRecordConsr;
    @Autowired
    private ExportConsr exportConsr;
    @Autowired
    private WxUserWechatRelevanceDao wxUserWechatRelevanceDao;
    @Autowired
    private WxWechatUserCorrelationDao wxWechatUserCorrelationDao;
    @Autowired
    private BookLabelDao bookLabelDao;
    @Autowired
    private BookGroupFriendGuideDao bookGroupFriendGuideDao;
    @Autowired
    private ResourceConsr resourceConsr;
    @Autowired
    private ReadingUserDao readingUserDao;
    @Autowired
    private SelfRobotKeywordBiz selfRobotKeywordBiz;
    @Autowired
    private PcloudRobotBiz pcloudRobotBiz;
    @Autowired
    private BookAdviserDao bookAdviserDao;
    @Autowired
    private BookRaysClassifyDao bookRaysClassifyDao;
    @Autowired
    private WechatConsr wechatConsr;
    @Autowired
    private BookAppletSceneDao bookAppletSceneDao;
    @Autowired
    private RightsSettingBiz rightsSettingBiz;
    @Autowired
    private AppletUserBookcaseBiz appletUserBookcaseBiz;

    private static final ThreadPoolExecutor PLATFORM_STATISTICS_EXPORT_THREAD = new ThreadPoolExecutor(2, 2,
            0, TimeUnit.SECONDS, new LinkedBlockingQueue<>(),
            new BasicThreadFactory.Builder().namingPattern("platform_statistics_export_thread-%d").build());

    @Override
    public BookGroupDTO getDTOByBookId(Long bookId, Long channelId, Long adviserId) {
        return bookGroupDao.getDTOByBookId(bookId, channelId, adviserId);
    }

    /**
     * 创建社群书时生成群二维码
     */
    @Override
    @ParamLog("创建社群书时生成群二维码")
    @Transactional(rollbackFor = Exception.class)
    public BookGroup createBookGroupAfterCreateBook(Long bookId, Long channelId, Long adviserId, Integer addType, Long sceneId, Integer joinGroupType) throws BizException {
        BookGroup bookGroup = new BookGroup();
        bookGroup.setBookId(bookId);
        bookGroup.setChannelId(channelId);
        bookGroup.setCreateUser(adviserId);
        //填充出版社id
        Long agentId = adviserConsr.getAgentIdByAdviser(bookGroup.getCreateUser());
        bookGroup.setAgentId(agentId);
        Boolean isShowBookName = bookGroupDao.getIsShowBookName(adviserId);
        if (isShowBookName != null) {
            bookGroup.setIsShowBookName(isShowBookName);
        }
        if (JoinGroupTypeEnum.ROBOT.getCode().equals(joinGroupType)){
            bookGroup.setBookGroupCipher(getBookGroupCipher());
        }
        if (addType != null && addType == 1) {
            GroupQrcodeVO groupQrcodeVO;
            if (sceneId != null) {
                //将图书下某个二维码替换成社群码
                groupQrcodeVO = qrcodeSceneConsr.setQrcodeToGroup(sceneId);
            } else {
                //创建公众号二维码
                groupQrcodeVO = qrcodeSceneConsr.createWxGroupQrcode(bookId, channelId, adviserId);
            }
            if (groupQrcodeVO == null) {
                throw new BookBizException(BookBizException.ERROR, "二维码生成失败！");
            }
            bookGroup.setGroupQrcodeUrl(groupQrcodeVO.getQrcodeUrl());
            bookGroup.setSceneId(groupQrcodeVO.getSceneId());
            bookGroupDao.insert(bookGroup);
            if (joinGroupType != null) {
                bookGroupDao.updateJoinGroupType(bookGroup.getId(), joinGroupType);
            }
        } else {
            bookGroupDao.insert(bookGroup);
            String groupQrcodeUrl = QrcodeUtils.createWithMargin(bookGroupQrcodeDomain + "/" + bookGroup.getId(), 1);
            BookGroup group = new BookGroup();
            group.setId(bookGroup.getId());
            group.setGroupQrcodeUrl(groupQrcodeUrl);
            if (joinGroupType != null) {
                group.setJoinGroupType(joinGroupType);
            }
            bookGroupDao.update(group);
            bookGroup.setGroupQrcodeUrl(groupQrcodeUrl);
        }
        if (null != bookId && !bookId.equals(0L)) {
            mainLineConsr.sendAddBookGroupTask(bookId, adviserId);
        }
        //小睿机器人生成小程序码
        if (JoinGroupTypeEnum.XIAORUI.getCode().equals(joinGroupType)){
            this.createBookGroupAppletUrl(bookGroup.getId(),bookId,channelId,adviserId);
        }
        return bookGroup;
    }

    /**
     * 获取社群书群二维码信息
     */
    @Override
    public BookGroupDTO getBookGroupInfo(Long bookGroupId) throws BizException {
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
        if (null == bookGroupDTO) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "群二维码不存在！");
        }
        List<Long> labelIds = new ArrayList<>();
        if (null != bookGroupDTO.getProLabelId()) {
            labelIds.add(bookGroupDTO.getProLabelId());
        }
        if (null != bookGroupDTO.getDepLabelId()) {
            labelIds.add(bookGroupDTO.getDepLabelId());
        }
        if (null != bookGroupDTO.getPurLabelId()) {
            labelIds.add(bookGroupDTO.getPurLabelId());
        }
        if (!ListUtils.isEmpty(labelIds)) {
            Map<Long, String> labelMap = ResponseHandleUtil.parseMap(labelService.getLabelName(labelIds), Long.class, String.class);
            if (!MapUtils.isEmpty(labelMap)) {
                if (null != bookGroupDTO.getProLabelId() && labelMap.containsKey(bookGroupDTO.getProLabelId())) {
                    bookGroupDTO.setProLabelName(labelMap.get(bookGroupDTO.getProLabelId()));
                }
                if (null != bookGroupDTO.getDepLabelId() && labelMap.containsKey(bookGroupDTO.getDepLabelId())) {
                    bookGroupDTO.setDepLabelName(labelMap.get(bookGroupDTO.getDepLabelId()));
                }
                if (null != bookGroupDTO.getPurLabelId() && labelMap.containsKey(bookGroupDTO.getPurLabelId())) {
                    bookGroupDTO.setPurLabelName(labelMap.get(bookGroupDTO.getPurLabelId()));
                }
            }
        }
        BookDto bookDto = bookBiz.getBaseById(bookGroupDTO.getBookId());
        if (null != bookDto) {
            bookDto.setBookName(null != bookDto.getBookName() ? StringUtil.addBracket(bookDto.getBookName()) : null);
            bookGroupDTO.setBookInfo(bookDto);
        }
        return bookGroupDTO;
    }

    public BookGroupDTO getBookInfo(Long bookGroupId) throws BizException{
        BookGroupDTO bookGroupDTO = bookGroupDao.getBookInfo(bookGroupId);
        return bookGroupDTO;
    }

    @Override
    public Map<Long, BookGroupDTO> getBookGroupInfoByIds(List<Long> bookGroupIds) throws BizException {
        if (ListUtils.isEmpty(bookGroupIds)) {
            return null;
        }
        List<BookGroupDTO> list = bookGroupDao.getDTOByIds(bookGroupIds);
        List<Long> bookIds = list.stream().map(BookGroupDTO::getBookId).collect(Collectors.toList());
        Map<Long, BookDto> mapByIds = bookDao.getMapByIds(bookIds);
        if (ListUtils.isEmpty(list)) {
            return null;
        }
        list.forEach(e ->{
            if (!MapUtils.isEmpty(mapByIds) && mapByIds.get(e.getBookId()) != null){
                e.setBookName(mapByIds.get(e.getBookId()).getBookName());
                e.setIsbn(mapByIds.get(e.getBookId()).getIsbn());
                e.setBookNumber("BK" + e.getBookId());
            }
        });
        return list.stream().collect(Collectors.toMap(BookGroupDTO::getId, dto -> dto));
    }

    @Override
    public List<BookGroupDTO> getBookGroupInfoByBookIdAndAdviserId(List<Long> bookIds, List<Long> adviserIds){
        if(ListUtils.isEmpty(bookIds) || ListUtils.isEmpty(adviserIds)) {
            return null;
        }

        return bookGroupDao.getDTOByBookIdsAnsAdviserIds(bookIds,adviserIds);
    }

    /**
     * 获取社群书群二维码信息
     */
    @Override
    public BookGroupDTO getBookGroupInfo4Wechat(Long bookGroupId) throws BizException {
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
        if (bookGroupDTO != null) {
            Long adviserId = bookGroupDTO.getCreateUser();
            if (adviserId!=null){
                Map<Long, AdviserBaseInfoDto> adviserInfoDtoMap = adviserConsr.getAdviserId2AdviserInfoDtoMap(Arrays.asList(adviserId));
                if (adviserInfoDtoMap != null) {
                    AdviserBaseInfoDto adviserBaseInfoDto = adviserInfoDtoMap.get(adviserId);
                    if (adviserBaseInfoDto != null) {
                        bookGroupDTO.setAgentId(adviserBaseInfoDto.getAgentId());
                        bookGroupDTO.setAgentName(adviserBaseInfoDto.getAgentName());
                    }
                }
            }
            if (bookGroupDTO.getBookId() != null) {
                Map<String, Object> paramMap = Maps.newHashMap();
                paramMap.put("bookId", bookGroupDTO.getBookId());
                paramMap.put("adviserId", adviserId);
                paramMap.put("channelId", bookGroupDTO.getChannelId());
                BookDto bookDto = bookDao.getById(paramMap);
                if (bookDto != null) {
                    bookGroupDTO.setBookName(bookDto.getBookName());
                    bookGroupDTO.setBookImg(bookDto.getCoverImg());
                    bookGroupDTO.setPublish(bookDto.getPublish());
                    bookGroupDTO.setAreaLabelId(bookDto.getAreaLabelId());
                    bookGroupDTO.setVerLabelId(bookDto.getVerLabelId());
                    bookGroupDTO.setGraLabelId(bookDto.getGraLabelId());
                    bookGroupDTO.setSubLabelId(bookDto.getSubLabelId());
                    List<Long> bookLabelIds = new ArrayList<>();
                    bookLabelIds.add(bookDto.getAreaLabelId());
                    bookLabelIds.add(bookDto.getVerLabelId());
                    bookLabelIds.add(bookDto.getGraLabelId());
                    bookLabelIds.add(bookDto.getSubLabelId());
                    Map<Long, BookLabel> bookLabelMap = bookLabelDao.getMapByIds(bookLabelIds);
                    if (bookLabelMap.get(bookDto.getAreaLabelId()) != null) {
                        bookGroupDTO.setAreaLabelName(bookLabelMap.get(bookDto.getAreaLabelId()).getName());
                    }
                    if (bookLabelMap.get(bookDto.getVerLabelId()) != null) {
                        bookGroupDTO.setVerLabelName(bookLabelMap.get(bookDto.getVerLabelId()).getName());
                    }
                    if (bookLabelMap.get(bookDto.getGraLabelId()) != null) {
                        bookGroupDTO.setGraLabelName(bookLabelMap.get(bookDto.getGraLabelId()).getName());
                    }
                    if (bookLabelMap.get(bookDto.getSubLabelId()) != null) {
                        bookGroupDTO.setSubLabelName(bookLabelMap.get(bookDto.getSubLabelId()).getName());
                    }
                }
            }
        }
        //好友引导语
        List<BookGroupFriendGuide> friendGuides = this.getFriendGuideList(bookGroupId);
        if (!ListUtils.isEmpty(friendGuides)){
            bookGroupDTO.setFriendGuideList(friendGuides);
        }
        return bookGroupDTO;
    }

    /**
     * 获取社群书群二维码信息
     */
    @Override
    public BookGroupDTO getBookGroupInfoByBookId(Long bookId, Long channelId, Long adviserId, Integer addType, Long sceneId, Integer joinGroupType) throws BizException {
        BookGroupDTO bookGroupDTO = null;
        if (!bookId.equals(0L)) {
            bookGroupDTO = bookGroupDao.getDTOByBookId(bookId, channelId, adviserId);
        }
        if (null == bookGroupDTO) {
            BookGroup bookGroup = this.createBookGroupAfterCreateBook(bookId, channelId, adviserId, addType, sceneId, joinGroupType);
            bookGroupDTO = new BookGroupDTO();
            bookGroupDTO.setId(bookGroup.getId());
            bookGroupDTO.setBookId(bookId);
            bookGroupDTO.setChannelId(channelId);
            bookGroupDTO.setGroupQrcodeUrl(bookGroup.getGroupQrcodeUrl());
            bookGroupDTO.setCreateUser(adviserId);
        } else {
            // 当书籍存在时根据前端传的addType来决定用什么码替换addType=1公众号码，其他为自建码
            BookGroup group = new BookGroup();
            group.setId(bookGroupDTO.getId());
            // 更新为微信码
            if (addType != null && addType == 1) {
                //创建公众号二维码
                GroupQrcodeVO groupQrcodeVO = qrcodeSceneConsr.createWxGroupQrcode(bookId, channelId, adviserId);
                if (groupQrcodeVO == null) {
                    throw new BookBizException(BookBizException.ERROR, "二维码生成失败！");
                }
                group.setSceneId(groupQrcodeVO.getSceneId());
                group.setGroupQrcodeUrl(groupQrcodeVO.getQrcodeUrl());
                bookGroupDao.update(group);
                // 展示返回最新生成的
                bookGroupDTO.setGroupQrcodeUrl(groupQrcodeVO.getQrcodeUrl());
            }
            // 更新为自建码
            if (addType != null && addType == 2) {
                // 如果是恢复书籍，且选择自建码则清空sceneId
                if (null != bookGroupDTO.getSceneId() && bookGroupDTO.getSceneId() > 0) {
                    group.setSceneId(0L);
                    final Boolean haveQrcode = this.isHaveQrcode(bookId, channelId, adviserId);
                    // 如果之前是公众号二维码则要重新生成自有码
                    if (!haveQrcode) {
                        String groupQrcodeUrl = QrcodeUtils.createWithMargin(bookGroupQrcodeDomain + "/" + bookGroupDTO.getId(), 1);
                        group.setGroupQrcodeUrl(groupQrcodeUrl);
                        // 展示返回最新生成的
                        bookGroupDTO.setGroupQrcodeUrl(groupQrcodeUrl);
                    }
                    bookGroupDao.update(group);
                }
            }
        }
        List<Long> labelIds = new ArrayList<>();
        if (null != bookGroupDTO.getProLabelId()) {
            labelIds.add(bookGroupDTO.getProLabelId());
        }
        if (null != bookGroupDTO.getDepLabelId()) {
            labelIds.add(bookGroupDTO.getDepLabelId());
        }
        if (null != bookGroupDTO.getPurLabelId()) {
            labelIds.add(bookGroupDTO.getPurLabelId());
        }
        if (!ListUtils.isEmpty(labelIds)) {
            Map<Long, String> labelMap = ResponseHandleUtil.parseMap(labelService.getLabelName(labelIds), Long.class, String.class);
            if (!MapUtils.isEmpty(labelMap)) {
                if (null != bookGroupDTO.getProLabelId() && labelMap.containsKey(bookGroupDTO.getProLabelId())) {
                    bookGroupDTO.setProLabelName(labelMap.get(bookGroupDTO.getProLabelId()));
                }
                if (null != bookGroupDTO.getDepLabelId() && labelMap.containsKey(bookGroupDTO.getDepLabelId())) {
                    bookGroupDTO.setDepLabelName(labelMap.get(bookGroupDTO.getDepLabelId()));
                }
                if (null != bookGroupDTO.getPurLabelId() && labelMap.containsKey(bookGroupDTO.getPurLabelId())) {
                    bookGroupDTO.setPurLabelName(labelMap.get(bookGroupDTO.getPurLabelId()));
                }
            }
        }
        BookDto bookDto = bookBiz.getBaseById(bookId);
        if (null != bookDto) {
            bookDto.setBookName(null != bookDto.getBookName() ? StringUtil.addBracket(bookDto.getBookName()) : null);
            bookGroupDTO.setBookInfo(bookDto);
        }
        //好友引导语
        List<BookGroupFriendGuide> friendGuides = this.getFriendGuideList(bookGroupDTO.getId());
        if (!ListUtils.isEmpty(friendGuides)){
            bookGroupDTO.setFriendGuideList(friendGuides);
        }
        return bookGroupDTO;
    }

    @ParamLog("获取好友引导语信息")
    public List<BookGroupFriendGuide> getFriendGuideList(Long bookGroupId){
        List<BookGroupFriendGuide> friendGuides = bookGroupFriendGuideDao.getListByBookGroupId(bookGroupId);
        if (ListUtils.isEmpty(friendGuides)){
            return new ArrayList<>();
        }
        List<Long> resourceIds = friendGuides.stream().filter(s->s.getType().equals(ReplyTypeEnum.RESOURCE.value)).map(BookGroupFriendGuide::getResourceId).distinct().collect(Collectors.toList());
        Map<Long, ResourceDTO> resourceDTOMap = new HashMap<>();
        if (!ListUtils.isEmpty(resourceIds)){
            resourceDTOMap = resourceConsr.mapByIds(resourceIds);
        }
        for (BookGroupFriendGuide friendGuide : friendGuides){
            if (ReplyTypeEnum.RESOURCE.value.equals(friendGuide.getType()) && !MapUtils.isEmpty(resourceDTOMap)) {
                ResourceDTO resourceDTO = resourceDTOMap.get(friendGuide.getResourceId());
                if (resourceDTO != null) {
                    friendGuide.setResourceName(resourceDTO.getResourceName());
                    friendGuide.setResourceUrl(resourceDTO.getFileUrl());
                    friendGuide.setResourceTypeCode(resourceDTO.getTypeCode());
                    friendGuide.setResourceTypeName(resourceDTO.getTypeName());
                    friendGuide.setFileType(resourceDTO.getFileType());
                    friendGuide.setResourcePdfItems(resourceDTO.getResourcePdfItems());
                    friendGuide.setResourceOfficeItemDTOs(resourceDTO.getResourceOfficeItemDTOs());
                    friendGuide.setFileSize(resourceDTO.getFileSize());
                }
            }
        }
        return friendGuides;
    }

    /**
     * 更新群二维码信息
     */
    @Override
    @ParamLog(value = "更新群二维码信息", isAfterReturn = false)
    @Transactional(rollbackFor = Exception.class)
    public void updateBookGroup(BookGroup bookGroup) throws BizException {
        if (null == bookGroup.getId()
                || StringUtil.isEmpty(bookGroup.getGroupQrcodeName())
                || bookGroup.getJoinGroupType() == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        if (JoinGroupTypeEnum.GROUP_QRCODE.getCode().equals(bookGroup.getJoinGroupType())
                && (StringUtil.isEmpty(bookGroup.getJoinTitle())
                || StringUtil.isEmpty(bookGroup.getJoinSlogan())
                || null == bookGroup.getProLabelId()
                || null == bookGroup.getDepLabelId()
                || null == bookGroup.getPurLabelId() )) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        if (JoinGroupTypeEnum.ROBOT.getCode().equals(bookGroup.getJoinGroupType())
                && (bookGroup.getIsInviteGroup() == null
                || StringUtil.isEmpty(bookGroup.getAddFriendGuide())
                || StringUtil.isEmpty(bookGroup.getCustomerServiceName())
                || null == bookGroup.getProLabelId()
                || null == bookGroup.getDepLabelId()
                || null == bookGroup.getPurLabelId())) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        if (JoinGroupTypeEnum.AI_ROBOT.getCode().equals(bookGroup.getJoinGroupType())
                && (ListUtils.isEmpty(bookGroup.getFriendGuideList())
                || StringUtil.isEmpty(bookGroup.getShortBookName()))) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }

        if (bookGroup.getGroupQrcodeName().contains("#")){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "名称不能包含#！");
        }
        BookGroup group = bookGroupDao.getById(bookGroup.getId());
        if (null == group) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "群二维码不存在！");
        }
        if (!bookGroup.getJoinGroupType().equals(group.getJoinGroupType())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "社群码前后类型不一致！！");
        }
        checkShortBookName(bookGroup);
        if (null == group.getProductId()) {
            AddAppProductParamDTO addAppProductParamDTO = new AddAppProductParamDTO();
            addAppProductParamDTO.setAppProCode(ProductTypeConstant.BOOK_GROUP);
            addAppProductParamDTO.setAppProName(bookGroup.getGroupQrcodeName());
            addAppProductParamDTO.setCoverImg(DEFAULT_PRODUCT_COVER_IMG);
            addAppProductParamDTO.setPartyId(group.getCreateUser());
            addAppProductParamDTO.setChannelId(group.getChannelId());
            Long agentId = adviserConsr.getAgentIdByAdviser(group.getCreateUser());
            addAppProductParamDTO.setAgentId(agentId);
            Product product = ResponseHandleUtil.parseResponse(productService.postAddBookGroupProduct(addAppProductParamDTO), Product.class);
            if (null == product) {
                throw new BookBizException(BookBizException.DB_DML_FAIL, "操作失败！");
            }
            bookGroup.setProductId(product.getProductId());
        } else {
            UpdateAppProductParamDTO updateAppProductParamDTO = new UpdateAppProductParamDTO();
            updateAppProductParamDTO.setProductId(group.getProductId());
            updateAppProductParamDTO.setChannelId(group.getChannelId());
            updateAppProductParamDTO.setAppProName(bookGroup.getGroupQrcodeName());
            ResponseHandleUtil.parseResponse(productService.postUpdateBookGroupProduct(updateAppProductParamDTO), Product.class);
        }
        bookGroupDao.update(bookGroup);
        if (JoinGroupTypeEnum.AI_ROBOT.getCode().equals(bookGroup.getJoinGroupType())){
            this.updateFriendGuide(bookGroup.getId(),bookGroup.getFriendGuideList(), group.getCreateUser());
        }
    }

    /**
     * 更新群引导语
     * @param bookGroupId
     * @param friendGuideList
     */
    private void updateFriendGuide(Long bookGroupId, List<BookGroupFriendGuide> friendGuideList,Long createUser){
        if (null == bookGroupId || ListUtils.isEmpty(friendGuideList)){
            return;
        }
        bookGroupFriendGuideDao.deleteByBookGroupId(bookGroupId);
        friendGuideList.forEach(e->{
            e.setBookGroupId(bookGroupId);
            e.setCreateUser(createUser);
        });
        bookGroupFriendGuideDao.insert(friendGuideList);
    }

    @ParamLog("判断书籍简称是否重复")
    private void checkShortBookName(BookGroup bookGroup) {
        if (!StringUtil.isEmpty(bookGroup.getShortBookName())) {
            //判断是否为纯数字，不能为纯数字
            if (!StringUtil.isEmpty(bookGroup.getShortBookName())) {
                String shortBookName = bookGroup.getShortBookName();
                Boolean allNum = true;
                for (int i = 0; i < shortBookName.length(); i++) {
                    int chr = shortBookName.charAt(i);
                    if (chr < 48 || chr > 57) {
                        allNum = false;
                    }
                }
                if (allNum) {
                    throw new BookBizException(BookBizException.PARAM_IS_ERROR, "请填写符合规范的书刊简称！");
                }
            }
            BookGroup byShortBookName = bookGroupDao.getByShortBookName(bookGroup.getShortBookName());
            if (byShortBookName != null && !byShortBookName.getId().equals(bookGroup.getId())) {
                throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍简称已存在，请重新设置");
            }
        }
    }

    /**
     * 根据书刊ID删除
     */
    @Override
    @ParamLog(value = "根据书刊ID删除", isAfterReturn = false)
    @Transactional(rollbackFor = Exception.class)
    public void deleteByBookId(Long bookId, Long channelId, Long adviserId) throws BizException {
        bookGroupDao.deleteByBookId(bookId, channelId, adviserId);
    }

    /**
     * 根据书刊ID恢复
     */
    @Override
    @ParamLog(value = "根据书刊ID恢复", isAfterReturn = false)
    @Transactional(rollbackFor = Exception.class)
    public void recoverByBookId(Long bookId, Long channelId, Long adviserId) throws BizException {
        bookGroupDao.recoverByBookId(bookId, channelId, adviserId);
    }

    /**
     * 关联社群码和社群书
     */
    @Override
    @ParamLog("关联社群码和社群书")
    @Transactional(rollbackFor = Exception.class)
    public void linkBookGroup(Long bookId, Long bookGroupId, Long adviserId) throws BizException {
        BookGroupDTO bookGroupDTO = getBookGroupInfo4Wechat(bookGroupId);
        if (null == bookGroupDTO || bookGroupDTO.getIsDelete() || !bookGroupDTO.getCreateUser().equals(adviserId)) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "社群码不存在或已删除！");
        }
        if (null != bookGroupDTO.getBookId() && !bookGroupDTO.getBookId().equals(0L)) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "社群码已关联其他社群书！");
        }
        BookGroupDTO dto = bookGroupDao.getDTOByBookId(bookId, bookGroupDTO.getChannelId(), adviserId);
        if (null != dto) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "该社群书已经添加过其他社群码！");
        }
        BookGroup bookGroup = new BookGroup();
        bookGroup.setBookId(bookId);
        bookGroup.setId(bookGroupId);
        long result = bookGroupDao.linkBookGroup(bookGroup);
        if (result <= 0) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "关联社群书失败！");
        }
    }

    /**
     * 根据社群码ID获取书名
     */
    @Override
    public Map<String, Object> getBookNameByBookGroupId(Long bookGroupId) throws BizException {
        Map<String, Object> result = new HashMap<>();
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
        if (bookGroupDTO != null) {
            result.put("joinGroupType", bookGroupDTO.getJoinGroupType());
            if (JoinGroupTypeEnum.XIAORUI.getCode().equals(bookGroupDTO.getJoinGroupType())){
                BookAppletScene applet = bookAppletSceneDao.getByBookGroupId(bookGroupId);
                if (null!=applet){
                    result.put("classifyId",applet.getRaysClassifyId());
                }
            }
        }
        if (null != bookGroupDTO && null != bookGroupDTO.getBookId()) {
            BookDto bookDto = bookBiz.getBaseById(bookGroupDTO.getBookId());
            if (null != bookDto) {
                result.put("bookName", StringUtil.addBracket(bookDto.getBookName()));
            }
            result.put("isDelete", bookGroupDTO.getIsDelete());
        } else {
            result.put("isDelete", true);
        }
        return result;
    }

    /**
     * 获取社群书列表(编辑)
     */
    @Override
    public PageBean listBookGroup4Adviser(Map<String, Object> paramMap, PageParam pageParam, Long adviserId) throws BizException {
        PageBean pageBean = bookDao.listPage(pageParam, paramMap, "listBookGroup4Adviser");
        if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBean(0, 0, new ArrayList<>());
        }
        // 设置是否被冻结
        bookSet.setFreezeStatus(pageBean.getRecordList());
        // 填充社群书数据
        List<Long> bookGroupIds = new ArrayList<>();
        pageBean.getRecordList().forEach(obj -> bookGroupIds.add(((BookDto) obj).getBookGroupId()));
        ResponseEntity<ResponseDto<Map<Long, BigDecimal>>> responseEntity = settlementService.getWXGroupIncomeByAdviser(bookGroupIds, adviserId);
        Map<Long, BigDecimal> incomeMap = ResponseHandleUtil.parseMap(responseEntity, Long.class, BigDecimal.class);
        Map<Long, BookGroupStatisticDTO> statisMap = bookGroupClassifyDao.getClassifyCountAbout(bookGroupIds);
        Map<Long, Integer> scanMap = ResponseHandleUtil.parseMap(groupMemberService.getScanUserCountByGroup(bookGroupIds), Long.class, Integer.class);
        for (Object object : pageBean.getRecordList()) {
            BookDto bookDto = (BookDto) object;
            Long bookGroupId = bookDto.getBookGroupId();
            bookDto.setGroupQrcodeLink(bookGroupQrcodeDomain + "/" + bookGroupId);
            bookDto.setBookName(null != bookDto.getBookName() ? StringUtil.addBracket(bookDto.getBookName()) : null);
            if (!MapUtils.isEmpty(statisMap) && statisMap.containsKey(bookGroupId)) {
                BookGroupStatisticDTO dto = statisMap.get(bookGroupId);
                bookDto.setClassifyCount(null != dto.getClassifyCount() ? dto.getClassifyCount().longValue() : 0L);
                bookDto.setGroupCount(null != dto.getGroupNumber() ? dto.getGroupNumber().longValue() : 0L);
                bookDto.setGroupPersonCount(null != dto.getUserNumber() ? dto.getUserNumber().longValue() : 0L);
            } else {
                bookDto.setClassifyCount(0L);
                bookDto.setGroupPersonCount(0L);
                bookDto.setGroupCount(0L);
            }
            if (!MapUtils.isEmpty(scanMap) && scanMap.containsKey(bookGroupId)) {
                bookDto.setScanCount(null != scanMap.get(bookGroupId) ? scanMap.get(bookGroupId).longValue() : 0L);
            } else {
                bookDto.setScanCount(0L);
            }
            if (!MapUtils.isEmpty(incomeMap) && incomeMap.containsKey(bookGroupId)) {
                BigDecimal income = incomeMap.get(bookGroupId);
                bookDto.setTotalIncome(null != income ? income.setScale(2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO);
            } else {
                bookDto.setTotalIncome(BigDecimal.ZERO);
            }
            //好友数量
            Integer friendsCount = bookGroupCipherUserDao.getFriendsCountByBookGroup(bookGroupId);
            bookDto.setFriendsCount(friendsCount);
            Boolean hasRobotKeyword = selfRobotKeywordBiz.hasKeyword(bookGroupId);
            bookDto.setHasRobotKeyword(hasRobotKeyword);
        }
        return pageBean;
    }

    @Override
    public PageBean listBookGroup4Channel(Long channelId, ListBookGroup4ChannelParamVO listBookGroup4ChannelParamVO) {
        Integer currentPage = listBookGroup4ChannelParamVO.getCurrentPage();
        Integer numPerPage = listBookGroup4ChannelParamVO.getNumPerPage();
        if (currentPage == null || numPerPage == null || currentPage < 0 || numPerPage < 0) {
            throw BookBizException.PAGE_PARAM_DELETION;
        }
        PageParam pageParam = new PageParam(currentPage, numPerPage);
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("channelId", channelId);
        paramMap.put("keywords", listBookGroup4ChannelParamVO.getKeywords());
        paramMap.put("isFundBook", listBookGroup4ChannelParamVO.getIsFundBook());
        String startTime = listBookGroup4ChannelParamVO.getStartTime();
        String endTime = listBookGroup4ChannelParamVO.getEndTime();
        if (startTime != null){
            paramMap.put("startTime", startTime + " 00:00:00");
        }
        if (endTime != null){
            paramMap.put("endTime", endTime + " 23:59:59");
        }
        PageBean listBookGroup4Channel = bookDao.listPage(pageParam, paramMap, "listBookGroup4Channel");
        List<Long> bookGroupIds = new ArrayList<>();
        listBookGroup4Channel.getRecordList().forEach(e -> {
            ListBook4ChannelVO listBook4ChannelVO = (ListBook4ChannelVO) e;
            bookGroupIds.add(listBook4ChannelVO.getBookGroupId());
        });
        if(ListUtils.isEmpty(bookGroupIds)){
            return new PageBean(0, 0, new ArrayList<>());
        }
        Map<Long, BookGroupStatisticDTO> statisMap = bookGroupClassifyDao.getClassifyCountAbout(bookGroupIds);
        listBookGroup4Channel.getRecordList().forEach( e ->{
            ListBook4ChannelVO listBook4ChannelVO = (ListBook4ChannelVO) e;
            if (!MapUtils.isEmpty(statisMap) && statisMap.containsKey(listBook4ChannelVO.getBookGroupId())) {
                BookGroupStatisticDTO dto = statisMap.get(listBook4ChannelVO.getBookGroupId());
                listBook4ChannelVO.setClassifyNum(null != dto.getClassifyCount() ? dto.getClassifyCount().longValue() : 0L);
                listBook4ChannelVO.setTotalNum(null != dto.getUserNumber() ? dto.getUserNumber().longValue() : 0L);
            }else {
                listBook4ChannelVO.setClassifyNum(0L);
                listBook4ChannelVO.setTotalNum(0L);
            }
        });

        return listBookGroup4Channel;
    }

    /**
     * 获取社群书列表(编辑)
     */
    @Override
    public List<BookDto> listSimpleBookGroup4Adviser(Map<String, Object> paramMap) throws BizException {
        return bookDao.listSimpleBookGroup4Adviser(paramMap);
    }

    /**
     * 获取社群书列表(编辑)
     */
    @Override
    public PageBean listSimpleBookGroup4Adviser(Map<String, Object> paramMap, PageParam pageParam) throws BizException {
        return bookDao.listPage(pageParam, paramMap, "listSimpleBookGroup4Adviser");
    }

    /**
     * 获取未创建社群码的书刊列表
     */
    @Override
    public PageBean listBook4CreateBookGroup(Map<String, Object> paramMap, PageParam pageParam, Long adviserId) throws BizException {
        PageBean pageBean = bookDao.listPage(pageParam, paramMap, "listBook4CreateBookGroup");
        if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBean(0, 0, new ArrayList<>());
        }
        return pageBean;
    }

    @Override
    @ParamLog("获取社群码名称以及商品标识")
    public QrcodeNameAndProIdDTO getQrcodeNameAndProId(Long bookGroupId) throws BizException {
        return bookGroupDao.getQrcodeNameAndProId(bookGroupId);
    }

    @Override
    @ParamLog("获取排序类型")
    public Integer getRankType(Long bookGroupId) throws BizException {
        return bookGroupDao.getRankType(bookGroupId);
    }

    @Override
    @ParamLog("更新排序类型")
    public void updateRankType(Long bookGroupId, Integer rankType) throws BizException {
        bookGroupDao.updateRankType(bookGroupId, rankType);
    }

    /**
     * 编辑获取社群码总数量
     */
    @Override
    public Map<String, Object> getTotalBookGroupCount(Long adviserId) throws BizException {
        Map<String, Object> result = new HashMap<>();
        Integer bookGroupCount = bookGroupDao.getBookGroupCount(adviserId);
        result.put("bookGroupCount", bookGroupCount);
        Integer friendsCount = bookGroupDao.getBookGroupFriendsCountByAdviser(adviserId);
        result.put("friendsCount", friendsCount);
        return result;
    }

    @Override
    public String getSpareQr(Long bookGroupId) {
        return bookGroupDao.getSpareQr(bookGroupId);
    }

    @Override
    public BookGroupDTO getBaseInfoBySceneId(Long sceneId) {
        BookGroupDTO bookGroupDTO = bookGroupDao.getBaseInfoBySceneId(sceneId);
        if (bookGroupDTO != null) {
            bookGroupDTO.setUrl(bookGroupQrcodeDomain + "/" + bookGroupDTO.getId());
        }
        return bookGroupDTO;
    }

    @Override
    public void updatePersonQrcode(PersonalQrcodeDTO personalQrcodeDTO) {
        if (personalQrcodeDTO == null || personalQrcodeDTO.getNewQrcodeUrl() == null ||
                personalQrcodeDTO.getOldQrcodeUrl() == null){
            throw new BookBizException(BookBizException.ERROR,"参数缺失");
        }
        bookGroupDao.updatePersonQrcode(personalQrcodeDTO);
    }

    @Override
    @ParamLog("是否是特殊的出版社")
    public Boolean isSpecialAgent(Long agentId) {
        return bookGroupDao.isSpecialAgent(agentId);
    }

    @Override
    public Boolean isHaveQrcode(Long bookId, Long channelId, Long adviserId) {
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOByBookId(bookId, channelId, adviserId);
        return bookGroupDTO != null && null == bookGroupDTO.getSceneId();
    }

    @ParamLog("获取应用统计")
    @Override
    public PageBeanNew<AppStatisticsDTO> getAppStatistics(Integer currentPage, Integer numPerPage, Long bookGroupId, Long qrcodeId, Long partyId) {
        PageParam pageParam = new PageParam(currentPage, numPerPage);
        Map<String, Object> map = new HashMap<>();
        map.put("bookGroupId", bookGroupId);
        map.put("qrcodeId", qrcodeId);
        PageBeanNew<AppStatisticsDTO> pageBeanNew ;
        if (qrcodeId != null) {
            pageBeanNew = appTouchRecordDao.listPageNew(pageParam, map, "getAppTouchStatistics");
        } else {
            pageBeanNew = bookGroupAppDao.listPageNew(pageParam, map, "getAppServeStatistics");
            List<AppStatisticsDTO> list = pageBeanNew.getRecordList();
            if (!ListUtils.isEmpty(list)) {
                List<AppStatisticsDTO> touchStatistics = appTouchRecordDao.getAppTouchStatistics(map);
                if (!ListUtils.isEmpty(touchStatistics)) {
                    for (AppStatisticsDTO appStatisticsDTO : list) {
                        for (AppStatisticsDTO in : touchStatistics) {
                            if (appStatisticsDTO.getServeId().equals(in.getServeId()) && appStatisticsDTO.getServeType().equalsIgnoreCase(in.getServeType())) {
                                appStatisticsDTO.setPushCount(in.getPushCount());
                            }
                        }
                    }
                }
                for (AppStatisticsDTO appStatisticsDTO : list) {
                    if (appStatisticsDTO.getPushCount() == null) {
                        appStatisticsDTO.setPushCount(0);
                    }
                }
            }
        }
        List<AppStatisticsDTO> appStatisticsDTOS = pageBeanNew.getRecordList();
        if (ListUtils.isEmpty(appStatisticsDTOS)) {
            return pageBeanNew;
        }
        List<Long> serveIds = appStatisticsDTOS.stream().filter(s -> s.getServeId() != null).map(AppStatisticsDTO::getServeId).collect(Collectors.toList());
        //获取点击次数
        List<AppStatisticsDTO> appClickStatisticsDTOS = appClickRecordDao.getClickStatisticsByServeIds(serveIds, qrcodeId, bookGroupId);
        Map<Long, Integer> clickCountMap = new HashMap<>();
        if (!ListUtils.isEmpty(appClickStatisticsDTOS)) {
            for (AppStatisticsDTO in : appClickStatisticsDTOS) {
                clickCountMap.put(in.getServeId(), in.getClickCount());
            }
        }
        List<Long> productIds = appStatisticsDTOS.stream().filter(s -> s.getServeId() != null && "PRODUCT".equalsIgnoreCase(s.getServeType())).map(AppStatisticsDTO::getServeId).collect(Collectors.toList());
        List<Long> appIds = appStatisticsDTOS.stream().filter(s -> s.getServeId() != null && "APP".equalsIgnoreCase(s.getServeType())).map(AppStatisticsDTO::getServeId).collect(Collectors.toList());
        //获取详情
        Map<Long, AppDto> appDtoMap = appConsr.mapByIds(appIds);
        Map<Long, ProductDto> productDtoMap = productConsr.getProBasesByIds(productIds);


        List<AppPriceCacheDTO> appPriceCacheDTOS = new ArrayList<>();
        for (Long appId : appIds) {
            if (appDtoMap.get(appId) != null) {
                AppPriceCacheDTO appPriceCacheDTO = new AppPriceCacheDTO();
                appPriceCacheDTO.setAppTypeEnum(AppTypeEnum.APP_TYPE_MAP.get(appDtoMap.get(appId).getTypeCode()));
                appPriceCacheDTO.setAppId(appId);
                appPriceCacheDTOS.add(appPriceCacheDTO);
            }
        }
        Map<Long, BigDecimal> appPriceMap = ResponseHandleUtil.parseMapResponse(appPriceCacheService.getCaches(appPriceCacheDTOS), Long.class, BigDecimal.class);
        //结算接口
        Map<Long, BigDecimal> productIncomeMap = settlementConsr.getAdviserIncomeByCondition(productIds, "PRODUCT", partyId, qrcodeId, bookGroupId);
        Map<Long, BigDecimal> appIncomeMap = settlementConsr.getAdviserIncomeByCondition(appIds, "APP", partyId, qrcodeId, bookGroupId);
        //交易接口
        WechatGroupDto wechatGroupDtoP = new WechatGroupDto();
        wechatGroupDtoP.setBookGroupId(bookGroupId);
        wechatGroupDtoP.setIds(productIds);
        wechatGroupDtoP.setPartyId(partyId);
        wechatGroupDtoP.setType("PRODUCT");
        wechatGroupDtoP.setQrcodeId(qrcodeId);
        WechatGroupDto wechatGroupDtoA = new WechatGroupDto();
        wechatGroupDtoA.setBookGroupId(bookGroupId);
        wechatGroupDtoA.setIds(appIds);
        wechatGroupDtoA.setPartyId(partyId);
        wechatGroupDtoA.setType("APP");
        wechatGroupDtoA.setQrcodeId(qrcodeId);
        Map<Long, GroupMoneyDto> productSaleMap = tradeConsr.getQrGroupSaleMoney(wechatGroupDtoP);
        Map<Long, GroupMoneyDto> appSaleMap = tradeConsr.getQrGroupSaleMoney(wechatGroupDtoA);
        for (AppStatisticsDTO appStatisticsDTO : appStatisticsDTOS) {
            Long id = appStatisticsDTO.getServeId();
            String type = appStatisticsDTO.getServeType();
            Integer clickCount = clickCountMap.get(id);
            if (clickCount == null) {
                clickCount = 0;
            }
            appStatisticsDTO.setClickCount(clickCount);
            Integer buyCount = 0;
            Double incomeAmount = 0D;
            Double saleAmount = 0D;
            if ("PRODUCT".equalsIgnoreCase(type)) {
                if (productIncomeMap.get(id) != null) {
                    incomeAmount = productIncomeMap.get(id).doubleValue();
                }
                appStatisticsDTO.setIncomeAmount(incomeAmount);
                if (productSaleMap.get(id) != null) {
                    saleAmount = productSaleMap.get(id).getSaleMoney();
                    buyCount = productSaleMap.get(id).getSaleCount().intValue();
                }
                appStatisticsDTO.setSaleAmount(saleAmount);
                appStatisticsDTO.setBuyCount(buyCount);
                if (productDtoMap != null && productDtoMap.get(id) != null) {
                    ProductDto productDto = productDtoMap.get(id);
                    appStatisticsDTO.setServeName(productDto.getProductName());
                    appStatisticsDTO.setImage(productDto.getCoverImg());
                    ProductTypeDto productTypeDto = productDto.getProductTypeDto();
                    if (productTypeDto != null) {
                        appStatisticsDTO.setTypeName(productTypeDto.getTypeName());
                    }
                    List<SpecificationDto> specificationDtos = productDto.getSpecification();
                    if (!ListUtils.isEmpty(specificationDtos)) {
                        SpecificationDto specificationDto = specificationDtos.get(0);
                        if (specificationDto != null) {
                            appStatisticsDTO.setDealPrice(specificationDto.getDealPrice());
                            appStatisticsDTO.setRetailPrice(specificationDto.getAdvisePrice());
                        }
                    }
                }
            }
            if ("APP".equalsIgnoreCase(type)) {
                if (appIncomeMap.get(id) != null) {
                    incomeAmount = appIncomeMap.get(id).doubleValue();
                }
                appStatisticsDTO.setIncomeAmount(incomeAmount);
                GroupMoneyDto groupMoneyDtoApp = appSaleMap.get(id);
                if (groupMoneyDtoApp != null) {
                    saleAmount = groupMoneyDtoApp.getSaleMoney();
                    buyCount = groupMoneyDtoApp.getSaleCount().intValue();
                }
                appStatisticsDTO.setSaleAmount(saleAmount);
                appStatisticsDTO.setBuyCount(buyCount);
                if (appDtoMap != null && appDtoMap.get(id) != null) {
                    AppDto appDto = appDtoMap.get(id);
                    appStatisticsDTO.setTypeName(appDto.getTypeName());
                    appStatisticsDTO.setServeName(appDto.getTitle());
                    appStatisticsDTO.setImage(appDto.getSquareImg());
                }
                if (appPriceMap != null) {
                    if (appPriceMap.get(id) != null) {
                        appStatisticsDTO.setRetailPrice(appPriceMap.get(id).doubleValue());
                        appStatisticsDTO.setDealPrice(0D);
                    }
                }
            }
            if (buyCount == null || buyCount == 0 || clickCount == null || clickCount == 0) {
                appStatisticsDTO.setBuyRate(0D);
            } else {
                appStatisticsDTO.setBuyRate(new BigDecimal(buyCount.doubleValue() / clickCount).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
            }
        }
        //处理音频、视频、直播课的逻辑
        dealOtherSale(appStatisticsDTOS,productDtoMap,bookGroupId,qrcodeId,partyId);
        return pageBeanNew;
    }

    @ParamLog("处理音频、视频、直播课的逻辑")
    private void dealOtherSale(List<AppStatisticsDTO> appStatisticsDTOS, Map<Long, ProductDto> productDtoMap, Long bookGroupId, Long qrcodeId, Long partyId) {
        if (productDtoMap == null || productDtoMap.values() == null || productDtoMap.values().isEmpty()) {
            return;
        }
        //视频课，音频课，直播课特殊处理
        List<Long> videoProductIds = new ArrayList<>();
        List<Long> audioProductIds = new ArrayList<>();
        List<Long> liveProductIds = new ArrayList<>();
        List<ProductDto> productDtos = new ArrayList<>(productDtoMap.values());
        if (!ListUtils.isEmpty(productDtos)) {
            for (ProductDto productDto : productDtos) {
                ProductTypeDto productTypeDto=productDto.getProductTypeDto();
                String productTypeCode="";
                if (productTypeDto!=null){
                    productTypeCode=productTypeDto.getTypeCode();
                }
                String[] videoTypes = {"VIDEO_COURSE", "VIDEO_SCHEDULE"};
                if (Arrays.asList(videoTypes).contains(productTypeCode)) {
                    videoProductIds.add(productDto.getProductId());
                }
                String[] audioTypes = {"AUDIOAPP", "AUDIO_RESOURCE", "AUDIO_SCHEDULE", "AUDIO_COURSE"};
                if (Arrays.asList(audioTypes).contains(productTypeCode)) {
                    audioProductIds.add(productDto.getProductId());
                }
                String[] liveTypes = {"LIVE", "SCHEDULE"};
                if (Arrays.asList(liveTypes).contains(productTypeCode)) {
                    liveProductIds.add(productDto.getProductId());
                }
            }
        }
        Map<Long, List<Long>> videoPProductMapIds = new HashMap<>();
        Map<Long, List<Long>> audioPProductMapIds = new HashMap<>();
        Map<Long, List<Long>> livePProductMapIds = new HashMap<>();
        //视频课
        if (!ListUtils.isEmpty(videoProductIds)) {
            videoPProductMapIds = ResponseHandleUtil.parseMapList(scheduleService.getCourseProductIdByIds(videoProductIds, "PRODUCT"), Long.class, Long.class);
        }
        //音频课
        if (!ListUtils.isEmpty(audioProductIds)) {
            audioPProductMapIds = ResponseHandleUtil.parseMapList(audioLessonService.getProIdsByIds(audioProductIds, "PRODUCT"), Long.class, Long.class);
        }
        //直播课
        if (!ListUtils.isEmpty(liveProductIds)) {
            ProductIdSearchDto productIdSearchDto=new ProductIdSearchDto();
            productIdSearchDto.setIds(liveProductIds);
            productIdSearchDto.setType("PRODUCT");
            livePProductMapIds = ResponseHandleUtil.parseMapList(timeTableService.getCoursePidsUnderTable(productIdSearchDto), Long.class, Long.class);
        }
        List<Long> valProductIds = new ArrayList<>();
        fillProductIdsFromLL(valProductIds,videoPProductMapIds);
        fillProductIdsFromLL(valProductIds,audioPProductMapIds);
        fillProductIdsFromLL(valProductIds,livePProductMapIds);
        if (!ListUtils.isEmpty(valProductIds)){
            //调交易中心获取交易额信息
            WechatGroupDto wechatGroupDtoP = new WechatGroupDto();
            wechatGroupDtoP.setBookGroupId(bookGroupId);
            wechatGroupDtoP.setIds(valProductIds);
            wechatGroupDtoP.setPartyId(partyId);
            wechatGroupDtoP.setType("PRODUCT");
            wechatGroupDtoP.setQrcodeId(qrcodeId);
            Map<Long, GroupMoneyDto> productSaleMap = tradeConsr.getQrGroupSaleMoney(wechatGroupDtoP);
            Map<Long, BigDecimal> productIncomeMap = settlementConsr.getAdviserIncomeByCondition(valProductIds, "PRODUCT", partyId, qrcodeId, bookGroupId);
            SpeWechatGroupDto speWechatGroupDto=new SpeWechatGroupDto();
            speWechatGroupDto.setBookGroupId(bookGroupId);
            speWechatGroupDto.setPartyId(partyId);
            speWechatGroupDto.setQrcodeId(qrcodeId);
            Map<Long,List<Long>> map=new HashMap<>();
            map.putAll(videoPProductMapIds);
            map.putAll(audioPProductMapIds);
            map.putAll(livePProductMapIds);
            speWechatGroupDto.setProductIdMap(map);
            Map<Long, GroupMoneyDto> forBuyCountMap = tradeConsr.getSpeQrGroupSaleMoney(speWechatGroupDto);
            Map<Long, Double> proSaleMap = new HashMap<>();
            Map<Long, Double> proIncomeMap = new HashMap<>();
            if (productSaleMap.values() != null && !productSaleMap.values().isEmpty()) {
                dealSale(videoProductIds, videoPProductMapIds, productSaleMap, proSaleMap, productIncomeMap, proIncomeMap);
                dealSale(audioProductIds, audioPProductMapIds, productSaleMap, proSaleMap, productIncomeMap, proIncomeMap);
                dealSale(liveProductIds, livePProductMapIds, productSaleMap, proSaleMap, productIncomeMap, proIncomeMap);
                for (AppStatisticsDTO appStatisticsDTO : appStatisticsDTOS) {
                    Long id = appStatisticsDTO.getServeId();
                    String type = appStatisticsDTO.getServeType();
                    if ("PRODUCT".equalsIgnoreCase(type)) {
                        Integer toAddCount = 0;
                        GroupMoneyDto groupMoneyDto = forBuyCountMap.get(id);
                        if (groupMoneyDto != null && groupMoneyDto.getSaleCount() != null) {
                            toAddCount = groupMoneyDto.getSaleCount().intValue();
                        }
                        addProductSale(id, productDtoMap, proSaleMap, proIncomeMap, toAddCount, appStatisticsDTO);
                    }
                }
            }
        }
    }

    private void addProductSale(Long id, Map<Long, ProductDto> productDtoMap, Map<Long, Double> proSaleMap, Map<Long, Double> proIncomeMap, Integer toAddCount, AppStatisticsDTO appStatisticsDTO) {
        ProductDto productDto = productDtoMap.get(id);
        String[] videoTypes = {"VIDEO_COURSE", "VIDEO_SCHEDULE"};
        String[] audioTypes = {"AUDIOAPP", "AUDIO_RESOURCE", "AUDIO_SCHEDULE", "AUDIO_COURSE"};
        String[] liveTypes = {"LIVE", "SCHEDULE"};
        String typeCode = "";
        if (productDto != null && productDto.getProductTypeDto() != null) {
            typeCode = productDto.getProductTypeDto().getTypeCode();
        }
        if (productDto != null && (Arrays.asList(videoTypes).contains(typeCode)
                || Arrays.asList(audioTypes).contains(typeCode)
                || Arrays.asList(liveTypes).contains(typeCode))) {
            Double toAdd = proSaleMap.get(id);
            Double incomeToAdd = proIncomeMap.get(id);
            if (toAdd != null) {
                Double oldSale = appStatisticsDTO.getSaleAmount();
                if (oldSale == null) {
                    oldSale = 0D;
                }
                appStatisticsDTO.setSaleAmount(oldSale + toAdd);
            }
            if (incomeToAdd != null) {
                Double oldIncome = appStatisticsDTO.getIncomeAmount();
                if (oldIncome == null) {
                    oldIncome = 0D;
                }
                appStatisticsDTO.setIncomeAmount(oldIncome + incomeToAdd);
            }
            if (toAddCount != null) {
                Integer oldBuy = appStatisticsDTO.getBuyCount();
                if (oldBuy == null) {
                    oldBuy = 0;
                }
                appStatisticsDTO.setBuyCount(oldBuy + toAddCount);
                Integer buyCount = appStatisticsDTO.getBuyCount();
                Integer clickCount = appStatisticsDTO.getClickCount();
                //重新设置购买率
                if (buyCount == null || buyCount == 0 || clickCount == null || clickCount == 0) {
                    appStatisticsDTO.setBuyRate(0D);
                } else {
                    appStatisticsDTO.setBuyRate(new BigDecimal(buyCount.doubleValue() / clickCount).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                }
            }
        }
    }

    private void dealSale(List<Long> ids, Map<Long,List<Long>> productMapIds, Map<Long,GroupMoneyDto> productSaleMap, Map<Long,Double> saleMap, Map<Long, BigDecimal> productIncomeMap, Map<Long, Double> incomeMap) {
        if (!ListUtils.isEmpty(ids)) {
            for (Long id : ids) {
                List<Long> productIds = productMapIds.get(id);
                if (!ListUtils.isEmpty(productIds)) {
                    Double saleMoney = 0D;
                    Long  saleCount = 0L;
                    Double incomeMoney = 0D;
                    for (Long productId : productIds) {
                        GroupMoneyDto groupMoneyDto = productSaleMap.get(productId);
                        if (groupMoneyDto != null) {
                            if (groupMoneyDto.getSaleMoney() != null) {
                                saleMoney = saleMoney + groupMoneyDto.getSaleMoney();
                            }
                            if (groupMoneyDto.getSaleCount() != null) {
                                saleCount = saleCount + groupMoneyDto.getSaleCount();
                            }
                        }
                        if (productIncomeMap != null && productIncomeMap.get(productId) != null) {
                            incomeMoney = incomeMoney + productIncomeMap.get(productId).doubleValue();
                        }
                    }
                    saleMap.put(id, saleMoney);
                    incomeMap.put(id, incomeMoney);
                }
            }
        }
    }

    private void fillProductIdsFromLL(List<Long> productIds,Map<Long, List<Long>> map){
        if (map != null && !map.values().isEmpty()) {
            List<List<Long>> ll = new ArrayList<>(map.values());
            for (List<Long> l : ll) {
                if (!ListUtils.isEmpty(l)) {
                    productIds.addAll(l);
                }
            }
        }
    }
    @Override
    public void exportGroupQrcode4Adviser(Map<String, Object> paramMap, Long adviserId) {
        ThreadPoolUtils.EXPORT_THREAD_POOL.execute(() -> {
            // 生成文件名
            String fileName = "社群码导出_" + DateUtils.getShortDateStr();
            Boolean isSuccess = true;
            String zipUrl = "";
            try {
                Map<String, List<String[]>> zipFileMap = new HashMap<>();
                List<String[]> qrcodePicUrls = new ArrayList<String[]>();
                // 设置查询参数
                List<BookDto> bookDtos = bookDao.listBookGroup4Adviser(paramMap);
                if (ListUtils.isEmpty(bookDtos)) {
                    return;
                }
                Integer noName = 0;
                for (BookDto bookDto : bookDtos) {
                    String bookName = null != bookDto.getBookName() ? StringUtil.addBracket(bookDto.getBookName()) : null;
                    String groupQrcodeName = bookDto.getGroupQrcodeName();
                    if (StringUtil.isEmpty(bookDto.getGroupQrcodeUrl())) {
                        continue;
                    }
                    String qrcodeUrl = bookDto.getGroupQrcodeUrl().replace("//oss", "//file");
                    String qrcodeName;
                    if (!StringUtil.isEmpty(bookName)) {
                        qrcodeName = bookName;
                        if (!StringUtil.isEmpty(groupQrcodeName)) {
                            qrcodeName = qrcodeName + groupQrcodeName;
                        }
                    } else {
                        if (!StringUtil.isEmpty(groupQrcodeName)) {
                            qrcodeName = groupQrcodeName;
                        } else {
                            noName = noName + 1;
                            qrcodeName = "未命名" + noName;
                        }
                    }
                    if (Integer.valueOf(2).equals(bookDto.getJoinGroupType()) && !StringUtil.isEmpty(bookDto.getBookGroupCipher())) {
                        qrcodeName = qrcodeName + "（" + bookDto.getBookGroupCipher() + "）";
                    }
                    // 加入二维码图片
                    String[] qrcodePicurl = {qrcodeName, qrcodeUrl};
                    qrcodePicUrls.add(qrcodePicurl);
                }
                zipFileMap.put(fileName, qrcodePicUrls);
                UploadResultInfo zipUrlInfo = CompressUtils.zipByCatalog(zipFileMap, fileName);
                zipUrl = zipUrlInfo != null ? zipUrlInfo.getUrl() : null;

            } catch (Exception e) {
                LOGGER.error("生成导出文件失败" + e.getMessage(), e);
                isSuccess = false;
            }
            // 发送消息
            if (isSuccess) {
                JSONObject content = new JSONObject();
                content.put("commitTime", DateUtils.formatDate(new Date()));
                content.put("type", "社群码导出");
                messageConsr.sendLetter(adviserId, adviserId, content.toJSONString(), SystemCode.adviser.code, "qrcode_download", zipUrl, fileName, NotifyOriginTypeEnum.BOOK_GROUP.value, null);
            }
        });
    }

    @ParamLog("根据bookId获取社群书分类等统计")
    @Override
    public StatisticVO getBookGroupStatistics(Long bookId) {
        StatisticVO statisticVO = bookGroupClassifyDao.getBookGroupStatistics(bookId);
        if (null == statisticVO || null == statisticVO.getBookGroupId()) {
            return new StatisticVO();
        }
        if (JoinGroupTypeEnum.ROBOT.getCode().equals(statisticVO.getJoinGroupType())) {
            Long bookGroupId = statisticVO.getBookGroupId();
            //个人号数、好友数
            Integer robotCount = bookGroupCipherUserDao.getAltCountByBookGroup(bookGroupId);
            statisticVO.setRobotCount(robotCount);
            Integer friendCount = bookGroupCipherUserDao.getFriendsCountByBookGroup(bookGroupId);
            statisticVO.setFriendCount(friendCount);
        }
        return statisticVO;
    }

    @ParamLog("根据bookId获取社群书分类和关键词等统计信息")
    @Override
    public List<ClassifyKeywordDTO> getBookGroupKeywordStatistics(Long bookId) {
        List<ClassifyKeywordDTO> classifyKeywordDTOS = bookGroupClassifyDao.getClassifyStatistics(bookId);
        return classifyKeywordDTOS;
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("更新是否显示书名")
    @Override
    public void updateIsShowBookName(Boolean isShowBookName, Long partyId) {
        bookGroupDao.updateIsShowBookName(isShowBookName,partyId);
    }

    @ParamLog("获取是否显示书名")
    @Override
    public Boolean getIsShowBookName(Long partyId) {
        return bookGroupDao.getIsShowBookName(partyId);
    }


    @Transactional(rollbackFor = Exception.class)
    @ParamLog("删除社群码")
    @Override
    public void deleteBookGroup(Long bookGroupId) {
        if (bookGroupId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空");
        }
        BookGroupDTO dto = bookGroupDao.getDTOById(bookGroupId);
        if (dto == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "没有该数据！");
        }
        if (dto.getBookId() != null && !new Long(0L).equals(dto.getBookId())) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "该社群码已经绑定图书！");
        }
        ClassifyAndGroupCountVO classifyAndGroupCount = bookGroupClassifyBiz.getClassifyAndGroupCount(bookGroupId);
        if (classifyAndGroupCount != null
                && ((classifyAndGroupCount.getClassifyCount() != null && classifyAndGroupCount.getClassifyCount() > 0)
                || (classifyAndGroupCount.getGroupCount() != null && classifyAndGroupCount.getGroupCount() > 0))) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "该社群码下已有分类！");
        }
        bookGroupDao.deleteByBookGroupId(bookGroupId);
    }

    @Override
    public void deleteBookGroup4Adviser(Long bookGroupId) {
        if (bookGroupId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空");
        }
        BookGroupDTO dto = bookGroupDao.getDTOById(bookGroupId);
        if (dto == null || dto.getIsDelete()) {
            throw new BookBizException(BookBizException.ID_NOT_EXIST, "没有该数据！");
        }
        bookGroupDao.deleteByBookGroupId(bookGroupId);
        bookAppletSceneDao.deleteByBookGroupId(bookGroupId);
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("根据社群码id获取个人二维码信息")
    @Override
    public OwnAltQrcodeInfoDTO getOwnAltQrcodeInfoDTOByBookGroupId(Long wechatUserId, Long bookGroupId) {
        OwnAltQrcodeInfoDTO ownAltQrcodeInfoDTO = new OwnAltQrcodeInfoDTO();
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
        if (bookGroupDTO == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "没有该社群码");
        }
        ownAltQrcodeInfoDTO.setCustomerServiceName(bookGroupDTO.getCustomerServiceName());
        //这里的暗号从社群书获取
        ownAltQrcodeInfoDTO.setCipher(bookGroupDTO.getBookGroupCipher());
        ownAltQrcodeInfoDTO.setAddFriendGuide(bookGroupDTO.getAddFriendGuide());
        Long bookId = bookGroupDTO.getBookId();
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("bookId", bookId);
        paramMap.put("adviserId", bookGroupDTO.getCreateUser());
        paramMap.put("channelId", bookGroupDTO.getChannelId());
        BookDto bookDto = bookDao.getById(paramMap);
        Long templetId = bookDto.getTempletId();
        //根据分类id获取大类
        TempletRelevance templetRelevance = templetRelevanceDao.getByTempletId(templetId);
        LOGGER.info("根据分类id获取大类templetRelevance" + templetRelevance.toString());
        Integer largeTemplet = templetRelevance.getLargeTemplet();
        Long agentId=bookGroupDTO.getAgentId();
        //根据bookGroupId获取机器人
        AvailableRobotParamDTO availableRobotParamDTO=new AvailableRobotParamDTO();
        availableRobotParamDTO.setAgentId(agentId);
        availableRobotParamDTO.setBookGroupId(bookGroupId);
        availableRobotParamDTO.setWechatUserId(wechatUserId);
        availableRobotParamDTO.setLargeTemplet(largeTemplet);
        availableRobotParamDTO.setSpecialAgent(bookGroupDTO.getBelongSpecialAgent());
        if (JoinGroupTypeEnum.ROBOT.getCode().equals(bookGroupDTO.getJoinGroupType())){
            List<Long> labelIds = new ArrayList<>();
            if (null != bookGroupDTO.getProLabelId()) {
                labelIds.add(bookGroupDTO.getProLabelId());
            }
            if (null != bookGroupDTO.getDepLabelId()) {
                labelIds.add(bookGroupDTO.getDepLabelId());
            }
            if (!ListUtils.isEmpty(labelIds)) {
                Map<Long, String> labelMap = ResponseHandleUtil.parseMap(labelService.getLabelName(labelIds), Long.class, String.class);
                if (!MapUtils.isEmpty(labelMap)) {
                    if (null != bookGroupDTO.getProLabelId() && labelMap.containsKey(bookGroupDTO.getProLabelId())) {
                        availableRobotParamDTO.setSubject(labelMap.get(bookGroupDTO.getProLabelId()));
                    }
                    if (null != bookGroupDTO.getDepLabelId() && labelMap.containsKey(bookGroupDTO.getDepLabelId())) {
                        availableRobotParamDTO.setGrade(labelMap.get(bookGroupDTO.getDepLabelId()));
                    }
                }
            }
            availableRobotParamDTO.setRobotType(SelfRobotTypeEnum.version_origin.getCode());
        }
        if (JoinGroupTypeEnum.AI_ROBOT.getCode().equals(bookGroupDTO.getJoinGroupType())){
            Long subLabelId = bookDto.getSubLabelId();
            Long graLabelId = bookDto.getGraLabelId();
            if (subLabelId!=null&&graLabelId!=null){
                Map<Long, BookLabel> bookLabelMap = bookLabelDao.getMapByIds(Arrays.asList(subLabelId, graLabelId));
                if (bookLabelMap.get(graLabelId)!=null){
                    availableRobotParamDTO.setGrade(bookLabelMap.get(graLabelId).getName());
                }
                if (bookLabelMap.get(subLabelId)!=null){
                    availableRobotParamDTO.setSubject(bookLabelMap.get(subLabelId).getName());
                }
            }
            availableRobotParamDTO.setRobotType(SelfRobotTypeEnum.version1.getCode());
        }
        SelfRobotDTO selfRobotDTO = wechatGroupConsr.getAvailableRobotByBookGroup(availableRobotParamDTO);
        if (selfRobotDTO == null) {
            //没有可用机器人返回没有可用机器人
            ownAltQrcodeInfoDTO.setHasUsedRobot(false);
            return ownAltQrcodeInfoDTO;
        }
        ownAltQrcodeInfoDTO.setHasUsedRobot(true);
        ownAltQrcodeInfoDTO.setAltHeadUrl(selfRobotDTO.getHeadPic());
        ownAltQrcodeInfoDTO.setAltId(selfRobotDTO.getWxId());
        ownAltQrcodeInfoDTO.setAltNickName(selfRobotDTO.getNickName());
        ownAltQrcodeInfoDTO.setAltQrcodeUrl(selfRobotDTO.getQrcodeUrl());
        ownAltQrcodeInfoDTO.setAltHeadUrl(selfRobotDTO.getHeadPic());
        ownAltQrcodeInfoDTO.setResourceOpen(selfRobotDTO.getResourceOpen());
        if (selfRobotDTO.getAgentRobot()!=null&&selfRobotDTO.getAgentRobot()) {
            //先查询有没有重复的
            BookGroupAgentRecord old = bookGroupAgentRecordDao.getByAltIdAndBookGroupId(selfRobotDTO.getWxId(), bookGroupId);
            if (old == null) {
                //没有重复的就插入
                BookGroupAgentRecord bookGroupAgentRecord = new BookGroupAgentRecord();
                bookGroupAgentRecord.setBookGroupId(bookGroupId);
                bookGroupAgentRecord.setAgentId(agentId);
                bookGroupAgentRecord.setAdviserId(bookGroupDTO.getCreateUser());
                bookGroupAgentRecord.setAgentName(selfRobotDTO.getAgentName());
                bookGroupAgentRecord.setGrade(selfRobotDTO.getGrade());
                bookGroupAgentRecord.setSubject(selfRobotDTO.getSubject());
                bookGroupAgentRecord.setTarget(selfRobotDTO.getTarget());
                bookGroupAgentRecord.setAltId(selfRobotDTO.getWxId());
                bookGroupAgentRecordDao.insert(bookGroupAgentRecord);
            }
        }
        return ownAltQrcodeInfoDTO;
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("根据分类id获取个人二维码信息")
    @Override
    public OwnAltQrcodeInfoDTO getOwnAltQrcodeInfoDTOByClassifyId(Long wechatUserId, Long classifyId) {
        OwnAltQrcodeInfoDTO ownAltQrcodeInfoDTO = new OwnAltQrcodeInfoDTO();
        //根据分类id查询社群码信息
        ClassifyDTO classifyDTO = bookGroupClassifyDao.getById(classifyId);
        if (classifyDTO == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "没有该分类");
        }
        Long bookId = classifyDTO.getBookId();
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("bookId", bookId);
        paramMap.put("adviserId", classifyDTO.getCreateUser());
        paramMap.put("channelId", classifyDTO.getChannelId());
        BookDto bookDto = bookDao.getById(paramMap);
        Long templetId = bookDto.getTempletId();
        //根据分类id获取大类
        TempletRelevance templetRelevance = templetRelevanceDao.getByTempletId(templetId);
        LOGGER.info("根据分类id获取大类templetRelevance" + templetRelevance.toString());
        Integer largeTemplet = templetRelevance.getLargeTemplet();
        SelfRobotDTO selfRobotDTO = wechatGroupConsr.getAvailableRobot(wechatUserId, largeTemplet, classifyId);
        if (selfRobotDTO == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "未找到机器人!");
        }
        ownAltQrcodeInfoDTO.setAltHeadUrl(selfRobotDTO.getHeadPic());
        ownAltQrcodeInfoDTO.setAltId(selfRobotDTO.getWxId());
        ownAltQrcodeInfoDTO.setAltNickName(selfRobotDTO.getNickName());
        ownAltQrcodeInfoDTO.setAltQrcodeUrl(selfRobotDTO.getQrcodeUrl());
        ownAltQrcodeInfoDTO.setAltHeadUrl(selfRobotDTO.getHeadPic());
        //获取之前是否有没有使用的暗号
        JoinGroupCipher joinGroupCipher = joinGroupCipherDao.getByWechatUserId(wechatUserId, classifyId);
        String cipher;
        if (joinGroupCipher != null) {
            cipher = joinGroupCipher.getCipher();
        } else {
            //新增暗号
            cipher = UUIDUitl.generateShort();
            //查重，如果有重复，再次生成
            JoinGroupCipher joinGroupCipherHas = joinGroupCipherDao.getByCipher(cipher);
            if (joinGroupCipherHas != null) {
                cipher = UUIDUitl.generateShort();
            }
            cipher = "RAYS_" + cipher;
            JoinGroupCipher joinGroupCipherNew = new JoinGroupCipher();
            joinGroupCipherNew.setCipher(cipher);
            joinGroupCipherNew.setWechatUserId(wechatUserId);
            joinGroupCipherNew.setClassifyId(classifyId);
            joinGroupCipherNew.setAltId(selfRobotDTO.getWxId());
            joinGroupCipherNew.setType(CipherTypeEnum.CLASSIFY_CIPHER.code);
            joinGroupCipherDao.insert(joinGroupCipherNew);
        }
        ownAltQrcodeInfoDTO.setCipher(cipher);
        return ownAltQrcodeInfoDTO;
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("根据分类id获取个人二维码信息")
    @Override
    public OwnAltQrcodeInfoDTO getOwnAltQrcodeInfoDTOByQrcodeId(Long wechatUserId, Long qrcodeId) {
        OwnAltQrcodeInfoDTO ownAltQrcodeInfoDTO = new OwnAltQrcodeInfoDTO();
        GroupQrcode groupQrcode = groupQrcodeDao.getById(qrcodeId);
        Long classifyId = groupQrcode.getClassifyId();

        //根据分类id查询社群码信息
        ClassifyDTO classifyDTO = bookGroupClassifyDao.getById(classifyId);
        if (classifyDTO == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "没有该分类");
        }
        Long bookId = classifyDTO.getBookId();
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("bookId", bookId);
        paramMap.put("adviserId", classifyDTO.getCreateUser());
        paramMap.put("channelId", classifyDTO.getChannelId());
        BookDto bookDto = bookDao.getById(paramMap);
        Long templetId = bookDto.getTempletId();
        //根据分类id获取大类
        TempletRelevance templetRelevance = templetRelevanceDao.getByTempletId(templetId);
        LOGGER.info("根据分类id获取大类templetRelevance" + templetRelevance.toString());
        Integer largeTemplet = templetRelevance.getLargeTemplet();
        SelfRobotDTO selfRobotDTO = wechatGroupConsr.getAvailableRobot(wechatUserId, largeTemplet, classifyId);
        if (selfRobotDTO == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "未找到机器人!");
        }
        ownAltQrcodeInfoDTO.setAltHeadUrl(selfRobotDTO.getHeadPic());
        ownAltQrcodeInfoDTO.setAltId(selfRobotDTO.getWxId());
        ownAltQrcodeInfoDTO.setAltNickName(selfRobotDTO.getNickName());
        ownAltQrcodeInfoDTO.setAltQrcodeUrl(selfRobotDTO.getQrcodeUrl());
        ownAltQrcodeInfoDTO.setAltHeadUrl(selfRobotDTO.getHeadPic());
        //获取之前是否有没有使用的暗号
        JoinGroupCipher joinGroupCipher = joinGroupCipherDao.getByWechatUserIdAndQrcodeId(wechatUserId, qrcodeId, CipherTypeEnum.QRCODE_CIPHER.code);
        String cipher;
        if (joinGroupCipher != null) {
            cipher = joinGroupCipher.getCipher();
        } else {
            //新增暗号
            cipher = UUIDUitl.generateShort();
            //查重，如果有重复，再次生成
            JoinGroupCipher joinGroupCipherHas = joinGroupCipherDao.getByCipher(cipher);
            if (joinGroupCipherHas != null) {
                cipher = UUIDUitl.generateShort();
            }
            cipher = "RAYS_" + cipher;
            JoinGroupCipher joinGroupCipherNew = new JoinGroupCipher();
            joinGroupCipherNew.setCipher(cipher);
            joinGroupCipherNew.setWechatUserId(wechatUserId);
            joinGroupCipherNew.setClassifyId(classifyId);
            joinGroupCipherNew.setAltId(selfRobotDTO.getWxId());
            joinGroupCipherNew.setQrcodeId(qrcodeId);
            joinGroupCipherNew.setType(CipherTypeEnum.QRCODE_CIPHER.code);
            joinGroupCipherDao.insert(joinGroupCipherNew);
        }
        ownAltQrcodeInfoDTO.setCipher(cipher);
        return ownAltQrcodeInfoDTO;
    }

    @ParamLog("获取暗号状态")
    @Override
    public Integer getCipherState(String cipher) {
        Integer state;
        if (StringUtil.isEmpty(cipher)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空！");
        }
        JoinGroupCipher joinGroupCipher = joinGroupCipherDao.getByCipher(cipher);
        if (joinGroupCipher == null) {
            //暗号错误
            state = 2;
        } else if (joinGroupCipher.getHasUsed() != null && joinGroupCipher.getHasUsed()) {
            //已使用
            state = 1;
        } else {
            //未使用
            state = 0;
        }
        return state;
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("获取暗号状态为已使用")
    @Override
    public void updateCipherStateToUsed(String cipher, String wxId) {
        if (StringUtil.isEmpty(cipher) || StringUtil.isEmpty(wxId)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空！");
        }
        joinGroupCipherDao.updateCipherStateToUsed(cipher,wxId);
    }

    @ParamLog("获取个人二维码方式群已使用和未使用数量")
    @Override
    public GroupUseDTO getGroupUse(List<String> altIds) {
            if (ListUtils.isEmpty(altIds)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空！");
        }
        GroupUseDTO groupUseDTO = new GroupUseDTO();
        Integer notUsed = weixinQrcodeDao.countByState(0, altIds);
        Integer hasUsed = weixinQrcodeDao.countByState(1, altIds);
        Integer full = weixinQrcodeDao.countByState(2, altIds);
        groupUseDTO.setHasUsed(hasUsed + full);
        groupUseDTO.setNotUsed(notUsed);
        return groupUseDTO;
    }

    @ParamLog("获取所有的大类分类")
    @Override
    public List<LargeTempletDTO> getAllLargTemplet() {
        List<LargeTempletDTO> list = new ArrayList<>();
        for (LargeTempletEnum largeTempletEnum : LargeTempletEnum.values()) {
            LargeTempletDTO largeTempletDTO = new LargeTempletDTO();
            largeTempletDTO.setLargeTemplet(largeTempletEnum.code);
            largeTempletDTO.setName(largeTempletEnum.name);
            list.add(largeTempletDTO);
        }
        return list;
    }

    @ParamLog("根据微信id和机器人id获取分类集合")
    @Override
    public List<JoinGroupCipherDTO> getClassifyIdsByWxIdAndAltId(String wxId, String altId) {
        if (StringUtil.isEmpty(wxId) || StringUtil.isEmpty(altId)) {
            return new ArrayList<>();
        }
        List<JoinGroupCipherDTO> list = joinGroupCipherDao.getClassifyIdsByWxIdAndAltId(wxId, altId);
        return CollectionUtils.isEmpty(list) ? Lists.newArrayList() : list;
    }

    @ParamLog("获取暗号基本信息")
    @Override
    public GroupCipherDTO getJoinGroupCipher(String cipher) {
        if (StringUtil.isEmpty(cipher)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空！");
        }
        JoinGroupCipher joinGroupCipher = joinGroupCipherDao.getByCipher(cipher);
        if (joinGroupCipher != null) {
            GroupCipherDTO groupCipherDTO = new GroupCipherDTO();
            BeanUtils.copyProperties(joinGroupCipher, groupCipherDTO);
            return groupCipherDTO;
        }
        return null;
    }

    @ParamLog("为信息流批量获取社群书基本信息")
    @Override
    public Map<Long, StoreFlowInfoDto> getFlowInfoByBookGroupIds(List<Long> bookGroupIds) {
        Map<Long, StoreFlowInfoDto> result = new HashMap<>();
        if (ListUtils.isEmpty(bookGroupIds)) {
            return null;
        }
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("bookGroupIds", bookGroupIds);
        List<Object> listBook4ChannelVOS = bookDao.listBy(paramMap, "getBookGroupInfo4Channel");
        if(ListUtils.isEmpty(bookGroupIds)){
            return new HashMap<>();
        }
        Map<Long, BookGroupStatisticDTO> statisMap = bookGroupClassifyBiz.getBookGroupStatistic(bookGroupIds);
        listBook4ChannelVOS.forEach( e ->{
            ListBook4ChannelVO listBook4ChannelVO = (ListBook4ChannelVO) e;
            StoreFlowInfoDto storeFlowInfoDto = new StoreFlowInfoDto();
            storeFlowInfoDto.setOriginId(listBook4ChannelVO.getBookGroupId());
            storeFlowInfoDto.setOriginType(StoreCons.OriginTypeEnum.BOOK_GROUP.getCode());
            storeFlowInfoDto.setCoverImg(listBook4ChannelVO.getCoverImg());
            storeFlowInfoDto.setTitle(listBook4ChannelVO.getBookName());
            if (!MapUtils.isEmpty(statisMap) && statisMap.containsKey(listBook4ChannelVO.getBookGroupId())) {
                BookGroupStatisticDTO dto = statisMap.get(listBook4ChannelVO.getBookGroupId());
                storeFlowInfoDto.setResourceNum(null != dto.getClassifyCount() ? dto.getClassifyCount() : 0);
                storeFlowInfoDto.setResourceItemNum(null != dto.getUserNumber() ? dto.getUserNumber() : 0);
            }else {
                storeFlowInfoDto.setResourceNum(0);
                storeFlowInfoDto.setResourceItemNum(0);
            }
            result.put(listBook4ChannelVO.getBookGroupId(), storeFlowInfoDto);
        });
        return result;
    }

    @ParamLog("获取指定条数社群书基本信息")
    @Override
    public Map<Long, StoreFlowInfoDto> getBookGroupInfoByChannelId(Long channelId, Integer itemNum) {
        Map<Long, StoreFlowInfoDto> result = new HashMap<>();
        PageParam pageParam = new PageParam(0, itemNum);
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("channelId", channelId);
        PageBean listBookGroup4Channel = bookDao.listPage(pageParam, paramMap, "listBookGroup4Channel");
        List<Long> bookGroupIds = new ArrayList<>();
        listBookGroup4Channel.getRecordList().forEach(e -> {
            ListBook4ChannelVO listBook4ChannelVO = (ListBook4ChannelVO) e;
            bookGroupIds.add(listBook4ChannelVO.getBookGroupId());
        });
        if(ListUtils.isEmpty(bookGroupIds)){
            return new HashMap<>();
        }
        Map<Long, BookGroupStatisticDTO> statisMap = bookGroupClassifyBiz.getBookGroupStatistic(bookGroupIds);
        listBookGroup4Channel.getRecordList().forEach( e ->{
            ListBook4ChannelVO listBook4ChannelVO = (ListBook4ChannelVO) e;
            StoreFlowInfoDto storeFlowInfoDto = new StoreFlowInfoDto();
            storeFlowInfoDto.setOriginId(listBook4ChannelVO.getBookGroupId());
            storeFlowInfoDto.setOriginType(StoreCons.OriginTypeEnum.BOOK_GROUP.getCode());
            storeFlowInfoDto.setCoverImg(listBook4ChannelVO.getCoverImg());
            storeFlowInfoDto.setTitle(listBook4ChannelVO.getBookName());
            if (!MapUtils.isEmpty(statisMap) && statisMap.containsKey(listBook4ChannelVO.getBookGroupId())) {
                BookGroupStatisticDTO dto = statisMap.get(listBook4ChannelVO.getBookGroupId());
                storeFlowInfoDto.setResourceNum(null != dto.getClassifyCount() ? dto.getClassifyCount() : 0);
                storeFlowInfoDto.setResourceItemNum(null != dto.getUserNumber() ? dto.getUserNumber() : 0);
            }else {
                storeFlowInfoDto.setResourceNum(0);
                storeFlowInfoDto.setResourceItemNum(0);
            }
            result.put(listBook4ChannelVO.getBookGroupId(), storeFlowInfoDto);
        });
        return result;
    }


    @Override
    @ParamLog("知识商城获取社群书信息")
    public PageBeanNew<StoreFlowInfoDto> listBookGroup4KnowledgeMall(Long channelId, int currentPage, int numPerPage) {
        List<StoreFlowInfoDto> results = new ArrayList<>();
        PageParam pageParam = new PageParam(currentPage, numPerPage);
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("channelId", channelId);
        PageBeanNew<ListBook4ChannelVO> resultInfos = bookDao.listPageNew(pageParam, paramMap, "listBookGroup4Channel");
        List<Long> bookGroupIds = resultInfos.getRecordList().stream().map(ListBook4ChannelVO::getBookGroupId).collect(Collectors.toList());
        if(ListUtils.isEmpty(bookGroupIds)){
            return new PageBeanNew(currentPage, numPerPage, 0, new ArrayList<>());
        }
        Map<Long, BookGroupStatisticDTO> statisMap = bookGroupClassifyBiz.getBookGroupStatistic(bookGroupIds);
        for (ListBook4ChannelVO listBook4ChannelVO : resultInfos.getRecordList()) {
            StoreFlowInfoDto storeFlowInfoDto = new StoreFlowInfoDto();
            storeFlowInfoDto.setOriginId(listBook4ChannelVO.getBookGroupId());
            storeFlowInfoDto.setOriginType(StoreCons.OriginTypeEnum.BOOK_GROUP.getCode());
            storeFlowInfoDto.setCoverImg(listBook4ChannelVO.getCoverImg());
            storeFlowInfoDto.setTitle(listBook4ChannelVO.getBookName());
            if (!MapUtils.isEmpty(statisMap) && statisMap.containsKey(listBook4ChannelVO.getBookGroupId())) {
                BookGroupStatisticDTO dto = statisMap.get(listBook4ChannelVO.getBookGroupId());
                storeFlowInfoDto.setResourceNum(null != dto.getClassifyCount() ? dto.getClassifyCount() : 0);
                storeFlowInfoDto.setResourceItemNum(null != dto.getUserNumber() ? dto.getUserNumber() : 0);
            } else {
                storeFlowInfoDto.setResourceNum(0);
                storeFlowInfoDto.setResourceItemNum(0);
            }
            results.add(storeFlowInfoDto);
        }
        return new PageBeanNew<>(currentPage, numPerPage, resultInfos.getTotalCount(), results);
    }

    @ParamLog("获取用户购买或者参与过的社群书信息")
    @Override
    public PageBeanNew<GroupStoreMyPayDto> getUserBrowseGroup4KnowLedgeMall(Long channelId, Long wechatUserId, Integer currentPage, Integer numPerPage) {
        List<GroupStoreMyPayDto> results = new ArrayList<>();
        PageParam pageParam = new PageParam(currentPage, numPerPage);
        List<Long> bookGroupIds = Lists.newArrayList();
        bookGroupIds = tradeConsr.getBuyBookGroupIdList(channelId, wechatUserId);
        Map<String, Object> paramMap = new HashMap<>();
        if(ListUtils.isEmpty(bookGroupIds)){
            return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
        }
        paramMap.put("bookGroupIds", bookGroupIds);
        PageBeanNew<ListBook4ChannelVO> resultInfos = bookDao.listPageNew(pageParam, paramMap, "getBookGroupInfo4Channel");
        List<Long> groupIds = resultInfos.getRecordList().stream().map(ListBook4ChannelVO::getBookGroupId).collect(Collectors.toList());
        if(ListUtils.isEmpty(bookGroupIds)){
            return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
        }
        Map<Long, BookGroupStatisticDTO> statisMap = bookGroupClassifyDao.getClassifyCountAbout(groupIds);
        for (ListBook4ChannelVO listBook4ChannelVO : resultInfos.getRecordList()) {
            GroupStoreMyPayDto groupStoreMyPayDto = new GroupStoreMyPayDto();
            groupStoreMyPayDto.setOriginId(listBook4ChannelVO.getBookGroupId());
            groupStoreMyPayDto.setOriginType(StoreCons.OriginTypeEnum.BOOK_GROUP.getCode());
            groupStoreMyPayDto.setCoverImg(listBook4ChannelVO.getCoverImg());
            groupStoreMyPayDto.setOriginName(listBook4ChannelVO.getBookName());
            if (!MapUtils.isEmpty(statisMap) && statisMap.containsKey(listBook4ChannelVO.getBookGroupId())) {
                BookGroupStatisticDTO dto = statisMap.get(listBook4ChannelVO.getBookGroupId());
                groupStoreMyPayDto.setResourceNum(null != dto.getClassifyCount() ? dto.getClassifyCount() : 0);
                groupStoreMyPayDto.setResourceItemNum(null != dto.getUserNumber() ? dto.getUserNumber() : 0);
            } else {
                groupStoreMyPayDto.setResourceNum(0);
                groupStoreMyPayDto.setResourceItemNum(0);
            }
            results.add(groupStoreMyPayDto);
        }
        return new PageBeanNew<>(currentPage, numPerPage, resultInfos.getTotalCount(), results);
    }


    @Override
    public BookGroupStatisticsDTO getBookGroupStatisByBookGroupId(Long bookGroupId) {
        Map<Long, BookGroupStatisticDTO> bookGroupStatisticMap = bookGroupClassifyDao.getClassifyCountAbout(Arrays.asList(bookGroupId));
        BookGroupStatisticsDTO bookGroupStatisticsDTO = new BookGroupStatisticsDTO();
        Long appCount = appTouchRecordDao.getCountByBokkGroupId(bookGroupId, "APP");
        Long productCount = appTouchRecordDao.getCountByBokkGroupId(bookGroupId, "PRODUCT");
        if (MapUtils.isEmpty(bookGroupStatisticMap)){
            bookGroupStatisticsDTO.setClassifyCount(0L);
            bookGroupStatisticsDTO.setGroupPersonNum(0L);
            bookGroupStatisticsDTO.setWxGroupCount(0L);
            bookGroupStatisticsDTO.setPromAppCount(appCount);
            bookGroupStatisticsDTO.setPromProductCount(productCount);
            return bookGroupStatisticsDTO;
        }
        bookGroupStatisticsDTO.setClassifyCount(bookGroupStatisticMap.get(bookGroupId).getClassifyCount().longValue());
        bookGroupStatisticsDTO.setGroupPersonNum(bookGroupStatisticMap.get(bookGroupId).getUserNumber().longValue());
        bookGroupStatisticsDTO.setWxGroupCount(bookGroupStatisticMap.get(bookGroupId).getGroupNumber().longValue());
        bookGroupStatisticsDTO.setPromAppCount(appCount);
        bookGroupStatisticsDTO.setPromProductCount(productCount);
        return bookGroupStatisticsDTO;
    }

    @Override
    public PageBeanNew<ResourcesStatisticVO> getGroupIncomeStatic(GroupIncomeStaticParamVO groupIncomeStaticParamVO, Long adviserId) {
        Long bookGroupId = groupIncomeStaticParamVO.getBookGroupId();
        Integer currentPage = groupIncomeStaticParamVO.getCurrentPage();
        Integer numPerPage = groupIncomeStaticParamVO.getNumPerPage();
        String type = groupIncomeStaticParamVO.getType();
        Long classifyId = groupIncomeStaticParamVO.getClassifyId();
        Long wxGroupId = groupIncomeStaticParamVO.getWxGroupId();
        if (currentPage==null||currentPage<0||numPerPage==null||numPerPage<=0){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"分页参数错误！");
        }
        if (bookGroupId==null){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"社群码id不能为空！");
        }
        if (type==null){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"类型不能为空");
        }
        PageParam pageParam = new PageParam(currentPage, numPerPage);
        Map<String, Object> map = new HashMap<>();
        map.put("bookGroupId", bookGroupId);
        map.put("type", type);
        if (null != classifyId){
            map.put("classifyId", classifyId);
        }
        if (null != wxGroupId){
            map.put("qrcodeId", wxGroupId);
        }
        PageBeanNew<ResourcesStatisticVO> pageBeanNew = appClickRecordDao.listPageNew(pageParam, map, "getClickStatistics");
        List<ResourcesStatisticVO> recordList = pageBeanNew.getRecordList();
        if (ListUtils.isEmpty(recordList)){
            return pageBeanNew;
        }
        //填充数据
        setInfo(recordList,bookGroupId,classifyId,wxGroupId,type,adviserId);
        return pageBeanNew;
    }

    void setInfo(List<ResourcesStatisticVO> recordList,Long bookGroupId,Long classifyId, Long qrcodeId, String type,Long partyId){
        List<Long> rescourceIds = recordList.stream().map(ResourcesStatisticVO::getRescourceId).collect(Collectors.toList());
//        map.put("rescourceIds",rescourceIds);
        GroupRescourceIncomeParamDTO groupRescourceIncomeParamDTO = new GroupRescourceIncomeParamDTO();
        groupRescourceIncomeParamDTO.setBookGroupId(bookGroupId);
        groupRescourceIncomeParamDTO.setClassifyId(classifyId);
        groupRescourceIncomeParamDTO.setQrcodeId(qrcodeId);
        groupRescourceIncomeParamDTO.setType(type);
        groupRescourceIncomeParamDTO.setRescourceIds(rescourceIds);
        groupRescourceIncomeParamDTO.setRoleId(5L);
        groupRescourceIncomeParamDTO.setPartyId(partyId);
        Map<Long, BigDecimal> rescourceIncome = bookConsr.getRescourceIncome(groupRescourceIncomeParamDTO);
        GroupIncomeSearchDto groupIncomeSearchDto = new GroupIncomeSearchDto();
        groupIncomeSearchDto.setBookGroupId(bookGroupId);
        groupIncomeSearchDto.setClassifyId(classifyId);
        groupIncomeSearchDto.setIds(rescourceIds);
        groupIncomeSearchDto.setQrcodeId(qrcodeId);
        groupIncomeSearchDto.setTypeCode(type);
        Map<Long, GroupMoneyDto> saleDetail4Group = tradeConsr.getSaleDetail4Group(groupIncomeSearchDto);
        Map<Long, AppDto> appDtoMap;
        Map<Long, ProductDto> productDtoMap;
        if ("APP".equals(type)){
            appDtoMap = appConsr.mapByIds(rescourceIds);
            recordList.forEach(e ->{
                if (!MapUtils.isEmpty(appDtoMap) && null != appDtoMap.get(e.getRescourceId())){
                    e.setRescourceName(appDtoMap.get(e.getRescourceId()).getTitle());
                }
                if (!MapUtils.isEmpty(saleDetail4Group) && null != saleDetail4Group.get(e.getRescourceId())){
                    e.setSaleCount(saleDetail4Group.get(e.getRescourceId()).getSaleCount());
                    e.setTotalSale(new BigDecimal(saleDetail4Group.get(e.getRescourceId()).getSaleMoney()));
                }else {
                    e.setSaleCount(0L);
                    e.setTotalSale(BigDecimal.ZERO);
                }
                e.setType("APP");
                if (null == rescourceIncome.get(e.getRescourceId())){
                    e.setTotalIncome(BigDecimal.ZERO);
                }else {
                    e.setTotalIncome(rescourceIncome.get(e.getRescourceId()));
                }
            });
        }else {
            productDtoMap = productConsr.getProBasesByIds(rescourceIds);
            recordList.forEach(e ->{
                if (!MapUtils.isEmpty(productDtoMap) && null != productDtoMap.get(e.getRescourceId())){
                    e.setRescourceName(productDtoMap.get(e.getRescourceId()).getProductName());
                }
                e.setType("PRODUCT");
                if (null == rescourceIncome.get(e.getRescourceId())){
                    e.setTotalIncome(BigDecimal.ZERO);
                }else {
                    e.setTotalIncome(rescourceIncome.get(e.getRescourceId()));
                }
                if (!MapUtils.isEmpty(saleDetail4Group) && null != saleDetail4Group.get(e.getRescourceId())){
                    e.setSaleCount(saleDetail4Group.get(e.getRescourceId()).getSaleCount());
                    e.setTotalSale(new BigDecimal(saleDetail4Group.get(e.getRescourceId()).getSaleMoney()));
                }else {
                    e.setSaleCount(0L);
                    e.setTotalSale(BigDecimal.ZERO);
                }
            });
        }
    }

    @Override
    public List<GroupScanTrendVO> getGroupScanTrend(GroupScanTrendParamVO groupScanTrendParamVO, Long adviserId) {
        Integer dayNum = groupScanTrendParamVO.getDayNum();
        if (dayNum == null) {
            groupScanTrendParamVO.setDayNum(30);
            dayNum = 30;
        }
        Date startDate = groupScanTrendParamVO.getStartDate();
        Date endDate = groupScanTrendParamVO.getEndDate();
        Long bookGroupId = groupScanTrendParamVO.getBookGroupId();
        Long classifyId = groupScanTrendParamVO.getClassifyId();
        Long wxGroupId = groupScanTrendParamVO.getWxGroupId();
        List<Date> dateList = settlementConsr.getDateList(dayNum, startDate, endDate);
        List<GroupScanTrendVO> groupScanTrendVOS = appClickRecordDao.getClickTrend(groupScanTrendParamVO);
        List<Date> collect = groupScanTrendVOS.stream().map(GroupScanTrendVO::getDate).collect(Collectors.toList());
        List<ClassifyPayDetailDto> groupBuyCount = tradeConsr.getGroupBuyCount(bookGroupId, classifyId, wxGroupId, startDate, endDate);
        List<String> tradeDate = groupBuyCount.stream().map(ClassifyPayDetailDto::getDivideDate).collect(Collectors.toList());
        if (dateList.size() > groupScanTrendVOS.size()) {
            dateList.forEach(e -> {
                if (!collect.contains(e)) {
                    GroupScanTrendVO groupScanTrendVO = new GroupScanTrendVO();
                    groupScanTrendVO.setDate(e);
                    groupScanTrendVO.setScanCount(0L);
                    groupScanTrendVOS.add(groupScanTrendVO);
                }
            });
        }
        if (ListUtils.isEmpty(groupBuyCount)){
            groupScanTrendVOS.forEach( e -> e.setBuyCount(0L));
        }else {
            groupScanTrendVOS.forEach(e -> {
                for (ClassifyPayDetailDto classifyPayDetailDto : groupBuyCount) {
                    if (DateUtils.formatDate(e.getDate()).equals(classifyPayDetailDto.getDivideDate())) {
                        e.setBuyCount(classifyPayDetailDto.getBuyCount());
                    } else {
                        e.setBuyCount(0L);
                    }
                }
            });
        }

        return groupScanTrendVOS;
    }

    @Override
    public PageBeanNew<GroupStatisticVO> getClassifyStatistic(Long bookGroupId, Long adviserId, Integer currentPage, Integer numPerPage) {
        PageParam pageParam = new PageParam(currentPage,numPerPage);
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("bookGroupId",bookGroupId);
        PageBeanNew<GroupStatisticVO> pageClassify = bookGroupClassifyDao.listPageNew(pageParam, paramMap, "pageClassify");
        List<GroupStatisticVO> recordList = pageClassify.getRecordList();
        if (ListUtils.isEmpty(recordList)){
            return new PageBeanNew<>();
        }
        List<Long> classifyIds = recordList.stream().map(GroupStatisticVO::getClassifyId).collect(Collectors.toList());
        if (ListUtils.isEmpty(classifyIds)){
            return new PageBeanNew<>();
        }
        Map<Long, ClickClassifyDTO> longClickClassifyDTOMap = bookGroupClassifyDao.mapClickClassify(classifyIds);
        GetGroupClassifyIncomeDTO getGroupClassifyIncomeDTO = new GetGroupClassifyIncomeDTO();
        getGroupClassifyIncomeDTO.setClassifyIds(classifyIds);
        getGroupClassifyIncomeDTO.setPartyId(adviserId);
        getGroupClassifyIncomeDTO.setRoleId(5L);
        Map<Long, BigDecimal> classifyIncome = bookConsr.getClassifyIncome(getGroupClassifyIncomeDTO);
        Map<Long, Long> mapMemberCount = wechatGroupConsr.getclassifyMemberCount(classifyIds);
        recordList.forEach(e ->{

            if (longClickClassifyDTOMap.get(e.getClassifyId()) != null){
                Long count = longClickClassifyDTOMap.get(e.getClassifyId()).getCount()==null?0L:longClickClassifyDTOMap.get(e.getClassifyId()).getCount();
                e.setClickCount(count);
            }
            if (BigDecimal.ZERO.compareTo(e.getPrice()) ==0){
                e.setIsFree(1);
            }else {
                e.setIsFree(0);
            }
            if (!MapUtils.isEmpty(classifyIncome)){
                e.setIncome(classifyIncome.get(e.getClassifyId()));
            }else {
                e.setIncome(BigDecimal.ZERO);
            }
            if (!MapUtils.isEmpty(mapMemberCount)){
                e.setInGroupPersonCount(mapMemberCount.get(e.getClassifyId()));
            }else {
                e.setInGroupPersonCount(0L);
            }
        });
        return pageClassify;
    }

    @Override
    public List<WxGroupStatisticVO> getQrcodeStatistic(Long bookGroupId, Long classifyId, Long adviserId) {
        List<ClassifyQrcodeVO> qrcodeByClassify = groupQrcodeBiz.getQrcodeByClassify(bookGroupId, classifyId);
        if (ListUtils.isEmpty(qrcodeByClassify)){
            return new ArrayList<>();
        }
        List<Long> qrcodeIds = qrcodeByClassify.stream().map(ClassifyQrcodeVO::getId).collect(Collectors.toList());
        List<String> wxGroupIds = qrcodeByClassify.stream().map(ClassifyQrcodeVO::getWeixinGroupId).collect(Collectors.toList());
        GetGroupQrcodeIncomeDTO getGroupQrcodeIncomeDTO = new GetGroupQrcodeIncomeDTO();
        getGroupQrcodeIncomeDTO.setRoleId(5L);
        getGroupQrcodeIncomeDTO.setQrcodeIds(qrcodeIds);
        getGroupQrcodeIncomeDTO.setPartyId(adviserId);
        Map<Long, BigDecimal> qrcodeIncome = bookConsr.getQrcodeIncome(getGroupQrcodeIncomeDTO);
        Map<String, GroupMemberStatisDTO> groupMemberStatisDTOMap = wechatGroupConsr.listGroupMemberStatisInfo(wxGroupIds);
        List<WxGroupStatisticVO> wxGroupStatisticVOS = new ArrayList<>();
        qrcodeByClassify.forEach(e ->{
            WxGroupStatisticVO wxGroupStatisticVO = new WxGroupStatisticVO();
            wxGroupStatisticVO.setCreatedTime(e.getCreatedTime());
            wxGroupStatisticVO.setGroupPersonCount(e.getUserNumber().longValue());
            if (MapUtils.isEmpty(qrcodeIncome)){
                wxGroupStatisticVO.setIncome(BigDecimal.ZERO);
            }else {
                wxGroupStatisticVO.setIncome(qrcodeIncome.get(e.getId()));
            }
            if (MapUtils.isEmpty(groupMemberStatisDTOMap)){
                wxGroupStatisticVO.setInGroupPersonCount(0L);
            }else {
                wxGroupStatisticVO.setInGroupPersonCount(groupMemberStatisDTOMap.get(e.getWeixinGroupId()).getJoinCount().longValue());
            }
            wxGroupStatisticVO.setQrcodeId(e.getId());
            wxGroupStatisticVO.setWxGroupName(e.getGroupName());
            wxGroupStatisticVOS.add(wxGroupStatisticVO);
        });

        return wxGroupStatisticVOS;
    }

    @Override
    public TotalRescourceDataVO getTotalRescourceData(Long bookGroupId, Long adviserId, Long classifyId, Long qrcodeId, String type) {
        TotalRescourceDataVO totalRescourceDataVO = new TotalRescourceDataVO();
        List<Long> rescourceIds = appClickRecordDao.getRescourceIds(bookGroupId, classifyId, qrcodeId, type);
        Long rescourceTotalClick = appClickRecordDao.getRescourceTotalClick(bookGroupId, classifyId, qrcodeId, type);
        totalRescourceDataVO.setClickCount(rescourceTotalClick == null?0L:rescourceTotalClick);
        GroupRescourceIncomeParamDTO groupRescourceIncomeParamDTO = new GroupRescourceIncomeParamDTO();
        groupRescourceIncomeParamDTO.setBookGroupId(bookGroupId);
        groupRescourceIncomeParamDTO.setClassifyId(classifyId);
        groupRescourceIncomeParamDTO.setQrcodeId(qrcodeId);
        groupRescourceIncomeParamDTO.setType(type);
        groupRescourceIncomeParamDTO.setRescourceIds(rescourceIds);
        groupRescourceIncomeParamDTO.setPartyId(adviserId);
        groupRescourceIncomeParamDTO.setRoleId(5L);
        BigDecimal rescourceTotalIncome = bookConsr.getRescourceTotalIncome(groupRescourceIncomeParamDTO);
        totalRescourceDataVO.setTotalIncome(rescourceTotalIncome == null?BigDecimal.ZERO:rescourceTotalIncome);
        BigDecimal totalSale = tradeConsr.getTotalSale(bookGroupId, classifyId, qrcodeId, type);
        totalRescourceDataVO.setTotalSale(totalSale);
        return totalRescourceDataVO;
    }

    @Override
    public Map<String, String> exportRescourceIncomeData(Long bookGroupId, Long adviserId) {
        List<StatisticsIncomeDto> appStatisticsIncomeDtos = new ArrayList<>();
        List<StatisticsIncomeDto> productStatisticsIncomeDtos = new ArrayList<>();
        List<ResourcesStatisticVO> appClickStatistics = appClickRecordDao.getClickStatistics(bookGroupId, null, null, "APP");
        List<ResourcesStatisticVO> productClickStatistics = appClickRecordDao.getClickStatistics(bookGroupId, null, null, "PRODUCT");
        if (!ListUtils.isEmpty(appClickStatistics)){
            setInfo(appClickStatistics, bookGroupId, null, null, "APP", adviserId);
            //获取挂在应用下的商品信息
            ProductStaticUnderAppMapDTO productStaticUnderAppMapDTO = new ProductStaticUnderAppMapDTO();
            productStaticUnderAppMapDTO.setBookGroupId(bookGroupId);
            productStaticUnderAppMapDTO.setAppIds(appClickStatistics.stream().map(ResourcesStatisticVO::getRescourceId).collect(Collectors.toList()));
            productStaticUnderAppMapDTO.setPartyId(adviserId);
            productStaticUnderAppMapDTO.setRoleId(5L);
//            Map<Long, List<com.pcloud.settlementcenter.record.dto.ResourcesStatisticVO>> productStaticUnderApp = settlementConsr.getProductStaticUnderApp(productStaticUnderAppMapDTO);
//            Map<Long, List<StatisticsIncomeDto>> productStaticUnderAppMap = copy(productStaticUnderApp,bookGroupId);
            appClickStatistics.forEach(e ->{
                StatisticsIncomeDto statisticsIncomeDto = new StatisticsIncomeDto();
                statisticsIncomeDto.setAppId(e.getRescourceId());
                statisticsIncomeDto.setBookGroupId(bookGroupId);
                statisticsIncomeDto.setIncome(e.getTotalIncome());
                statisticsIncomeDto.setAppName(e.getRescourceName());
                statisticsIncomeDto.setSaleCounts(e.getSaleCount().intValue());
                statisticsIncomeDto.setSaleMoney(e.getTotalSale());
                statisticsIncomeDto.setScanCounts(e.getBrowseCount().intValue());
//                statisticsIncomeDto.setItemList(productStaticUnderAppMap.get(e.getRescourceId()));
                appStatisticsIncomeDtos.add(statisticsIncomeDto);
            });

        }
        if (!ListUtils.isEmpty(productClickStatistics)){
            setInfo(productClickStatistics, bookGroupId, null, null, "PRODUCT", adviserId);
            productClickStatistics.forEach(e ->{
                StatisticsIncomeDto statisticsIncomeDto = new StatisticsIncomeDto();
                statisticsIncomeDto.setProductId(e.getRescourceId());
                statisticsIncomeDto.setBookGroupId(bookGroupId);
                statisticsIncomeDto.setIncome(e.getTotalIncome());
                statisticsIncomeDto.setProductName(e.getRescourceName());
                statisticsIncomeDto.setSaleCounts(e.getSaleCount().intValue());
                statisticsIncomeDto.setSaleMoney(e.getTotalSale());
                statisticsIncomeDto.setScanCounts(e.getBrowseCount().intValue());
                productStatisticsIncomeDtos.add(statisticsIncomeDto);
            });
        }

        TotalRescourceDataVO appTotalRescourceData = getTotalRescourceData(bookGroupId, null, null, null, "APP");
        StatisticsIncomeDto appSumStatistics = setResourceSumStatistics(appTotalRescourceData);
        TotalRescourceDataVO productTotalRescourceData = getTotalRescourceData(bookGroupId, null, null, null, "PRODUCT");
        StatisticsIncomeDto productSumStatistics = setResourceSumStatistics(productTotalRescourceData);
        Map<String, Object> dataMap = new HashMap<>();
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
        if (bookGroupDTO == null){
            bookGroupDTO = new BookGroupDTO();
        }
        String groupQrcodeName = bookGroupDTO.getGroupQrcodeName()== null?" ":bookGroupDTO.getGroupQrcodeName();
        String title = "社群码" + groupQrcodeName + "的收益列表";
        dataMap.put("appIncomeList", appStatisticsIncomeDtos);
        dataMap.put("productIncomeList", productStatisticsIncomeDtos);
        dataMap.put("title", title);
        dataMap.put("appSumStatistics", appSumStatistics);
        dataMap.put("productSumStatistics", productSumStatistics);
        String today = DateUtils.formatDate(DateUtils.nowTimeStamp(), DateUtils.DATE_FORMAT_DATEONLY);
        String fileName = title+ "-" + today;
        String filePath;
        try {
            filePath = ExcelExportor.uploadExcel(this.getClass(), dataMap, "template_bookGroupStatistics.ftl");
            LOGGER.info("生成Excel【END】" + filePath);
        } catch (Exception e) {
            LOGGER.error("生成Excel异常+++" + e.getMessage(), e);
            throw new BookBizException(BookBizException.ERROR, "导出失败，请联系管理员");
        }
        Map<String, String> resultMap = new HashMap<>();
        resultMap.put("fileName", fileName);
        resultMap.put("fileUrl", filePath);

        return resultMap;
    }

    private StatisticsIncomeDto setResourceSumStatistics(TotalRescourceDataVO totalRescourceDataVO){
        if (totalRescourceDataVO == null){
            return new StatisticsIncomeDto();
        }
        Long clickCount = totalRescourceDataVO.getClickCount();
        BigDecimal totalIncome = totalRescourceDataVO.getTotalIncome();
        BigDecimal totalSale = totalRescourceDataVO.getTotalSale();
        StatisticsIncomeDto statisticsIncomeDto = new StatisticsIncomeDto();
        statisticsIncomeDto.setScanCounts(clickCount.intValue());
        statisticsIncomeDto.setIncome(totalIncome);
        statisticsIncomeDto.setSaleMoney(totalSale);
        return statisticsIncomeDto;
    }

    private Map<Long, List<StatisticsIncomeDto>> copy(Map<Long, List<com.pcloud.settlementcenter.record.dto.ResourcesStatisticVO>> productStaticUnderApp,Long bookGroupId){
        Map<Long, List<StatisticsIncomeDto>> productStaticUnderAppMap = new HashMap<>();
        if (MapUtils.isEmpty(productStaticUnderApp)){
            return productStaticUnderAppMap;
        }
        List<StatisticsIncomeDto> productStatisticsIncomeDtos = new ArrayList<>();
        productStaticUnderApp.forEach((k,v) ->{
            v.forEach(e ->{
                StatisticsIncomeDto statisticsIncomeDto = new StatisticsIncomeDto();
                statisticsIncomeDto.setProductId(e.getRescourceId());
                statisticsIncomeDto.setIncome(e.getTotalIncome());
                statisticsIncomeDto.setProductName(e.getRescourceName());
                statisticsIncomeDto.setSaleCounts(e.getSaleCount() == null ? 0 : e.getSaleCount().intValue());
                statisticsIncomeDto.setSaleMoney(e.getTotalSale());
                statisticsIncomeDto.setScanCounts(e.getBrowseCount() == null? 0 :e.getBrowseCount().intValue());
                productStatisticsIncomeDtos.add(statisticsIncomeDto);
            });
            productStaticUnderAppMap.put(k,productStatisticsIncomeDtos);
        });
        return productStaticUnderAppMap;
    }

    @Override
    public Map<Long, Long> getResourcesBrowseCount(ResourceBrowseParamDto resourceBrowseParamDto) {
        Map<Long, Long> resultMap = new HashMap<>();
        Long bookGroupId = resourceBrowseParamDto.getBookGroupId();
        Long classifyId = resourceBrowseParamDto.getClassifyId();
        Long qrcodeId = resourceBrowseParamDto.getQrcodeId();
        String typeCode = resourceBrowseParamDto.getTypeCode();
        List<Long> ids = resourceBrowseParamDto.getIds();
        if (ListUtils.isEmpty(ids)){
            return resultMap;
        }
        Map<String, Object> map = new HashMap<>();
        map.put("bookGroupId", bookGroupId);
        map.put("classifyId", classifyId);
        map.put("qrcodeId", qrcodeId);
        map.put("type", typeCode);
        map.put("rescourceIds", ids);
        Map<Long, ResourceClickVO> resourceClick = appClickRecordDao.getResourceClick(map);
        if (MapUtils.isEmpty(resourceClick)){
            return resultMap;
        }
        resourceClick.forEach((k,v) ->{
            resultMap.put(k,v.getClickCount());
        });
        return resultMap;
    }

    @Override
    public Map<String, Integer> getBookGroupFriendsCountByDay(Long bookGroupId, String startDate, String endDate) {
        String startTime = DateUtils.formatDate(DateUtils.getDayStart(DateUtils.getDateByStr(startDate)), DateUtils.DATE_FORMAT_DATETIME);
        String endTime = DateUtils.formatDate(DateUtils.getDayEnd(DateUtils.getDateByStr(endDate)), DateUtils.DATE_FORMAT_DATETIME);
        List<DayCountDTO> countDTOS = bookGroupCipherUserDao.getBookGroupFriendsCountByDay(bookGroupId, startTime, endTime);
        Map<String, Integer> map = new HashMap<>();
        if (ListUtils.isEmpty(countDTOS)) {
            return map;
        }
        for (DayCountDTO dayCountDTO : countDTOS) {
            map.put(dayCountDTO.getDate(), dayCountDTO.getCount());
        }
        return map;
    }

    @Override
    public PageBeanNew<FriendsVO> listPageFriendsStatistic(Long bookGroupId, Integer currentPage, Integer numPerPage) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("bookGroupId", bookGroupId);
        PageBeanNew<FriendsVO> pageBeanNew = bookGroupCipherUserDao.listPageNew(new PageParam(currentPage, numPerPage), paramMap, "listPageFriendsStatistic");
        List<FriendsVO> recordList = pageBeanNew.getRecordList();
        if (null == pageBeanNew || ListUtils.isEmpty(recordList)) {
            return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
        }
        List<UserRobotDTO> paramList = new ArrayList<>();
        recordList.forEach(friendsVO -> {
            UserRobotDTO robotDTO = new UserRobotDTO();
            robotDTO.setWxUserId(friendsVO.getWxUserId());
            robotDTO.setRobotId(friendsVO.getRobotId());
            paramList.add(robotDTO);
        });
        Map<String, UserChatCountDTO> dtoMap = wechatGroupConsr.getUserChatInfoByUserIdRobotId(paramList);
        for (FriendsVO friendsVO : recordList) {
            friendsVO.setState("正常");
            if (!MapUtils.isEmpty(dtoMap)) {
                UserChatCountDTO countDTO = dtoMap.get(friendsVO.getWxUserId());
                friendsVO.setNickName(countDTO.getNickName());
                friendsVO.setHeadPic(countDTO.getHeadPic());
                friendsVO.setSex(countDTO.getSex());
                friendsVO.setCountry(countDTO.getCountry());
                friendsVO.setProvince(countDTO.getProvince());
                friendsVO.setCity(countDTO.getCity());
                friendsVO.setSpeakCount(countDTO.getChatCount());
                friendsVO.setSpeakCountLast7(countDTO.getSevenDayChatCount());
                friendsVO.setLastSpeakTime(countDTO.getLastChatTime());
                if (null != countDTO.getFriendState() && countDTO.getFriendState() == 2) {
                    friendsVO.setState("已删除");
                }
            }
        }
        return pageBeanNew;
    }

    @ParamLog("批量新增资源配置")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void batchAddBookGroupServe(Long partyId, List<BookGroupServe> bookGroupServes) {
        checkBookGroupServe(bookGroupServes);
        List<Long> bookGroupIds = bookGroupServes.stream().filter(s -> s.getBookGroupId() != null).map(BookGroupServe::getBookGroupId).distinct().collect(Collectors.toList());
        List<BookGroupServe> bookGroupServeLists = bookGroupServeDao.getListByBookGroupIds(bookGroupIds);
        //校验之前是否已存在
        for (BookGroupServe bookGroupServe : bookGroupServes) {
            Long bookGroupId = bookGroupServe.getBookGroupId();
            Long serveId = bookGroupServe.getServeId();
            String ServeType = bookGroupServe.getServeType();
            for (BookGroupServe bookGroupServeList : bookGroupServeLists) {
                if (bookGroupId.equals(bookGroupServeList.getBookGroupId())
                        && serveId.equals(bookGroupServeList.getServeId())
                        && ServeType.equals(bookGroupServeList.getServeType())) {
                    throw new BookBizException(BookBizException.PARAM_IS_EXIST, "该资源已存在！");
                }
            }
        }
        List<BookGroupDTO> dtos = bookGroupDao.getDTOByIds(bookGroupIds);
        Map<Long, BookGroupDTO> dtoMap = new HashMap<>();
        List<Long> channelIds=new ArrayList<>();
        for (BookGroupDTO bookGroupDTO : dtos) {
            dtoMap.put(bookGroupDTO.getId(), bookGroupDTO);
            if (!channelIds.contains(bookGroupDTO.getChannelId())){
                channelIds.add(bookGroupDTO.getChannelId());
            }
        }
        Map<Long, AccountSettingDto> accountSettingDtoMap = new HashMap<>();
        for (Long channelId : channelIds) {
            AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(channelId);
            accountSettingDtoMap.put(channelId, accountSettingDto);
        }
        for (BookGroupServe bookGroupServe : bookGroupServes) {
            Long bookGroupId = bookGroupServe.getBookGroupId();
            BookGroupDTO bookGroupDTO = dtoMap.get(bookGroupId);
            AccountSettingDto accountSettingDto = accountSettingDtoMap.get(bookGroupDTO.getChannelId());
            if (AppAndProductTypeEnum.APP.value.equalsIgnoreCase(bookGroupServe.getServeType())) {
                AppDto appDto = appConsr.getBaseById(bookGroupServe.getServeId());
                if (appDto != null) {
                    accountSettingDto = qrcodeSceneConsr.getWechatInfo(appDto.getChannelId());
                }
            }
            // 处理链接地址
            String endUrl = bookGroupServe.getServeUrl() + "&book_group_id=" + bookGroupId;
            String linkUrl = SendWeixinRequestTools.splitUrl(accountSettingDto, endUrl);
            //转短链
            String resultUrl = UrlUtils.getShortUrl4Own(linkUrl);
            bookGroupServe.setShortUrl(resultUrl);
            bookGroupServe.setCreateUser(partyId);
        }
        bookGroupServeDao.batchInsert(bookGroupServes);
        //将作品应用关键词加到社群书应用
        bookGroupAppBiz.addServeToBookGroupApp(bookGroupServes);
        Map<Long, List<BookGroupServe>> listMap = bookGroupServes.stream().filter(s -> AppAndProductTypeEnum.PRODUCT.value.equalsIgnoreCase(s.getServeType())).collect(Collectors.groupingBy(s -> s.getBookGroupId()));
        for (Long bookGroupId : bookGroupIds) {
            List<BookGroupServe> list = listMap.get(bookGroupId);
            if (!ListUtils.isEmpty(list)) {
                BookGroupDTO dto = dtoMap.get(bookGroupId);
                List<Long> productIds = list.stream().filter(s -> s.getServeId() != null).map(BookGroupServe::getServeId).collect(Collectors.toList());
                //自动上架
                productConsr.productAutoOnShelves(dto.getChannelId(), productIds);
            }
        }
    }

    @ParamLog("删除资源配置")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteBookGroupServe(Long id) {
        if (id==null){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数错误！");
        }
        bookGroupServeDao.deleteById(id);
    }

    @ParamLog("获取资源配置集合")
    @Override
    public List<BookGroupServe> getBookGroupServeList(Long bookGroupId) {
        if (bookGroupId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空！");
        }
        List<BookGroupServe> list = bookGroupServeDao.getListByBookGroupId(bookGroupId);
        if (ListUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        fillServeInfo(list);
        return list;
    }

    @ParamLog("客户端获取资源配置集合")
    @Override
    public PageBeanNew<BookGroupServe> getBookGroupServeList4Wechat(Long bookGroupId, Integer currentPage, Integer numPerPage) {
        if (bookGroupId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空！");
        }
        if (currentPage == null || numPerPage == null || currentPage < 0 || numPerPage <= 0) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "分页参数有误！");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("bookGroupId", bookGroupId);
        PageBeanNew<BookGroupServe> pageBeanNew = bookGroupServeDao.listPageNew(new PageParam(currentPage, numPerPage), map, "getListByBookGroupId");
        fillServeInfo(pageBeanNew.getRecordList());
        return pageBeanNew;
    }

    @ParamLog("填充资源信息")
    private void fillServeInfo(List<BookGroupServe> list) {
        if (ListUtils.isEmpty(list)){
            return;
        }
        List<Long> productIds = new ArrayList<>();
        List<Long> appIds = new ArrayList<>();
        for (BookGroupServe bookGroupServe : list) {
            if (AppAndProductTypeEnum.PRODUCT.value.equals(bookGroupServe.getServeType())) {
                productIds.add(bookGroupServe.getServeId());
            }
            if (AppAndProductTypeEnum.APP.value.equals(bookGroupServe.getServeType())) {
                appIds.add(bookGroupServe.getServeId());
            }
        }
        Map<Long, ProductDto> productDtoMap = new HashMap<>();
        Map<Long, AppDto> appDtoMap = new HashMap<>();
        Map<Long, Boolean> isSuperMap = new HashMap<>();
        if (!ListUtils.isEmpty(productIds)) {
            productDtoMap = productConsr.getProBasesByIds(productIds);
            isSuperMap = productConsr.getIsSuperByProductIdList(productIds);
        }
        if (!ListUtils.isEmpty(appIds)) {
            appDtoMap = appConsr.mapByIds(appIds);
        }
        for (BookGroupServe bookGroupServe : list) {
            if (AppAndProductTypeEnum.PRODUCT.value.equals(bookGroupServe.getServeType())) {
                ProductDto productDto = productDtoMap.get(bookGroupServe.getServeId());
                if (productDto != null) {
                    bookGroupServe.setServeName(productDto.getProductName());
                    if (productDto.getProductTypeDto() != null) {
                        bookGroupServe.setFromType(productDto.getProductTypeDto().getTypeCode());
                    }
                    bookGroupServe.setIsSuper(isSuperMap.get(bookGroupServe.getServeId()));
                }
            }
            if (AppAndProductTypeEnum.APP.value.equals(bookGroupServe.getServeType())) {
                AppDto appDto = appDtoMap.get(bookGroupServe.getServeId());
                if (appDto != null) {
                    bookGroupServe.setServeName(appDto.getTitle());
                    bookGroupServe.setFromType(appDto.getTypeCode());
                }
            }
        }
    }

    @ParamLog("获取社群码暗号")
    @Override
    public String getBookGroupCipher() {
        String bookGroupCipher = createBookGroupCipher();
        //判断是否为库里面没有的
        BookGroup bookGroup = bookGroupDao.getByBookGroupCipher(bookGroupCipher);
        if (bookGroup != null) {
            //重新生成
            bookGroupCipher = createBookGroupCipher();
        }
        return bookGroupCipher;
    }

    @ParamLog("校验字段")
    private void checkBookGroupServe(List<BookGroupServe> bookGroupServes){
        if (ListUtils.isEmpty(bookGroupServes)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空！");
        }
        for (BookGroupServe bookGroupServe : bookGroupServes) {
            if (bookGroupServe == null) {
                throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空！");
            }
            if (bookGroupServe.getBookGroupId() == null) {
                throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数社群书id不能为空！");
            }
            if (bookGroupServe.getServeId() == null) {
                throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数应用或作品id不能为空！");
            }
            if (StringUtil.isEmpty(bookGroupServe.getServeUrl())){
                throw new BookBizException(BookBizException.PARAM_IS_ERROR, "链接不能为空！");
            }
            if (!("PRODUCT".equals(bookGroupServe.getServeType()) || "APP".equals(bookGroupServe.getServeType()))) {
                throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数应用或作品类型有误（APP或PRODUCT）！");
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("批量更新资源配置")
    @Override
    public void batchUpdateBookGroupServe(Long partyId, List<BookGroupServe> bookGroupServes) {
        checkBookGroupServe(bookGroupServes);
        List<Long> bookGroupIds = bookGroupServes.stream().filter(s -> s.getBookGroupId() != null).map(BookGroupServe::getBookGroupId).distinct().collect(Collectors.toList());
        //删除之前旧的
        bookGroupServeDao.deleteByBookGroupIds(bookGroupIds);
        //批量新增新的
        batchAddBookGroupServe(partyId,bookGroupServes);
    }

    @ParamLog("将1v1旧数据的关键词全部都干掉，有应用或作品的挂在社群书配置资源里面")
    @Override
    public void dealSelfBookGroupKeywordToServer() {
        List<BookGroup> bookGroups = bookGroupDao.getBookGroupByJoinGroupType(JoinGroupTypeEnum.ROBOT.getCode());
        if (ListUtils.isEmpty(bookGroups)) {
            return;
        }
        List<Long> bookGroupIds = bookGroups.stream().filter(s -> s.getId() != null).map(BookGroup::getId).collect(Collectors.toList());
        //查询关键词
        List<KeywordDTO> keywordDTOS = bookKeywordDao.getListByBookGroupIdsAndType(bookGroupIds, ReplyTypeEnum.APP.value);
        if (ListUtils.isEmpty(keywordDTOS)) {
            return;
        }
        Map<Long, List<KeywordDTO>> map = keywordDTOS.stream().filter(s -> s.getBookGroupId() != null).collect(Collectors.groupingBy(KeywordDTO::getBookGroupId));
        for (BookGroup bookGroup : bookGroups) {
            Long bookGroupId = bookGroup.getId();
            List<KeywordDTO> list = map.get(bookGroupId);
            if (ListUtils.isEmpty(list)) {
                continue;
            }
            //查询有没有配置资源，如果没有则新增加入
            List<BookGroupServe> bookGroupServes = bookGroupServeDao.getListByBookGroupId(bookGroupId);
            if (!ListUtils.isEmpty(bookGroupServes)) {
                continue;
            }
            List<BookGroupServe> bookGroupServesNew = new ArrayList<>();
            for (KeywordDTO keywordDTO : list) {
                BookGroupServe bookGroupServe = new BookGroupServe();
                bookGroupServe.setBookGroupId(bookGroupId);
                bookGroupServe.setServeId(keywordDTO.getServeId());
                bookGroupServe.setServeType(keywordDTO.getServeType());
                bookGroupServe.setCreateUser(bookGroup.getCreateUser());
                bookGroupServe.setServeUrl(keywordDTO.getLinkUrl());
                // 处理链接地址
                String endUrl = bookGroupServe.getServeUrl() + "&book_group_id=" + bookGroupId;
                AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(bookGroup.getChannelId());
                if ("APP".equalsIgnoreCase(bookGroupServe.getServeType())) {
                    AppDto appDto = appConsr.getBaseById(bookGroupServe.getServeId());
                    if (appDto != null) {
                        accountSettingDto = qrcodeSceneConsr.getWechatInfo(appDto.getChannelId());
                    }
                }
                String linkUrl = SendWeixinRequestTools.splitUrl(accountSettingDto, endUrl);
                //转短链
                String resultUrl = UrlUtils.getShortUrl4Own(linkUrl);
                bookGroupServe.setShortUrl(resultUrl);
                bookGroupServesNew.add(bookGroupServe);
            }
            if (!ListUtils.isEmpty(bookGroupServesNew)){
                bookGroupServeDao.batchInsert(bookGroupServesNew);
            }
        }
        //按照社群码id集合把关键词逻辑删除
        bookKeywordDao.deleteByBookGroupIds(bookGroupIds);
    }

    @ParamLog("补充1v1旧数据的暗号")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void fillSelfBookGroupCipher() {
        List<BookGroup> bookGroups = bookGroupDao.getNoCipherSelfBookGroups();
        if (ListUtils.isEmpty(bookGroups)) {
            return;
        }
        for (BookGroup bookGroup : bookGroups) {
            String groupCipher = getBookGroupCipher();
            bookGroupDao.updateCipher(bookGroup.getId(),groupCipher);
        }
    }

    @ParamLog("将之前的配置资源取的社群码运营更新为应用本身的运营")
    @Override
    public void dealBookGroupServerChannel() {
        List<BookGroupServe> bookGroupServes=bookGroupServeDao.getListByServerType("APP");
        if (ListUtils.isEmpty(bookGroupServes)) {
            return;
        }
        List<Long> appIds=new ArrayList<>();
        List<Long> bookGroupIds=new ArrayList<>();
        for (BookGroupServe bookGroupServe:bookGroupServes){
            if (!appIds.contains(bookGroupServe.getServeId())){
                appIds.add(bookGroupServe.getServeId());
            }
            if (!bookGroupIds.contains(bookGroupServe.getBookGroupId())){
                bookGroupIds.add(bookGroupServe.getBookGroupId());
            }
        }
        Map<Long, AppDto> appDtoMap = appConsr.getBaseByIds(appIds);
        List<BookGroupDTO> bookGroupDTOList = bookGroupDao.getDTOByIds(bookGroupIds);
        Map<Long, BookGroupDTO> bookGroupMap=new HashMap<>();
        for (BookGroupDTO bookGroupDTO:bookGroupDTOList){
            bookGroupMap.put(bookGroupDTO.getId(),bookGroupDTO);
        }
        for (BookGroupServe bookGroupServe : bookGroupServes) {
            AppDto appDto = appDtoMap.get(bookGroupServe.getServeId());
            BookGroupDTO bookGroupDTO = bookGroupMap.get(bookGroupServe.getBookGroupId());
            if (appDto != null && bookGroupDTO != null && !appDto.getChannelId().equals(bookGroupDTO.getChannelId())) {
                //换链接
                String endUrl = bookGroupServe.getServeUrl() + "&book_group_id=" + bookGroupServe.getBookGroupId();
                AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(appDto.getChannelId());
                String linkUrl = SendWeixinRequestTools.splitUrl(accountSettingDto, endUrl);
                //转短链
                String resultUrl = UrlUtils.getShortUrl4Own(linkUrl);
                bookGroupServeDao.updateShortUrl(bookGroupServe.getId(), resultUrl);
            }
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("更新是否邀请入群")
    @Override
    public void updateIsInviteGroup(BookGroup bookGroup) {
        if (bookGroup == null || bookGroup.getId() == null || bookGroup.getIsInviteGroup() == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        BookGroupDTO oldBookGroup = bookGroupDao.getDTOById(bookGroup.getId());
        if (oldBookGroup == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "该社群码不存在！");
        }
        bookGroupDao.updateIsInviteGroup(bookGroup.getId(), bookGroup.getIsInviteGroup());
        //如果从不邀请进群修改为邀请进群则视为更新
        if (oldBookGroup.getIsInviteGroup() != null && !oldBookGroup.getIsInviteGroup() && bookGroup.getIsInviteGroup()) {
            bookGroupDao.updateIsSomeUpdate(bookGroup.getId(), true);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("更新1v1是否有更新")
    @Override
    public void updateIsSomeUpdate(BookGroup bookGroup) {
        if (bookGroup == null || bookGroup.getId() == null || bookGroup.getIsSomeUpdate() == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        Long bookGroupId = bookGroup.getId();
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
        if (bookGroupDTO != null && JoinGroupTypeEnum.ROBOT.getCode().equals(bookGroupDTO.getJoinGroupType())) {
            bookGroupDao.updateIsSomeUpdate(bookGroupId, bookGroup.getIsSomeUpdate());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("新增推送更新")
    @Override
    public void addPushBookGroupUpdate(BookGroup bookGroup) {
        if (bookGroup == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        Long bookGroupId = bookGroup.getId();
        if (bookGroupId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
        if (bookGroupDTO == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "没有该社群码！");
        }
        if (!JoinGroupTypeEnum.ROBOT.getCode().equals(bookGroupDTO.getJoinGroupType())) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "该社群码不是1v1模式！");
        }
        if (bookGroupDTO.getIsSomeUpdate() == null || !bookGroupDTO.getIsSomeUpdate()) {
            LOGGER.info("没有更新！bookGroupId=" + bookGroupId);
            return;
        }
        if (bookGroupDTO.getLastPushUpdateTime() != null && (new Date().getTime() - bookGroupDTO.getLastPushUpdateTime().getTime() < 7 * 24 * 60 * 60 * 1000)) {
            LOGGER.info("距离上次更新不到7天！bookGroupId=" + bookGroupId);
            return;
        }
        //查询已经关联的用户wxUserIds
        List<BookGroupCipherUser> bookGroupCipherUsers = bookGroupCipherUserDao.getWxUserIdAndAltsByBookGroupId(bookGroupId);
        if (ListUtils.isEmpty(bookGroupCipherUsers)) {
            LOGGER.info("该社群书没有用户bookGroupId=" + bookGroupId);
            return;
        }
        if (bookGroupCipherUsers.size()>100){
            LOGGER.info("该社群书用户数量超过100，不处理bookGroupId="+bookGroupId);
            return;
        }
        List<PushBookGroupUpdate> pushBookGroupUpdates=new ArrayList<>();
        for (BookGroupCipherUser bookGroupCipherUser:bookGroupCipherUsers){
            PushBookGroupUpdate pushBookGroupUpdate=new PushBookGroupUpdate();
            pushBookGroupUpdate.setBookGroupId(bookGroupId);
            pushBookGroupUpdate.setWxUserId(bookGroupCipherUser.getWxUserId());
            pushBookGroupUpdate.setAltId(bookGroupCipherUser.getAltId());
            pushBookGroupUpdate.setIsPush(false);
            pushBookGroupUpdates.add(pushBookGroupUpdate);
        }
        pushBookGroupUpdateDao.batchInsert(pushBookGroupUpdates);
        bookGroupDao.updateLastPushUpdateTime(bookGroupId);
        bookGroupDao.updateIsSomeUpdate(bookGroupId,false);
    }

    @ParamLog("推送更新")
    @Override
    public void pushBookGroupUpdate() {
        PushBookGroupUpdate pushBookGroupUpdate = pushBookGroupUpdateDao.getEarliestPushBookGroupUpdate();
        if (pushBookGroupUpdate != null) {
            Integer count = pushBookGroupUpdateDao.updateIsPushTrue(pushBookGroupUpdate.getId());
            if (count == 0) {
                LOGGER.info("此条已更新pushBookGroupUpdate="+pushBookGroupUpdate.toString());
                return;
            }
            try {
                LOGGER.info("开始推送pushBookGroupUpdate="+pushBookGroupUpdate.toString());
                SendTextDTO sendTextDTO = new SendTextDTO();
                sendTextDTO.setWxId(pushBookGroupUpdate.getAltId());
                sendTextDTO.setCode(SendMessageTypeEnum.SELF.getCode());
                //获取小号基本信息，获取ip
                GroupRobotDTO groupRobotDTO = wechatGroupConsr.getGroupRobotByWxId(pushBookGroupUpdate.getAltId());
                if (groupRobotDTO!=null){
                    Integer version=groupRobotDTO.getVersion();
                    WeixinQrcodeGeneration weixinQrcodeGeneration = weixinQrcodeGenerationDao.getByGeneration(version);
                    if (weixinQrcodeGeneration!=null){
                        sendTextDTO.setIp(weixinQrcodeGeneration.getWechatGroupIp());
                    }
                }
                sendTextDTO.setWechatUserId(pushBookGroupUpdate.getWxUserId());
                bookKeywordBiz.dealByBookGroup(sendTextDTO, pushBookGroupUpdate.getBookGroupId(), true);
            } catch (Exception e){
                LOGGER.error("推送更新出错pushBookGroupUpdate=" + pushBookGroupUpdate.toString() + e.getMessage());
            } finally {
                pushBookGroupUpdateDao.updateIsPushTrue(pushBookGroupUpdate.getId());
            }
        }
    }

    @ParamLog("获取是否能推送更新的各个状态")
    @Override
    public Map<String, Boolean> getStatesForPushUpdate(Long bookGroupId) {
        if (bookGroupId==null){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        Map<String, Boolean> map = new HashMap<>();
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
        if (bookGroupDTO == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "没有该社群码！");
        }
        if (bookGroupDTO.getIsSomeUpdate() != null && bookGroupDTO.getIsSomeUpdate()) {
            map.put("isSomeUpdate", true);
        } else {
            map.put("isSomeUpdate", false);
        }
        if (bookGroupDTO.getLastPushUpdateTime() != null && (new Date().getTime() - bookGroupDTO.getLastPushUpdateTime().getTime() < 7 * 24 * 60 * 60 * 1000)) {
            map.put("isMoreThan7days", false);
        } else {
            map.put("isMoreThan7days", true);
        }
        //查询已经关联的用户wxUserIds
        List<BookGroupCipherUser> bookGroupCipherUsers = bookGroupCipherUserDao.getWxUserIdAndAltsByBookGroupId(bookGroupId);
        if (!ListUtils.isEmpty(bookGroupCipherUsers) && bookGroupCipherUsers.size() < 100) {
            map.put("isPersonSizeSuitable", true);
        } else {
            map.put("isPersonSizeSuitable", false);
        }
        return map;
    }

    @ParamLog("上架所有的个人号配置资源")
    @Override
    public void dealBookGroupServeOldOnShelves() {
        //查询所有的配置资源作品
        List<BookGroupServe> list = bookGroupServeDao.getProductServeList();
        if (!ListUtils.isEmpty(list)) {
            List<Long> bookGroupIds = list.stream().map(BookGroupServe::getBookGroupId).distinct().collect(Collectors.toList());
            List<BookGroupDTO> dtos = bookGroupDao.getDTOByIds(bookGroupIds);
            Map<Long, Long> channelMap = new HashMap<>();
            for (BookGroupDTO bookGroupDTO : dtos) {
                channelMap.put(bookGroupDTO.getId(), bookGroupDTO.getChannelId());
            }
            Map<Long, List<BookGroupServe>> map = list.stream().collect(Collectors.groupingBy(BookGroupServe::getBookGroupId));
            for (Long bookGroupId : bookGroupIds) {
                List<BookGroupServe> bookGroupServes = map.get(bookGroupId);
                Long channelId = channelMap.get(bookGroupId);
                if (!ListUtils.isEmpty(bookGroupServes) && channelId != null) {
                    List<Long> productIds = bookGroupServes.stream().filter(s -> s.getServeId() != null).map(BookGroupServe::getServeId).collect(Collectors.toList());
                    //上架
                    productConsr.productAutoOnShelves(channelId, productIds);
                }
            }
        }
    }

    @ParamLog("生成暗号")
    private String createBookGroupCipher(){
        //生成暗号规则：abc1234，前三位小写字母，后四位数字
        Random random = new Random();
        String s = "";
        for (int i = 0; i < 3; i++) {
            int result = 97 + random.nextInt(26);
            s = s + String.valueOf((char) result);
        }
        for (int i = 0; i < 4; i++) {
            int result = random.nextInt(10);
            s = s + String.valueOf(result);
        }
        return s;
    }
    @Override
    public PageBeanNew<BookGroupAnalysisVO> listPageBookGroupAnalysis(BookGroupAnalysisParam bookGroupAnalysisParam) {
        Map<String, Object> paramMap = new HashMap<>();
        if (!ListUtils.isEmpty(bookGroupAnalysisParam.getBookIds())) {
            paramMap.put("bookIds", bookGroupAnalysisParam.getBookIds());
        }
        if (!ListUtils.isEmpty(bookGroupAnalysisParam.getAdviserIds())) {
            paramMap.put("adviserIds", bookGroupAnalysisParam.getAdviserIds());
        }
        if (!ListUtils.isEmpty(bookGroupAnalysisParam.getAgentIds())) {
            paramMap.put("agentIds", bookGroupAnalysisParam.getAgentIds());
        }
        paramMap.put("isFundSupport", bookGroupAnalysisParam.getIsFundSupport());
        paramMap.put("isCopyright", bookGroupAnalysisParam.getIsCopyright());
        PageBeanNew<BookGroupAnalysisVO> pageBeanNew = bookGroupDao.listPageNew(
                new PageParam(bookGroupAnalysisParam.getCurrentPage(), bookGroupAnalysisParam.getNumPerPage()), paramMap, "listPageBookGroupAnalysis");
        if (null == pageBeanNew || ListUtils.isEmpty(pageBeanNew.getRecordList())) {
            return new PageBeanNew<>(bookGroupAnalysisParam.getCurrentPage(), bookGroupAnalysisParam.getNumPerPage(), 0, new ArrayList<>());
        }
        String monthDate = bookGroupAnalysisParam.getMonthDate();
        //设置书刊分类名称
        groupSet.setTempletName(pageBeanNew.getRecordList());
        //设置出版运营编辑名称
        groupSet.setPartyInfo(pageBeanNew.getRecordList());
        //设置社群码扫码量
        groupSet.setGroupScanCount(pageBeanNew.getRecordList(), monthDate);
        //设置微信群数据（分类数，群数，群人数，好友数，资源数）
        groupSet.setGroupStatistic(pageBeanNew.getRecordList(), monthDate);
        //设置资源数据(浏览量，读者量，销售额，支付率，客单价)
        groupSet.setResourceStatistic(pageBeanNew.getRecordList(), monthDate);
        return pageBeanNew;
    }

    @Override
    public void exportBookGroupAnalysis(BookGroupAnalysisParam bookGroupAnalysisParam, Long partyId) {
        ThreadPoolUtils.EXPORT_THREAD_POOL.execute(() -> {
            Map<String, Object> paramMap = new HashMap<>();
            if (!ListUtils.isEmpty(bookGroupAnalysisParam.getBookIds())){
                paramMap.put("bookIds", bookGroupAnalysisParam.getBookIds());
            }
            if (!ListUtils.isEmpty(bookGroupAnalysisParam.getAdviserIds())) {
                paramMap.put("adviserIds", bookGroupAnalysisParam.getAdviserIds());
            }
            if (!ListUtils.isEmpty(bookGroupAnalysisParam.getAgentIds())) {
                paramMap.put("agentIds", bookGroupAnalysisParam.getAgentIds());
            }
            paramMap.put("isFundSupport", bookGroupAnalysisParam.getIsFundSupport());
            paramMap.put("isCopyright", bookGroupAnalysisParam.getIsCopyright());
            List<BookGroupAnalysisVO> list = bookGroupDao.listPageBookGroupAnalysis(paramMap);
            if (ListUtils.isEmpty(list)) {
                return;
            }
            String monthDate = bookGroupAnalysisParam.getMonthDate();
            //设置书刊分类名称
            groupSet.setTempletName(list);
            //设置出版运营编辑名称
            groupSet.setPartyInfo(list);
            //设置社群码扫码量
            groupSet.setGroupScanCount(list, monthDate);
            //设置微信群数据（分类数，群数，群人数，好友数，资源数）
            groupSet.setGroupStatistic(list, monthDate);
            //设置资源数据(浏览量，读者量，销售额，支付率，客单价)
            groupSet.setResourceStatistic(list, monthDate);

            Boolean isSuccess = true;
            String fileUrl = "";
            String fileName = "社群书分析";
            if (!StringUtil.isEmpty(monthDate)) {
                String[] dateStr = monthDate.split("-");
                fileName = dateStr[0] + "年" + Integer.parseInt(dateStr[1]) + "月" + fileName;
            }
            try {
                fileUrl = groupSet.fillBookGroupExcel(list, fileName);
            } catch (Exception e) {
                isSuccess = false;
                LOGGER.error("导出文件失败" + e.getMessage(), e);
            }
            if (isSuccess) {
                JSONObject content = new JSONObject();
                content.put("commitTime", DateUtils.formatDate(new Date()));
                content.put("type", "社群书分析导出");
                messageConsr.sendLetter(partyId, partyId, content.toJSONString(), SystemCode.pcloud.code, "book_download", fileUrl, fileName);
            }
        });
    }

    @Override
    public List<BookGroupKeywordResourceDTO> getKeyWordResourceByBookGroup(Long bookGroupId) {
        List<BookGroupKeywordResourceDTO> list = bookKeywordDao.getBookGroupResourceList(bookGroupId);
        return list;
    }

    @Override
    public List<Long> getQrcodeIdsByBookGroupId(Long bookGroupId) {
        List<Long> ids=groupQrcodeDao.getIdsByBookGroupId(bookGroupId);
        return ids;
    }

    @Override
    public List<String> getFriendIdsByBookGroupId(Long bookGroupId) {
        return bookGroupCipherUserDao.getFriendIdsByBookGroupId(bookGroupId);
    }

    @Override
    public PageBeanNew<SelfRobotUserDTO> listPageFriendInfo(SelfRobtParamDTO selfRobtParamDTO) {
        Map<String, Object> paramMap = new HashMap<>();
        if (!ListUtils.isEmpty(selfRobtParamDTO.getUserIds())) {
            paramMap.put("userIds", selfRobtParamDTO.getUserIds());
        }
        if (!ListUtils.isEmpty(selfRobtParamDTO.getRobotIds())) {
            paramMap.put("robotIds", selfRobtParamDTO.getRobotIds());
        }
        if (!ListUtils.isEmpty(selfRobtParamDTO.getBookIds())) {
            paramMap.put("bookIds", selfRobtParamDTO.getBookIds());
        }
        if (null != selfRobtParamDTO.getFriendState() && !ListUtils.isEmpty(selfRobtParamDTO.getDeleteUserDTOS())) {
            paramMap.put("friendState", selfRobtParamDTO.getFriendState());
            paramMap.put("deleteUserList", selfRobtParamDTO.getDeleteUserDTOS());
        }
        List<SelfRobotUserDTO> totalList = bookGroupCipherUserDao.listPageFriendInfo(paramMap);
        if (ListUtils.isEmpty(totalList)) {
            return new PageBeanNew<>();
        }
        Integer totalCount = totalList.size();
        paramMap.put("pageNum", selfRobtParamDTO.getCurrentPage() * selfRobtParamDTO.getNumPerPage());
        paramMap.put("numPerPage", selfRobtParamDTO.getNumPerPage());
        List<SelfRobotUserDTO> list = bookGroupCipherUserDao.listPageFriendInfo(paramMap);
        for (SelfRobotUserDTO userDTO : list) {
            List<BookDto> bookList = bookGroupCipherUserDao.getBookGroupListByUser(userDTO.getWxUserId(), userDTO.getRobotId());
            userDTO.setBookList(bookList);
        }
        PageBeanNew<SelfRobotUserDTO> pageBeanNew = new PageBeanNew(selfRobtParamDTO.getCurrentPage(), selfRobtParamDTO.getNumPerPage(), totalCount, list);
        return pageBeanNew;
    }

    @ParamLog("根据类型获取社群书数量")
    @Override
    public Integer getBookGroupCountByJoinGroupType(Integer joinGroupType) {
        return bookGroupDao.getBookGroupCountByJoinGroupType(joinGroupType);
    }

    @ParamLog("获取个人号累计加好友人数")
    @Override
    public Integer getAddFriendCount() {
        return bookGroupCipherUserDao.getAddFriendCount();
    }

    @ParamLog("根据时间段获取个人号加好友人数")
    @Override
    public List<CountAndTimeDTO> getAddFriendCountByTime(Integer timeType, String startTime, String endTime) {
        if (timeType == null || (1 != timeType && 2 != timeType)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "时间类型参数错误！");
        }
        if (StringUtil.isEmpty(startTime) || StringUtil.isEmpty(endTime)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "时间参数错误！");
        }
        List<CountAndTimeDTO> list = bookGroupCipherUserDao.getAddFriendCountByTime(timeType, startTime, endTime);
        groupSet.fillEmptyTime(list, timeType, startTime, endTime);
        list=list.stream().sorted(Comparator.comparing(CountAndTimeDTO::getTime)).collect(Collectors.toList());
        return list;
    }

    @ParamLog("获取出版社创建社群书数量排行")
    @Override
    public List<TopAgentBookGroupDTO> getTopAgentCreateBookGroup(Integer joinGroupType, Integer top, Boolean isSpecial) {
        if (top == null || top < 0 || isSpecial == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数错误");
        }
        List<Long> allAgentId=null;
        if (isSpecial) {
            allAgentId = wechatGroupConsr.getAllAgentId();
            if (ListUtils.isEmpty(allAgentId)) {
                allAgentId = Lists.newArrayList(-1L);
            }
        }
        List<TopAgentBookGroupDTO> dtos = bookGroupDao.getTopAgentCreateBookGroup(joinGroupType, top, allAgentId);
        if (!ListUtils.isEmpty(dtos)){
            List<Long> agentIds=dtos.stream().filter(s->s.getAgentId()!=null).map(TopAgentBookGroupDTO::getAgentId).collect(Collectors.toList());
            if (!ListUtils.isEmpty(agentIds)){
                Map<Long, String> namesMap = agentConsr.getNames(agentIds);
                if (namesMap!=null){
                    for (TopAgentBookGroupDTO topAgentBookGroupDTO:dtos){
                        topAgentBookGroupDTO.setAgentName(namesMap.get(topAgentBookGroupDTO.getAgentId()));
                    }
                }
            }
        }
        return dtos;
    }

    @ParamLog("补充社群书的出版社id")
    @Override
    public void fillAgentIdForBookGroup() {
        List<Long> adviserIds = bookGroupDao.getEmptyAgentIdAdviserId();
        if (ListUtils.isEmpty(adviserIds)) {
            return;
        }
        //根据adviserId拿agentId
        Map<Long, AdviserBaseInfoDto> infoDtoMap = adviserConsr.getAdviserId2AdviserInfoDtoMap(adviserIds);
        if (infoDtoMap == null) {
            return;
        }
        //根据adviserId更新
        for (Long adviserId : adviserIds) {
            AdviserBaseInfoDto adviserBaseInfoDto = infoDtoMap.get(adviserId);
            if (adviserBaseInfoDto != null && adviserBaseInfoDto.getAgentId() != null) {
                bookGroupDao.updateAgentIdByAdviserId(adviserId, adviserBaseInfoDto.getAgentId());
            }
        }
    }

    @ParamLog("获取所有已建分类的1v1的社群码")
    @Override
    public List<Long> get1v1HasClassifyBookGroupIds() {
        return bookGroupDao.get1v1HasClassifyBookGroupIds();
    }

    @ParamLog("获取个人号读者专业或深度分布")
    @Override
    public List<LabelUserCountDTO> getUserLabelDistribution(Integer largeTemplet, Integer type) {
        if (type == null || (type != 1 && type != 2) || largeTemplet == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数错误");
        }
        // 根据类型拿所有小号
        List<String> altIds = wechatGroupConsr.getRobotListByLargeTemplet(largeTemplet);
        List<LabelUserCountDTO> labelUserCountDTOS = bookGroupCipherUserDao.getUserLabelDistribution(type, altIds);
        if (!ListUtils.isEmpty(labelUserCountDTOS)) {
            List<Long> labelIds = labelUserCountDTOS.stream().filter(s -> s.getLabelId() != null).map(LabelUserCountDTO::getLabelId).collect(Collectors.toList());
            Map<Long, String> labelMap = ResponseHandleUtil.parseMap(labelService.getLabelName(labelIds), Long.class, String.class);
            if (!MapUtils.isEmpty(labelMap)) {
                for (LabelUserCountDTO labelUserCountDTO : labelUserCountDTOS) {
                    labelUserCountDTO.setLabelName(labelMap.get(labelUserCountDTO.getLabelId()));
                }
            }
        }
        return labelUserCountDTOS;
    }

    @Override
    @ParamLog("获取出版社个人号统计信息")
    public PageBeanNew<AgentStatisticsInfoDTO> getAgentStatisticsInfo(Long agentId, Boolean isSpecial, Integer currentPage, Integer numPerPage) {
        if (currentPage == null || numPerPage == null || currentPage < 0 || numPerPage < 0) {
            throw BookBizException.PAGE_PARAM_DELETION;
        }
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("agentId", agentId);
        if(isSpecial != null && isSpecial) {
            List<Long> specialAgentIds = wechatGroupConsr.getAllAgentId();
            if(CollectionUtils.isEmpty(specialAgentIds)) {
                specialAgentIds.add(-1L);
            }
            paramMap.put("specialAgentIds", specialAgentIds);
        }
        PageBeanNew<AgentStatisticsInfoDTO> pageBeanNew = bookGroupDao.listPageNew(new PageParam(currentPage, numPerPage), paramMap, "getAgentStatisticsInfo");
        if(!CollectionUtils.isEmpty(pageBeanNew.getRecordList())) {
            List<AgentStatisticsInfoDTO> agentStatisticsInfoDTOS = pageBeanNew.getRecordList();
            groupSet.setAgentStatisticsDetailInfo(agentStatisticsInfoDTOS);
        }
        return pageBeanNew;
    }

    @Override
    @ParamLog("导出出版社个人号统计信息")
    public void exportAgentStatisticsInfo(Long partyId, Long agentId, Boolean isSpecial) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("agentId", agentId);
        if(isSpecial != null && isSpecial) {
            List<Long> specialAgentIds = wechatGroupConsr.getAllAgentId();
            if(CollectionUtils.isEmpty(specialAgentIds)) {
                specialAgentIds.add(-1L);
            }
            paramMap.put("specialAgentIds", specialAgentIds);
        }
        List<AgentStatisticsInfoDTO> agentStatisticsInfoDTOS = bookGroupDao.getAgentStatisticsInfo(paramMap);
        if(CollectionUtils.isEmpty(agentStatisticsInfoDTOS)) {
            throw new BookBizException(BookBizException.RESULT_NULL, "暂无导出数据!");
        }
        //异步导出
        PLATFORM_STATISTICS_EXPORT_THREAD.execute(() -> {
            groupSet.setAgentStatisticsDetailInfo(agentStatisticsInfoDTOS);
            String fileName = "个人号出版社统计信息_" + DateUtils.getShortDateStr();
            try {
                String[] rowsName = {"序号", "出版社信息", "个人号社群书数量", "定制个人号数量", "已发消息数量"};
                List<Object[]> dataList = new ArrayList<>();
                Object[] objs;
                for (int i = 0; i < agentStatisticsInfoDTOS.size(); i++) {
                    AgentStatisticsInfoDTO dto = agentStatisticsInfoDTOS.get(i);
                    objs = new Object[rowsName.length];
                    objs[0] = i + 1;
                    objs[1] = dto.getAgentName();
                    objs[2] = dto.getGroupBookCount();
                    objs[3] = dto.getRobotCount();
                    objs[4] = dto.getSendMsgCount();
                    dataList.add(objs);
                }
                String fileUrl = exportConsr.exportExcel(fileName, rowsName, dataList);
                //发送站内信
                JSONObject content = new JSONObject();
                content.put("commitTime", DateUtils.formatDate(new Date()));
                content.put("type", "个人号出版社统计信息");
                messageConsr.sendLetter(partyId, partyId, content.toJSONString(), SystemCode.pcloud.code,
                        "agent_statistic_export", fileUrl, fileName, NotifyOriginTypeEnum.BOOK_GROUP.value, null);
            } catch (Exception e) {
                LOGGER.error("生成导出文件失败" + e.getMessage(), e);
            }
        });
    }

    @ParamLog("按时间获取资源服务点击量趋势")
    @Override
    public Map<String, List<CountAndTimeDTO>> getServeClickTendencyList(Long bookGroupId, List<String> dateList) {
        if (bookGroupId == null || ListUtils.isEmpty(dateList)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数错误");
        }
        List<CountAndTimeDTO> list = appClickRecordDao.getAppClickByBookGroupId(bookGroupId, dateList);
        Map<String, List<CountAndTimeDTO>> map = new HashMap<>();
        list = list.stream().sorted(Comparator.comparing(CountAndTimeDTO::getTime)).collect(Collectors.toList());
        for (String date : dateList) {
            List<CountAndTimeDTO> one = list.stream().filter(s -> s.getDate().equals(date)).collect(Collectors.toList());
            String start = DateUtils.getStrFormTime("yyyy-MM-dd HH:mm:ss", DateUtils.getDayStart(DateUtils.getDateByStr(date)));
            String end = DateUtils.getStrFormTime("yyyy-MM-dd HH:mm:ss", DateUtils.getDayEnd(DateUtils.getDateByStr(date)));
            groupSet.fillEmptyTime(one, 2, start, end);
            one = one.stream().sorted(Comparator.comparing(CountAndTimeDTO::getTime)).collect(Collectors.toList());
            map.put(date, one);
        }
        return map;
    }

    @ParamLog("个人号社群书统计")
    @Override
    public PageBeanNew<SelfBookGroupStDTO> getSelfBookGroupStatistics(SelfBookGroupStParamDTO selfBookGroupStParamDTO) {
        if (selfBookGroupStParamDTO == null
                || selfBookGroupStParamDTO.getCurrentPage() == null
                || selfBookGroupStParamDTO.getNumPerPage() == null
                || selfBookGroupStParamDTO.getCurrentPage() < 0
                || selfBookGroupStParamDTO.getNumPerPage() <= 0) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数错误！");
        }
        PageParam pageParam = new PageParam(selfBookGroupStParamDTO.getCurrentPage(), selfBookGroupStParamDTO.getNumPerPage());
        Map<String, Object> map = new HashMap<>();
        map.put("joinGroupTypes", Arrays.asList(JoinGroupTypeEnum.ROBOT.getCode(),JoinGroupTypeEnum.AI_ROBOT.getCode(),
                JoinGroupTypeEnum.XIAORUI.getCode()));
        map.put("name", selfBookGroupStParamDTO.getName());
        map.put("proLabelId", selfBookGroupStParamDTO.getProLabelId());
        map.put("depLabelId", selfBookGroupStParamDTO.getDepLabelId());
        map.put("bookIds", selfBookGroupStParamDTO.getBookIds());
        if (selfBookGroupStParamDTO.getIsSpecial() != null
                && selfBookGroupStParamDTO.getIsSpecial()
                && ListUtils.isEmpty(selfBookGroupStParamDTO.getAgentIds())) {
            //获取特殊出版社id集合
            List<Long> agentIds = wechatGroupConsr.getAllAgentId();
            if (ListUtils.isEmpty(agentIds)){
                //填充缺省值
                map.put("agentIds", Lists.newArrayList(-1L));
            }else {
                map.put("agentIds", agentIds);
            }
        } else {
            map.put("agentIds", selfBookGroupStParamDTO.getAgentIds());
        }
        PageBeanNew<SelfBookGroupStDTO> pageBeanNew = bookGroupDao.listPageNew(pageParam, map, "getSelfBookGroupStatistics");
        fillStInfo(pageBeanNew.getRecordList());
        return pageBeanNew;
    }

    @ParamLog("个人号社群书统计")
    @Override
    public void exportSelfBookGroupStatistics(SelfBookGroupStParamDTO selfBookGroupStParamDTO, String systemCode, Long partyId) {
        ThreadPoolUtils.EXPORT_THREAD_POOL.execute(() -> {
            try {
                //导出数据
                if (selfBookGroupStParamDTO == null) {
                    throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数错误！");
                }
                Map<String, Object> map = new HashMap<>();
                map.put("name", selfBookGroupStParamDTO.getName());
                map.put("proLabelId", selfBookGroupStParamDTO.getProLabelId());
                map.put("depLabelId", selfBookGroupStParamDTO.getDepLabelId());
                map.put("bookIds", selfBookGroupStParamDTO.getBookIds());
                if (selfBookGroupStParamDTO.getIsSpecial() != null
                        && selfBookGroupStParamDTO.getIsSpecial()
                        && ListUtils.isEmpty(selfBookGroupStParamDTO.getAgentIds())) {
                    //获取特殊出版社id集合
                    List<Long> agentIds = wechatGroupConsr.getAllAgentId();
                    if (ListUtils.isEmpty(agentIds)){
                        //填充缺省值
                        map.put("agentIds", Lists.newArrayList(-1L));
                    }else {
                        map.put("agentIds", agentIds);
                    }
                } else {
                    map.put("agentIds", selfBookGroupStParamDTO.getAgentIds());
                }
                Integer count = bookGroupDao.countSelfBookGroupStatistics(map);
                if (count > 10000) {
                    throw new BookBizException(BookBizException.ERROR, "数量超出限制，请添加筛选条件！");
                }
                List<SelfBookGroupStDTO> list = new ArrayList<>();
                Integer cu = 500;
                Integer p = (count / cu) + 1;
                for (int i = 0; i < p; i++) {
                    selfBookGroupStParamDTO.setCurrentPage(i);
                    selfBookGroupStParamDTO.setNumPerPage(cu);
                    PageBeanNew<SelfBookGroupStDTO> page = getSelfBookGroupStatistics(selfBookGroupStParamDTO);
                    list.addAll(page.getRecordList());
                }
                //导出
                exportSelfBGSt(list, systemCode, partyId);
            } catch (Exception e) {
                LOGGER.error("exportSelfBookGroupStatistics+++selfBookGroupStParamDTO=" + selfBookGroupStParamDTO.toString() + "systemCode=" + systemCode + "partyId=" + partyId);
            }
        });
    }

    @ParamLog("根据小号批量获取服务社群书数量")
    @Override
    public Map<String, Integer> getBookGroupCountMapByAltIds(List<String> altIds) {
        Map<String, Integer> map = new HashMap<>();
        if (ListUtils.isEmpty(altIds)) {
            return map;
        }
        List<AltAndCountDTO> list = bookGroupCipherUserDao.getBookGroupCountListByAltIds(altIds);
        for (AltAndCountDTO altAndCountDTO : list) {
            map.put(altAndCountDTO.getAltId(), altAndCountDTO.getCount());
        }
        return map;
    }

    @ParamLog("获取小号社群书数量")
    @Override
    public Integer getSerBookGroupCountByAltIds(List<String> altIds) {
        if(ListUtils.isEmpty(altIds)){
            return 0;
        }
        List<Long> bookGroupIds=bookGroupCipherUserDao.getBookGroupIdsByAltIds(altIds);
        if (ListUtils.isEmpty(bookGroupIds)){
            return 0;
        }
        return bookGroupIds.size();
    }

    @ParamLog("出版社关联的个人号以及个人号的社群书数量")
    @Override
    public List<AltAndCountDTO> getAltAndCountDTOListByAgentId(Long agentId) {
        List<AltAndCountDTO> list = new ArrayList<>();
        if (agentId == null) {
            return list;
        }
        List<String> altIds = bookGroupCipherUserDao.getAltIdsByAgentId(agentId);
        if (ListUtils.isEmpty(altIds)){
            return list;
        }
        list = bookGroupCipherUserDao.getBookGroupCountListByAltIds(altIds);
        return list;
    }

    @ParamLog("导出")
    private void exportSelfBGSt(List<SelfBookGroupStDTO> list,String systemCode, Long partyId) {
        if (ListUtils.isEmpty(list)) {
            return;
        }
        List<Object[]> dataList = new ArrayList<>();
        for (int i = 0, size = list.size(); i < size; i++) {
            SelfBookGroupStDTO dto = list.get(i);
            Object[] obj = new Object[31];
            obj[0] = i + 1;
            obj[1] = dto.getBookName();
            obj[2] = dto.getIsbn();
            obj[3] = dto.getUniqueNumber();
            obj[4] = dto.getAdviserName();
            obj[5] = dto.getAgentName();
            obj[6] = dto.getGroupQrcodeName();
            obj[7] = dto.getGroupQrcodeUrl();
            obj[8] = dto.getDepLabelName();
            obj[9] = dto.getPurLabelName();
            obj[10] = DateUtils.getStrFormTime("yyyy-MM-dd HH:mm:ss", dto.getCreateTime());
            String altName = "";
            if (!ListUtils.isEmpty(dto.getAltIdAndNameDTOS())) {
                for (AltIdAndNameDTO altIdAndNameDTO : dto.getAltIdAndNameDTOS()) {
                    altName = altName + altIdAndNameDTO.getAltName() + "、";
                }
            }
            obj[11] = altName;
            obj[12] = dto.getScanPeopleCount();
            obj[13] = dto.getCopyCipherPeopleCount();
            obj[14] = dto.getAccAddFriendCount();
            obj[15] = dto.getScanConversionRate();
            obj[16] = dto.getPreFriendCount();
            obj[17] = dto.getDelFriendCount();
            obj[18] = dto.getFriendKeepRate();
            obj[19] = dto.getSendMessageCount();
            obj[20] = dto.getClassifyCount();
            obj[21] = dto.getAccJoinGroupCount();
            obj[22] = dto.getPreInGroupPeopleCount();
            obj[23] = dto.getGroupMessageCount();
            obj[24] = dto.getServeCount();
            obj[25] = dto.getServeClickPeopleCount();
            obj[26] = dto.getServeClickCount();
            obj[27] = dto.getAvgBrowseTime();
            obj[28] = dto.getOneServeBrowseTime();
            obj[29] = dto.getBuyPeopleCount();
            obj[30] = dto.getSaleAmount();
            dataList.add(obj);
        }
        Date date = new Date();
        String[] rowsName = {"序号", "书名", "isbn编号", "唯一编号", "编辑名称", "出版社名称", "社群码名称",
                            "社群码url", "深度标签名称", "目的标签名称", "创建时间", "小号","扫码人数",
                            "复制暗号人数","累计加好友人数", "扫码转化率","当前好友人数","已删好友人数",
                            "好友留存率","已发消息量","群分类数量","累计进群人数","当前群总人数", "群消息数量",
                            "资源服务数量","资源点击人数","资源点击次数","社群书平均浏览时长","单个服务平均浏览时长",
                            "购买人数", "销售额"};
        String fileName = "个人号统计--" + DateUtils.getStrFormTime("yyyyMMdd", date);
        String fileUrl = exportConsr.exportExcel(fileName, rowsName, dataList);
        String letterType = "pcloud_book_group_serve";
        String content = String.format("{\"commitTime\":\"%s\",\"type\":\"%s\"}", DateUtils.formatDate(date), fileName);
        messageConsr.sendLetter(partyId, partyId, content, systemCode, letterType, fileUrl, fileName, NotifyOriginTypeEnum.BOOK_GROUP.value, null);
    }

    @ParamLog("填充个人号统计其他信息")
    private void fillStInfo(List<SelfBookGroupStDTO> list) {
        if (ListUtils.isEmpty(list)) {
            return;
        }
        List<Long> bookGroupIds = list.stream().filter(s -> s.getBookGroupId() != null).map(SelfBookGroupStDTO::getBookGroupId).distinct().collect(Collectors.toList());
        fillAltInfo(list);
        fillAgentNameAdviserNameLabel(list);
        fillGroupInfoAbout(list, bookGroupIds);
        fillServeAbout(list, bookGroupIds);
        fillScanPeopleCount(list, bookGroupIds);
        fillAccAddFriendCount(list, bookGroupIds);
        fillBrowse(list,bookGroupIds);
        fillSaleAbout(list,bookGroupIds);
        fillSendMessageCount(list,bookGroupIds);
        fillPreFriend(list, bookGroupIds);
        fillDefault(list);
    }

    @ParamLog("填充默认值")
    private void fillDefault(List<SelfBookGroupStDTO> list) {
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            if (selfBookGroupStDTO.getAccAddFriendCount() == null) {
                selfBookGroupStDTO.setAccAddFriendCount(0);
            }
            if (selfBookGroupStDTO.getDelFriendCount() == null) {
                selfBookGroupStDTO.setDelFriendCount(0);
            }
            if (selfBookGroupStDTO.getSaleAmount() == null) {
                selfBookGroupStDTO.setSaleAmount(0D);
            }
            if (selfBookGroupStDTO.getBuyPeopleCount() == null) {
                selfBookGroupStDTO.setBuyPeopleCount(0L);
            }
            if (selfBookGroupStDTO.getOneServeBrowseTime() == null) {
                selfBookGroupStDTO.setOneServeBrowseTime(0L);
            }
            if (selfBookGroupStDTO.getAvgBrowseTime() == null) {
                selfBookGroupStDTO.setAvgBrowseTime(0L);
            }
            if (selfBookGroupStDTO.getServeClickCount() == null) {
                selfBookGroupStDTO.setServeClickCount(0);
            }
            if (selfBookGroupStDTO.getServeClickPeopleCount() == null) {
                selfBookGroupStDTO.setServeClickPeopleCount(0);
            }
            if (selfBookGroupStDTO.getServeCount() == null) {
                selfBookGroupStDTO.setServeCount(0);
            }
            if (selfBookGroupStDTO.getGroupMessageCount() == null) {
                selfBookGroupStDTO.setGroupMessageCount(0);
            }
            if (selfBookGroupStDTO.getPreInGroupPeopleCount() == null) {
                selfBookGroupStDTO.setPreInGroupPeopleCount(0);
            }
            if (selfBookGroupStDTO.getAccJoinGroupCount() == null) {
                selfBookGroupStDTO.setAccJoinGroupCount(0);
            }
            if (selfBookGroupStDTO.getClassifyCount() == null) {
                selfBookGroupStDTO.setClassifyCount(0);
            }
            if (selfBookGroupStDTO.getSendMessageCount() == null) {
                selfBookGroupStDTO.setSendMessageCount(0);
            }
            if (selfBookGroupStDTO.getFriendKeepRate() == null) {
                selfBookGroupStDTO.setFriendKeepRate(0D);
            }
            if (selfBookGroupStDTO.getPreFriendCount() == null) {
                selfBookGroupStDTO.setPreFriendCount(0);
            }
            if (selfBookGroupStDTO.getScanConversionRate() == null) {
                selfBookGroupStDTO.setScanConversionRate(0D);
            }
            if (selfBookGroupStDTO.getCopyCipherPeopleCount() == null) {
                selfBookGroupStDTO.setCopyCipherPeopleCount(0);
            }
            if (selfBookGroupStDTO.getScanPeopleCount() == null) {
                selfBookGroupStDTO.setScanPeopleCount(0);
            }
            if (selfBookGroupStDTO.getAltIdAndNameDTOS() == null) {
                selfBookGroupStDTO.setAltIdAndNameDTOS(new ArrayList<>());
            }
        }
    }

    @ParamLog("填充当前好友人数 已删好友人数 好友留存率")
    private void fillPreFriend(List<SelfBookGroupStDTO> list, List<Long> bookGroupIds) {
        List<BookGroupCipherUser> alts = bookGroupCipherUserDao.getWxUserIdAndAltsByBookGroupIds(bookGroupIds);
        if (ListUtils.isEmpty(alts)) {
            return;
        }
        //调内部接口获取是否还是好友关系
        List<AltAndUserDTO> altAndUserDTOS = new ArrayList<>();
        for (BookGroupCipherUser bgcu : alts) {
            AltAndUserDTO altAndUserDTO = new AltAndUserDTO();
            altAndUserDTO.setAltId(bgcu.getAltId());
            altAndUserDTO.setWxUserId(bgcu.getWxUserId());
            altAndUserDTOS.add(altAndUserDTO);
        }
        List<AltAndUserResultDTO> dtos = wechatGroupConsr.listAltAndUserRelationship(altAndUserDTOS);
        if (ListUtils.isEmpty(dtos)) {
            return;
        }
        Map<String, Boolean> map = new HashMap<>();
        for (AltAndUserResultDTO altAndUserResultDTO : dtos) {
            map.put(altAndUserResultDTO.getAltId() + altAndUserResultDTO.getWxUserId(), altAndUserResultDTO.getIsFriend());
        }
        Map<Long, List<BookGroupCipherUser>> altMap = alts.stream().collect(Collectors.groupingBy(BookGroupCipherUser::getBookGroupId));
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            Long bookGroupId = selfBookGroupStDTO.getBookGroupId();
            List<BookGroupCipherUser> userList = altMap.get(bookGroupId);
            if (!ListUtils.isEmpty(userList)) {
                Integer preFriendCount = 0;
                for (BookGroupCipherUser bookGroupCipherUser : userList) {
                    Boolean isFriend = map.get(bookGroupCipherUser.getAltId() + bookGroupCipherUser.getWxUserId());
                    if (isFriend != null && isFriend) {
                        preFriendCount = preFriendCount + 1;
                    }
                }
                selfBookGroupStDTO.setPreFriendCount(preFriendCount);
                selfBookGroupStDTO.setDelFriendCount(selfBookGroupStDTO.getAccAddFriendCount() - preFriendCount);
                if (preFriendCount == null || selfBookGroupStDTO.getAccAddFriendCount() == null || selfBookGroupStDTO.getAccAddFriendCount() == 0) {
                    selfBookGroupStDTO.setFriendKeepRate(0D);
                } else {
                    selfBookGroupStDTO.setFriendKeepRate(selfBookGroupStDTO.getPreFriendCount().doubleValue() / selfBookGroupStDTO.getAccAddFriendCount().doubleValue());
                }
            } else {
                selfBookGroupStDTO.setPreFriendCount(0);
                selfBookGroupStDTO.setDelFriendCount(0);
                selfBookGroupStDTO.setFriendKeepRate(0D);
            }
        }
    }

    @ParamLog("填充发送消息数量")
    private void fillSendMessageCount(List<SelfBookGroupStDTO> list, List<Long> bookGroupIds) {
        List<BookGroupCipherUser> alts = bookGroupCipherUserDao.getWxUserIdAndAltsByBookGroupIds(bookGroupIds);
        if (ListUtils.isEmpty(alts)) {
            return;
        }
        List<String> wxUserIds = alts.stream().filter(s -> s.getWxUserId() != null).map(BookGroupCipherUser::getWxUserId).collect(Collectors.toList());
        Map<String, Integer> messageCountMap = wechatGroupConsr.mapReceiveMsgCountByIds(wxUserIds);
        Map<Long, List<BookGroupCipherUser>> altMap = alts.stream().collect(Collectors.groupingBy(BookGroupCipherUser::getBookGroupId));
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            Integer sendMessageCount = 0;
            Long bookGroupId = selfBookGroupStDTO.getBookGroupId();
            List<BookGroupCipherUser> bgcus = altMap.get(bookGroupId);
            if (bgcus!=null){
                List<String> wxIds = bgcus.stream().filter(s -> s.getWxUserId() != null).map(BookGroupCipherUser::getWxUserId).collect(Collectors.toList());
                for (String wxId : wxIds) {
                    if (messageCountMap.get(wxId) != null) {
                        sendMessageCount = sendMessageCount + messageCountMap.get(wxId);
                    }
                }
            }
            selfBookGroupStDTO.setSendMessageCount(sendMessageCount);
        }
    }

    @ParamLog("查询销售相关")
    private void fillSaleAbout(List<SelfBookGroupStDTO> list, List<Long> bookGroupIds) {
        Map<Long, ProductSaleDetailDto> map = tradeConsr.getSaleInfo4Group(bookGroupIds, null);
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            Long buyPeopleCount = 0L;
            Double saleAmount = 0D;
            ProductSaleDetailDto productSaleDetailDto = map.get(selfBookGroupStDTO.getBookGroupId());
            if (productSaleDetailDto != null) {
                if (productSaleDetailDto.getPayCount() != null) {
                    buyPeopleCount = productSaleDetailDto.getPayCount();
                }
                if (productSaleDetailDto.getSaleMoney() != null) {
                    saleAmount = productSaleDetailDto.getSaleMoney();
                }
            }
            //购买人数
            selfBookGroupStDTO.setBuyPeopleCount(buyPeopleCount);
            //销售额
            selfBookGroupStDTO.setSaleAmount(saleAmount);
        }
    }

    @ParamLog("填充浏览时长相关")
    private void fillBrowse(List<SelfBookGroupStDTO> list, List<Long> bookGroupIds) {
        Map<Long, GroupBrowseStatisticVO> bookGroupBrowseMap = browseRecordConsr.mapGroupBrowseStatistic(bookGroupIds, null);
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            Long avgBrowseTime = 0L;
            Long oneServeBrowseTime = 0L;
            GroupBrowseStatisticVO groupBrowseStatisticVO = bookGroupBrowseMap.get(selfBookGroupStDTO.getBookGroupId());
            if (groupBrowseStatisticVO != null && groupBrowseStatisticVO.getBrowseTimes() != null
                    && groupBrowseStatisticVO.getBrowserCount() != null && groupBrowseStatisticVO.getBrowserCount() != 0) {
                avgBrowseTime = groupBrowseStatisticVO.getBrowseTimes() / groupBrowseStatisticVO.getBrowserCount();
            }
            if (groupBrowseStatisticVO != null && groupBrowseStatisticVO.getBrowseTimes() != null
                    && selfBookGroupStDTO.getServeCount() != null && selfBookGroupStDTO.getServeCount() != 0) {
                oneServeBrowseTime = groupBrowseStatisticVO.getBrowseTimes() / selfBookGroupStDTO.getServeCount();
            }
            selfBookGroupStDTO.setAvgBrowseTime(avgBrowseTime);
            selfBookGroupStDTO.setOneServeBrowseTime(oneServeBrowseTime);
        }
    }

    @ParamLog("填充累计加好友人数")
    private void fillAccAddFriendCount(List<SelfBookGroupStDTO> list, List<Long> bookGroupIds) {
        List<BookGroupIdAndCountDTO> dtos = bookGroupCipherUserDao.getAddFriendByBookGroupIds(bookGroupIds);
        Map<Long, Integer> map = new HashMap<>();
        for (BookGroupIdAndCountDTO se : dtos) {
            map.put(se.getBookGroupId(), se.getCount());
        }
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            Long bookGroupId = selfBookGroupStDTO.getBookGroupId();
            Integer accAddFriendCount = map.get(bookGroupId) == null ? 0 : map.get(bookGroupId);
            selfBookGroupStDTO.setAccAddFriendCount(accAddFriendCount);
            Integer scanPeopleCount = selfBookGroupStDTO.getScanPeopleCount();
            //扫码转化率
            if (scanPeopleCount == null || scanPeopleCount == 0) {
                selfBookGroupStDTO.setScanConversionRate(0D);
            } else {
                selfBookGroupStDTO.setScanConversionRate(accAddFriendCount.doubleValue() / scanPeopleCount.doubleValue());
            }

        }
    }

    @ParamLog("填充扫码人数")
    private void fillScanPeopleCount(List<SelfBookGroupStDTO> list, List<Long> bookGroupIds) {
        Map<Long, Integer> scanMap = ResponseHandleUtil.parseMap(groupMemberService.getScanUserCountByGroup(bookGroupIds), Long.class, Integer.class);
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            Long bookGroupId = selfBookGroupStDTO.getBookGroupId();
            selfBookGroupStDTO.setScanPeopleCount(scanMap.get(bookGroupId) == null ? 0 : scanMap.get(bookGroupId));
        }
    }

    @ParamLog("填充资源相关")
    private void fillServeAbout(List<SelfBookGroupStDTO> list, List<Long> bookGroupIds) {
        //资源数量
        List<BookGroupIdAndCountDTO> serveDTOS = bookGroupAppDao.getServerCountByBookGroupIds(bookGroupIds);
        Map<Long, Integer> serveCountMap = new HashMap<>();
        for (BookGroupIdAndCountDTO se : serveDTOS) {
            serveCountMap.put(se.getBookGroupId(), se.getCount());
        }
        //点击复制暗号人数
        List<BookGroupIdAndCountDTO> copyCipherDTOS = copyCipherRecordDao.getCountByBookGroupIds(bookGroupIds);
        Map<Long, Integer> copyCipherCountMap = new HashMap<>();
        for (BookGroupIdAndCountDTO se : copyCipherDTOS) {
            copyCipherCountMap.put(se.getBookGroupId(), se.getCount());
        }
        //资源点击人数
        List<BookGroupIdAndCountDTO> serveClickPeopleCounts = appClickRecordDao.getClPeCoByBookGroupIds(bookGroupIds);
        Map<Long, Integer> serveClickPeCountMap = new HashMap<>();
        for (BookGroupIdAndCountDTO se : serveClickPeopleCounts) {
            serveClickPeCountMap.put(se.getBookGroupId(), se.getCount());
        }
        //资源点击次数
        List<BookGroupIdAndCountDTO> serveClickCounts = appClickRecordDao.getClCoByBookGroupIds(bookGroupIds);
        Map<Long, Integer> serveClickCountMap = new HashMap<>();
        for (BookGroupIdAndCountDTO se : serveClickCounts) {
            serveClickCountMap.put(se.getBookGroupId(), se.getCount());
        }
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            Long bookGroupId = selfBookGroupStDTO.getBookGroupId();
            selfBookGroupStDTO.setServeCount(serveCountMap.get(bookGroupId) == null ? 0 : serveCountMap.get(bookGroupId));
            selfBookGroupStDTO.setCopyCipherPeopleCount(copyCipherCountMap.get(bookGroupId) == null ? 0 : copyCipherCountMap.get(bookGroupId));
            selfBookGroupStDTO.setServeClickPeopleCount(serveClickPeCountMap.get(bookGroupId) == null ? 0 : serveClickPeCountMap.get(bookGroupId));
            selfBookGroupStDTO.setServeClickCount(serveClickCountMap.get(bookGroupId) == null ? 0 : serveClickCountMap.get(bookGroupId));
        }
    }

    @ParamLog("填充群相关")
    private void fillGroupInfoAbout(List<SelfBookGroupStDTO> list, List<Long> bookGroupIds) {
        List<SelfBookGroupStDTO> classifyInfos = bookGroupClassifyDao.listClassifyCountInfo(bookGroupIds);
        Map<Long, SelfBookGroupStDTO> map = new HashMap<>();
        for (SelfBookGroupStDTO selfBookGroupStDTO : classifyInfos) {
            map.put(selfBookGroupStDTO.getBookGroupId(), selfBookGroupStDTO);
        }
        //群消息数量
        Map<Long, GroupMsgCountDTO> groupMsgCountDTOMap = wechatGroupConsr.mapBookGroupMsgCount(bookGroupIds);
        //累计进群人数
        Map<Long, GroupUserCountDTO> groupUserCountDTOMap = wechatGroupConsr.mapBookGroupJoinUserCount(bookGroupIds, null);
        for (SelfBookGroupStDTO sel : list) {
            SelfBookGroupStDTO selfBookGroupStDTO = map.get(sel.getBookGroupId());
            if (selfBookGroupStDTO != null) {
                sel.setClassifyCount(selfBookGroupStDTO.getClassifyCount());
                sel.setPreInGroupPeopleCount(selfBookGroupStDTO.getPreInGroupPeopleCount());
            } else {
                sel.setClassifyCount(0);
                sel.setPreInGroupPeopleCount(0);
            }
            GroupMsgCountDTO groupMsgCountDTO=groupMsgCountDTOMap.get(sel.getBookGroupId());
            if (groupMsgCountDTO != null) {
                sel.setGroupMessageCount(groupMsgCountDTO.getMsgCount());
            } else {
                sel.setGroupMessageCount(0);
            }
            GroupUserCountDTO groupUserCountDTO=groupUserCountDTOMap.get(sel.getBookGroupId());
            if (groupUserCountDTO != null) {
                sel.setAccJoinGroupCount(groupUserCountDTO.getUserCount());
            } else {
                sel.setAccJoinGroupCount(0);
            }
        }
    }

    @ParamLog("填充出版社名称和编辑名称和标签")
    private void fillAgentNameAdviserNameLabel(List<SelfBookGroupStDTO> list) {
        List<Long> adviserIds=new ArrayList<>();
        List<Long> agentIds=new ArrayList<>();
        List<Long> labelIds=new ArrayList<>();
        for(SelfBookGroupStDTO selfBookGroupStDTO:list){
            if (!adviserIds.contains(selfBookGroupStDTO.getAdviserId())){
                adviserIds.add(selfBookGroupStDTO.getAdviserId());
            }
            if (!agentIds.contains(selfBookGroupStDTO.getAgentId())){
                agentIds.add(selfBookGroupStDTO.getAgentId());
            }
            if (!labelIds.contains(selfBookGroupStDTO.getDepLabelId()) && selfBookGroupStDTO.getDepLabelId() != null) {
                labelIds.add(selfBookGroupStDTO.getDepLabelId());
            }
            if (!labelIds.contains(selfBookGroupStDTO.getPurLabelId()) && selfBookGroupStDTO.getPurLabelId() != null) {
                labelIds.add(selfBookGroupStDTO.getPurLabelId());
            }
        }
        Map<Long, String> adviserNamesMap = adviserConsr.getNames(adviserIds);
        Map<Long, String> agentNamesMap = agentConsr.getNames(agentIds);
        Map<Long, String> labelMap = new HashMap<>();
        if (!ListUtils.isEmpty(labelIds)) {
            labelMap = ResponseHandleUtil.parseMap(labelService.getLabelName(labelIds), Long.class, String.class);
        }
        for (SelfBookGroupStDTO selfBookGroupStDTO:list){
            selfBookGroupStDTO.setAdviserName(adviserNamesMap.get(selfBookGroupStDTO.getAdviserId()));
            selfBookGroupStDTO.setAgentName(agentNamesMap.get(selfBookGroupStDTO.getAgentId()));
            selfBookGroupStDTO.setDepLabelName(labelMap.get(selfBookGroupStDTO.getDepLabelId()));
            selfBookGroupStDTO.setPurLabelName(labelMap.get(selfBookGroupStDTO.getPurLabelId()));
        }
    }

    @ParamLog("填充小号信息")
    private void fillAltInfo(List<SelfBookGroupStDTO> list) {
        List<Long> bookGroupIds = list.stream().filter(s -> s.getBookGroupId() != null).map(SelfBookGroupStDTO::getBookGroupId).collect(Collectors.toList());
        //填充个人号信息
        List<BookGroupAgentRecord> bookGroupAgentRecords = bookGroupAgentRecordDao.getAltIdByBookGroupIds(bookGroupIds);
        List<String> specialAltIds = new ArrayList<>();
        List<Long> specialBookGroupIds = new ArrayList<>();
        Map<Long, List<BookGroupAgentRecord>> spGroups = new HashMap<>();
        if (!ListUtils.isEmpty(bookGroupAgentRecords)) {
            spGroups = bookGroupAgentRecords.stream().collect(Collectors.groupingBy(BookGroupAgentRecord::getBookGroupId));
            for (BookGroupAgentRecord bookGroupAgentRecord : bookGroupAgentRecords) {
                if (!specialAltIds.contains(bookGroupAgentRecord.getAltId())) {
                    specialAltIds.add(bookGroupAgentRecord.getAltId());
                }
                specialBookGroupIds.add(bookGroupAgentRecord.getBookGroupId());
            }
        }
        bookGroupIds.removeAll(specialBookGroupIds);
        List<BookGroupCipherUser> bookGroupCipherUsers = bookGroupCipherUserDao.getAltIdByBookGroupIds(bookGroupIds);
        List<String> norAltIds = new ArrayList<>();
        List<Long> norBookGroupIds = new ArrayList<>();
        Map<Long, List<BookGroupCipherUser>> norGroups = new HashMap<>();
        if (!ListUtils.isEmpty(bookGroupCipherUsers)) {
            norGroups = bookGroupCipherUsers.stream().collect(Collectors.groupingBy(BookGroupCipherUser::getBookGroupId));
            for (BookGroupCipherUser bookGroupCipherUser : bookGroupCipherUsers) {
                if (!specialAltIds.contains(bookGroupCipherUser.getAltId())) {
                    norAltIds.add(bookGroupCipherUser.getAltId());
                }
                norBookGroupIds.add(bookGroupCipherUser.getBookGroupId());
            }
        }

        List<String> allAltIds=new ArrayList<>();
        allAltIds.addAll(specialAltIds);
        allAltIds.addAll(norAltIds);
        Map<String, RobotBaseInfoDTO> altsMap = wechatGroupConsr.mapRobotInfo(allAltIds);
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            List<AltIdAndNameDTO> altIdAndNameDTOS = new ArrayList<>();
            if (specialBookGroupIds.contains(selfBookGroupStDTO.getBookGroupId())) {
                List<BookGroupAgentRecord> records = spGroups.get(selfBookGroupStDTO.getBookGroupId());
                if (!ListUtils.isEmpty(records)) {
                    for (BookGroupAgentRecord b : records) {
                        AltIdAndNameDTO altIdAndNameDTO = new AltIdAndNameDTO();
                        altIdAndNameDTO.setAltId(b.getAltId());
                        if (altsMap.get(b.getAltId())!=null){
                            altIdAndNameDTO.setAltName(altsMap.get(b.getAltId()).getNickName());
                        }
                        altIdAndNameDTOS.add(altIdAndNameDTO);
                    }
                }
            } else {
                List<BookGroupCipherUser> records = norGroups.get(selfBookGroupStDTO.getBookGroupId());
                if (!ListUtils.isEmpty(records)) {
                    for (BookGroupCipherUser b : records) {
                        AltIdAndNameDTO altIdAndNameDTO = new AltIdAndNameDTO();
                        altIdAndNameDTO.setAltId(b.getAltId());
                        if (altsMap.get(b.getAltId())!=null){
                            altIdAndNameDTO.setAltName(altsMap.get(b.getAltId()).getNickName());
                        }
                        altIdAndNameDTOS.add(altIdAndNameDTO);
                    }
                }
            }
            selfBookGroupStDTO.setAltIdAndNameDTOS(altIdAndNameDTOS);
        }
    }

    @Override
    public PageBeanNew<UserBookInfoVO> listUser4SelfPush(UserSelectParamDTO userSelectParamDTO) {
        Integer currentPage = userSelectParamDTO.getCurrentPage();
        Integer numPerPage = userSelectParamDTO.getNumPerPage();
        Map<String, Object> map = new HashMap<>();
        //判断robotid是否是小睿
        String robotId = userSelectParamDTO.getRobotId();
        Integer groupRobotType = userSelectParamDTO.getGroupRobotType();
        List<UserBookInfoVO> list = new ArrayList<>();
        Integer totalCount = 0;

        if (StringUtil.isEmpty(robotId)){
            throw new BizException(BizException.PARAM_IS_NULL.getCode(),"robotId为空");
        }
        if (null == groupRobotType) {
            groupRobotType = AltTypeEnum.WECHAT.code;
        }
        PcloudRobot pcloudRobot = pcloudRobotBiz.getPcloudRobotByWxId(robotId);
        if (null != pcloudRobot){
            PageBeanNew<String>  wechatUserIdPage = wechatGroupConsr.listPageFriend(currentPage,numPerPage,
                   robotId,userSelectParamDTO.getUserQuery(),groupRobotType);
            if (!ListUtils.isEmpty(wechatUserIdPage.getRecordList())){
                List<String>  wechatUserIds = wechatUserIdPage.getRecordList();
                list = groupSet.setUserBookInfo4SelfPush4XIAORUI(wechatUserIds,groupRobotType);
                totalCount = wechatUserIdPage.getTotalCount();
            }
        }else {
            //用户昵称id模糊查询
            if (!StringUtil.isEmpty(userSelectParamDTO.getUserQuery())) {
                List<String> wxUserIds = wechatGroupConsr.getByUserQuery(userSelectParamDTO.getUserQuery());
                if (!ListUtils.isEmpty(wxUserIds)) {
                    map.put("wxUserIds", wxUserIds);
                } else {
                    return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
                }
            }
            map.put("depLabelId", userSelectParamDTO.getDepLabelId());
            map.put("proLabelId", userSelectParamDTO.getProLabelId());
            map.put("altId", userSelectParamDTO.getRobotId());
            map.put("bookIds", userSelectParamDTO.getBookIds());
            List<UserBookInfoVO> countlist = bookGroupCipherUserDao.listUser4SelfPush(map);
            if (ListUtils.isEmpty(countlist)) {
                return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
            }
            map.put("pageNum", currentPage * numPerPage);
            map.put("numPerPage", numPerPage);
            list = bookGroupCipherUserDao.listUser4SelfPush(map);
            //填充个人号群发用户信息、扫码书刊信息
            groupSet.setUserBookInfo4SelfPush(list);
            totalCount = countlist.size();
        }
        return new PageBeanNew<>(currentPage, numPerPage,totalCount, list);

    }

    @Override
    public PageBeanNew<UserBookInfoVO> listUser4SelfPushByAdvise(Map<String,Object> userSelectParam) {
        Integer currentPage = (Integer) userSelectParam.get("currentPage");
        Integer numPerPage = (Integer) userSelectParam.get("numPerPage");
        Map<String, Object> map = new HashMap<>();
        //用户昵称id模糊查询
        if (!StringUtil.isEmpty((CharSequence) userSelectParam.get("userQuery"))) {
            List<String> wxUserIds = wechatGroupConsr.getByUserQuery((String) userSelectParam.get("userQuery"));
            if (!ListUtils.isEmpty(wxUserIds)) {
                map.put("wxUserIds", wxUserIds);
            } else {
                return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
            }
        }
        map.put("bookId",userSelectParam.get("bookId"));
        List<UserBookInfoVO> countlist = bookGroupCipherUserDao.listUser4SelfPushByAdvise(map);
        if (ListUtils.isEmpty(countlist)) {
            return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
        }
        map.put("pageNum", currentPage * numPerPage);
        map.put("numPerPage", numPerPage);
        List<UserBookInfoVO> list = bookGroupCipherUserDao.listUser4SelfPushByAdvise(map);
        //填充个人号群发用户信息、扫码书刊信息
        groupSet.setUserBookInfo4SelfPush(list);
        return new PageBeanNew<>(currentPage, numPerPage, countlist.size(), list);
    }

    @ParamLog("根据类型获取社群书id集合")
    @Override
    public List<Long> getBookGroupIdsByJoinGroupType(Integer joinGroupType) {
        List<Long> bookGroupIds = bookGroupDao.getIdsByJoinGroupType(joinGroupType);
        return bookGroupIds;
    }

    @ParamLog("获取随机码")
    @Override
    public String getRandomCode(Long wechatUserId) {
        if (wechatUserId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "微信id为空！");
        }
        //先查询数据库
        WxUserWechatRelevance wxUserWechatRelevance = wxUserWechatRelevanceDao.getByWechatUserId(wechatUserId);
        if (wxUserWechatRelevance != null) {
            return wxUserWechatRelevance.getRandomCode();
        }
        //之前没有就新增
        WxUserWechatRelevance wechatRelevanceNew = new WxUserWechatRelevance();
        wechatRelevanceNew.setWechatUserId(wechatUserId);
        String randomCode = createRandomCode();
        //校验库里面有没有
        WxUserWechatRelevance toCheck = wxUserWechatRelevanceDao.getByRandomCode(randomCode);
        if (toCheck != null) {
            //重新获取
            randomCode = createRandomCode();
        }
        wechatRelevanceNew.setRandomCode(randomCode);
        //新增
        wxUserWechatRelevanceDao.insert(wechatRelevanceNew);
        return randomCode;
    }

    @Override
    @ParamLog
    @Transactional(rollbackFor = Exception.class)
    public Long changeQrCodeType(ChangeQrCodeTypeDto changeQrCodeTypeDto) {
        Long id = changeQrCodeTypeDto.getId();
        String type = changeQrCodeTypeDto.getType();
        Long bookGroupId = null;
        if (ChangeOriginTypeEnum.SCENE.getType().equals(type)) {
            bookGroupId = changeRaysBook2SelfRobotQr(id);
        } else if (ChangeOriginTypeEnum.BOOK_GROUP.getType().equals(type)) {
            bookGroupId = changeSheQun2SelfRobotQr(id);
        }
        return bookGroupId;
    }

    @Override
    public Long getChangeQrChangeTarget(Long originId, String originType) {
        return bookGroupDao.getChangeQrChangeTarget(originId, originType);
    }

    /**
     * 将现代纸书转换为个人自由码
     */
    private Long changeRaysBook2SelfRobotQr(Long sceneId) {
        QrcodeSceneDto qrcodeSceneDto = qrcodeSceneConsr.getById(sceneId);
        if (null == sceneId) {
            return null;
        }
        String qrCodeUrl = qrcodeSceneDto.getQrcodeUrl();
        String qrcodeType = qrcodeSceneDto.getQrcodeType();
        //先创建
        BookGroup bookGroup = this.createBookGroupAfterCreateBook(qrcodeSceneDto.getAdviserBookId(), qrcodeSceneDto.getChannelPartyId(), qrcodeSceneDto.getCreatedByUserLogin(), 2, sceneId,
                JoinGroupTypeEnum.ROBOT.getCode());
        //公众号码才需要覆盖sceneId
        bookGroup.setGroupQrcodeUrl(qrCodeUrl);
        if (ChannelConstants.QrCodeType.WECHAT.getName().equals(qrcodeType)) {
            bookGroup.setSceneId(sceneId);
        }
        //替换二维码
        bookGroupDao.update(bookGroup);
        //插入旧码下的资源
        Long newBookGroupId = bookGroup.getId();
        List<MessageDto> messages = qrcodeSceneDto.getMessages();
        if (!ListUtils.isEmpty(messages)) {
            List<BookGroupServe> list = new ArrayList<>();
            messages.forEach(item -> {
                BookGroupServe bookGroupServe = new BookGroupServe();
                bookGroupServe.setBookGroupId(newBookGroupId);
                bookGroupServe.setServeId(item.getFromId());
                bookGroupServe.setServeType(item.getTypeCode());
                bookGroupServe.setServeUrl(item.getUrl());
                list.add(bookGroupServe);
            });
            batchUpdateBookGroupServe(qrcodeSceneDto.getAdviserId(), list);
            bookGroupDao.updateIsSomeUpdate(newBookGroupId, true);
        }
        qrcodeSceneConsr.updateQrcodeToSelfRobotQrcode(sceneId, qrcodeSceneDto.getAdviserBookId());
        //插入转换记录表
        QrChangeRecord qrChangeRecord = QrChangeRecord.builder().oldSceneId(sceneId).newBookGroupId(newBookGroupId).build();
        bookGroupDao.insertQrChangeRecord(qrChangeRecord);
        return newBookGroupId;
    }

    /**
     * 社群书换为个人码的自由码
     */
    private Long changeSheQun2SelfRobotQr(Long oldBookGroupId) {
        //拿到旧的社群码
        BookGroupDTO bookInfo = bookGroupDao.getDTOById(oldBookGroupId);
        if (null == bookInfo) {
            return null;
        }
        Long sceneId = bookInfo.getSceneId();
        //如果已经是个人码,不管是微信码还是自建码，都直接返回
        if (JoinGroupTypeEnum.ROBOT.getCode().equals(bookInfo.getJoinGroupType())) {
            return null;
        }
        //创建新的社群码
        BookGroup bookGroup = this.createBookGroupAfterCreateBook(bookInfo.getBookId(), bookInfo.getChannelId(), bookInfo.getCreateUser(), 2, sceneId, JoinGroupTypeEnum.ROBOT.getCode());
        //替换qrCodeUrl
        bookGroup.setGroupQrcodeUrl(bookInfo.getGroupQrcodeUrl());
        bookGroup.setSceneId(sceneId);
        bookGroupDao.update(bookGroup);

        Long newBookGroupId = bookGroup.getId();
        //3.把旧码下的应用类关键词配置成资源
        List<BookGroupKeywordResourceDTO> bookGroupResourceList = bookKeywordDao.getBookGroupResourceList(oldBookGroupId);
        if (!ListUtils.isEmpty(bookGroupResourceList)) {
            List<BookGroupServe> bookGroupServes = new ArrayList<>();
            bookGroupResourceList.forEach(item -> {
                BookGroupServe bookGroupServe = new BookGroupServe();
                bookGroupServe.setBookGroupId(newBookGroupId);
                bookGroupServe.setServeType(item.getServeType());
                bookGroupServe.setServeUrl(item.getServeUrl());
                bookGroupServe.setServeId(item.getServeId());
                bookGroupServes.add(bookGroupServe);
            });
            batchUpdateBookGroupServe(bookInfo.getCreateUser(), bookGroupServes);
        }
        //删除旧数据
        bookGroupDao.deleteByBookGroupId(oldBookGroupId);
        //插入转换记录表
        QrChangeRecord qrChangeRecord = QrChangeRecord.builder().oldBookGroupId(oldBookGroupId).newBookGroupId(newBookGroupId).build();
        bookGroupDao.insertQrChangeRecord(qrChangeRecord);
        if (sceneId != null) {
            qrcodeSceneConsr.updateQrcodeToSelfRobotQrcode(sceneId, bookInfo.getBookId());
        }
        return newBookGroupId;
    }

    @ParamLog("获取社群书信息")
    @Override
    public PageBeanNew<BookGroupDTO> getListBookGroup4Adviser(Map<String, Object>paramMap, PageParam pageParam) {
        PageBeanNew<BookGroupDTO> pageBean = bookGroupDao.listPageNew(pageParam, paramMap, "getListBookGroup4Adviser");
        if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBeanNew<>(pageParam.getNumPerPage(), pageParam.getNumPerPage(), 0, new ArrayList<>());
        }
        // 填充社群书数据
        List<BookGroupDTO> bookGroupDTOList=pageBean.getRecordList();
        //设置关联状态
        //1.获取1v1关联社群书
        List<BookGroupDTO> bookGroupAssoList=bookGroupDao.getAssocBookGroupByAppInfo(paramMap);
        //2.获取关联bookId和bookGroupId
        for (BookGroupDTO bookGroupDTO:bookGroupDTOList){
            for(BookGroupDTO bookGroupAsso : bookGroupAssoList){
                if (bookGroupDTO.getBookId().equals(bookGroupAsso.getBookId())&&bookGroupDTO.getId().equals(bookGroupAsso.getId())){
                    bookGroupDTO.setAssocState(true);
                    break;
                }else {
                    bookGroupDTO.setAssocState(false);
                }
            }
        }
        fillBookGroupServe(bookGroupDTOList);
        return pageBean;
    }

    @ParamLog("获取1v1社群书关联信息")
    @Override
    public PageBeanNew<BookGroupDTO> getAssocBookGroupByAppInfo(Map<String, Object>paramMap, PageParam pageParam) {
        if(null == paramMap.get("channelId")||null == paramMap.get("serveId")||null == paramMap.get("serveType")) {
            throw new BookBizException(BookBizException.ERROR,"缺少必要参数！");
        }
        PageBeanNew<BookGroupDTO> pageBean = bookGroupDao.listPageNew(pageParam, paramMap, "getAssocBookGroupByAppInfo");
        if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBeanNew<>(pageParam.getNumPerPage(), pageParam.getNumPerPage(), 0, new ArrayList<>());
        }
        return pageBean;
    }

    @ParamLog("获取1v1社群书关联名称和数量")
    @Override
    public List<BookGroupDTO> getAssocBookGroupByServeInfo(Long adviserId,Long serveId,String serveType) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("serveId", serveId);
        paramMap.put("serveType", serveType);
        paramMap.put("adviserId", adviserId);
        if(null == paramMap.get("serveId")||null == paramMap.get("serveType")) {
            throw new BookBizException(BookBizException.ERROR,"缺少必要参数！");
        }
        List<BookGroupDTO> bookGroupDtos=bookGroupDao.getAssocBookGroupByAppInfo(paramMap);
        return bookGroupDtos;
    }

    @Override
    public List<BookGroupCountDTO> getAssocBookGroupCount(List<BookGroupCountDTO> dtos) {
        if (ListUtils.isEmpty(dtos)){
            return new ArrayList<>();
        }
        Long adviserId = dtos.get(0).getAdviserId();
        List<Long> appIds = dtos.stream().filter(d -> AppAndProductTypeEnum.APP.value.equals(d.getServeType()))
                .map(BookGroupCountDTO::getServeId).collect(Collectors.toList());
        List<Long> productIds = dtos.stream().filter(d -> AppAndProductTypeEnum.PRODUCT.value.equals(d.getServeType()))
                .map(BookGroupCountDTO::getServeId).collect(Collectors.toList());
        List<BookGroupCountDTO> resultDtos = new ArrayList<>();
        if (!ListUtils.isEmpty(appIds)){
            List<BookGroupCountDTO> countDtos = bookGroupServeDao.getCountByServeIds(appIds, AppAndProductTypeEnum.APP.value, adviserId);
            resultDtos.addAll(countDtos);
        }
        if (!ListUtils.isEmpty(productIds)){
            List<BookGroupCountDTO> countDtos = bookGroupServeDao.getCountByServeIds(productIds, AppAndProductTypeEnum.PRODUCT.value, adviserId);
            resultDtos.addAll(countDtos);
        }
        return resultDtos;
    }

	    @Override
    @ParamLog("ERP创建社群二维码")
    public ErpBookGroupDTO createGroupQrcode4Erp(ErpGroupQrcodeDTO erpGroupQrcodeDTO) {
        ErpBookGroupDTO bookGroupDTO = new ErpBookGroupDTO();

        Long bookId = erpGroupQrcodeDTO.getBookId();
        Long channelId = erpGroupQrcodeDTO.getChannelId();
        Long adviserId = erpGroupQrcodeDTO.getAdviserId();
        Integer addType = erpGroupQrcodeDTO.getAddType();
        Integer joinGroupType = erpGroupQrcodeDTO.getJoinGroupType();
        BookGroupDTO dto = bookGroupDao.getDTOByBookId(bookId, channelId, adviserId);
        if (null != dto) {
            bookGroupDTO.setCreateState("exist");
            return bookGroupDTO;
        }

        BookGroup bookGroup = this.createBookGroupAfterCreateBook(bookId, channelId, adviserId, addType, null, joinGroupType);
        bookGroup.setGroupQrcodeName(erpGroupQrcodeDTO.getGroupQrcodeName());
        bookGroup.setIsInviteGroup(true);
        if (JoinGroupTypeEnum.ROBOT.getCode().equals(joinGroupType)) {
            bookGroup.setAddFriendGuide("我是学习助手，请添加我为好友，我将为你提供本书配套资源服务");
            bookGroup.setCustomerServiceName("学习助手");
        } else {
            bookGroup.setJoinSlogan("请选择你喜欢的群分类，我们会根据你的选择，推荐进入对应的微信群，方便你与相同兴趣的群友交流");
            bookGroup.setJoinTitle("选择你想加入的微信群");
        }
        bookGroupDao.update(bookGroup);
        bookGroupDTO.setId(bookGroup.getId());
        bookGroupDTO.setGroupQrcodeUrl(bookGroup.getGroupQrcodeUrl());
        bookGroupDTO.setCreateState("success");
        return bookGroupDTO;
    }

    @ParamLog("填充资源配置名称和链接")
    private void fillBookGroupServe(List<BookGroupDTO> bookGroupDTOList) {
        if (ListUtils.isEmpty(bookGroupDTOList)){
            return;
        }
        List<Long> bookGroupIds= bookGroupDTOList.stream().filter(s -> s.getId() != null).map(BookGroupDTO::getId).collect(Collectors.toList());
        if (!ListUtils.isEmpty(bookGroupIds)) {
            List<BookGroupServe> bookGroupServeList=bookGroupServeDao.getListByBookGroupIds(bookGroupIds);
            List<Long> productIds = new ArrayList<>();
            List<Long> appIds = new ArrayList<>();
            for (BookGroupServe bookGroupServe : bookGroupServeList) {
                if (AppAndProductTypeEnum.PRODUCT.value.equals(bookGroupServe.getServeType())) {
                    productIds.add(bookGroupServe.getServeId());
                }
                if (AppAndProductTypeEnum.APP.value.equals(bookGroupServe.getServeType())) {
                    appIds.add(bookGroupServe.getServeId());
                }
            }
            Map<Long, ProductDto> productDtoMap = new HashMap<>();
            Map<Long, AppDto> appDtoMap = new HashMap<>();
            if (!ListUtils.isEmpty(productIds)) {
                productDtoMap = productConsr.getProBasesByIds(productIds);
            }
            if (!ListUtils.isEmpty(appIds)) {
                appDtoMap = appConsr.mapByIds(appIds);
            }
            for(BookGroupServe bookGroupServe:bookGroupServeList){
                if (AppAndProductTypeEnum.PRODUCT.value.equals(bookGroupServe.getServeType())) {
                    ProductDto productDto = productDtoMap.get(bookGroupServe.getServeId());
                    if (productDto != null) {
                        bookGroupServe.setServeName(productDto.getProductName());
                    }
                }
                if (AppAndProductTypeEnum.APP.value.equals(bookGroupServe.getServeType())) {
                    AppDto appDto = appDtoMap.get(bookGroupServe.getServeId());
                    if (appDto != null) {
                        bookGroupServe.setServeName(appDto.getTitle());
                    }
                }
            }
            Map<Long,List<BookGroupServe>> map=bookGroupServeList.stream().collect(Collectors.groupingBy(BookGroupServe::getBookGroupId));
            for(BookGroupDTO bookGroupDto : bookGroupDTOList){
                List<BookGroupServe> bookGroupServes = map.get(bookGroupDto.getId());
                bookGroupDto.setBookGroupServes(bookGroupServes);
            }

        }
    }

    @ParamLog("生成随机码")
    private String createRandomCode(){
        //生成暗号规则：abcdefg，7位字符串
        Random random = new Random();
        String s = "";
        for (int i = 0; i < 7; i++) {
            int result = 97 + random.nextInt(26);
            s = s + String.valueOf((char) result);
        }
        return s;
    }

    @Override
    public List<String> getFriendIdListByBookAndRobot(String altId, List<Long> bookIds) {
        return bookGroupCipherUserDao.getFriendIdListByBookAndRobot(altId, bookIds);
    }

    @Override
    public Map<String, List<UserBookBaseInfoDTO>> mapUserScanBook(String altId, List<String> wxUserIdList) {
        Map<String, List<UserBookBaseInfoDTO>> map = new HashMap<>();
        if (ListUtils.isEmpty(wxUserIdList)) {
            return new HashMap<>();
        }
        for (String wxUserId : wxUserIdList) {
            List<UserBookInfoItemVO> bookList = bookGroupCipherUserDao.getScanBookInfoByUser(wxUserId, altId);
            List<UserBookBaseInfoDTO> bookInfoList = new ArrayList<>();
            if (!ListUtils.isEmpty(bookList)) {
                List<Long> adviserIds = bookList.stream().filter(s -> s.getAdviserId() != null).map(UserBookInfoItemVO::getAdviserId).distinct().collect(Collectors.toList());
                Map<Long, AdviserBaseInfoDto> adviserBaseInfoDtoMap = adviserConsr.getAdviserId2AdviserInfoDtoMap(adviserIds);
                for (UserBookInfoItemVO infoItemVO : bookList) {
                    UserBookBaseInfoDTO baseInfoDTO = new UserBookBaseInfoDTO();
                    BeanUtils.copyProperties(infoItemVO, baseInfoDTO);
                    if (!MapUtils.isEmpty(adviserBaseInfoDtoMap) && adviserBaseInfoDtoMap.containsKey(infoItemVO.getAdviserId())) {
                        AdviserBaseInfoDto adviserBaseInfoDto = adviserBaseInfoDtoMap.get(infoItemVO.getAdviserId());
                        baseInfoDTO.setAdviserName(adviserBaseInfoDto.getPartyName());
                        baseInfoDTO.setAgentId(adviserBaseInfoDto.getAgentId());
                        baseInfoDTO.setAgentName(adviserBaseInfoDto.getAgentName());
                        baseInfoDTO.setPhoneNum(adviserBaseInfoDto.getPhoneNum());
                    }
                    bookInfoList.add(baseInfoDTO);
                }
            }
            if (!ListUtils.isEmpty(bookInfoList)) {
                map.put(wxUserId, bookInfoList);
            }
        }
        return map;
    }

    @Override
    public void updateSpecialState(Long id, Boolean belongSpecialAgent) {
        bookGroupDao.updateSpecialState(id, belongSpecialAgent);
    }

    @Override
    public Long getLatestCipherBookGroup(String altId, String wxUserId) {
        Long bookGroupId = bookGroupCipherUserDao.getLatestCipherBookGroup(altId, wxUserId);
        return bookGroupId;
    }

    @Override
    public BookGroupStatistic4AgentDTO getBookGroupStatisticsByAgent(Long bookId) {
        BookGroupStatistic4AgentDTO groupStatistic4AgentDTO = bookGroupDao.getBaseInfoByBookId(bookId);
        if (null == groupStatistic4AgentDTO) {
            return new BookGroupStatistic4AgentDTO();
        }
        Long bookGroupId = groupStatistic4AgentDTO.getBookGroupId();
        //资源浏览量
        Integer browseCount = 0;
        Integer browserCount = 0;
        Long browseTimes = 0L;
        Map<Long, GroupBrowseStatisticVO> browseMap = browseRecordConsr.mapGroupBrowseStatistic(Arrays.asList(bookGroupId), null);
        if (!MapUtils.isEmpty(browseMap) && browseMap.containsKey(bookGroupId)) {
            GroupBrowseStatisticVO browseStatisticVO = browseMap.get(bookGroupId);
            browseCount = browseStatisticVO.getBrowseCount();
            browserCount = browseStatisticVO.getBrowserCount();
            browseTimes = browseStatisticVO.getBrowserCount() == 0 ? 0 : browseStatisticVO.getBrowseTimes() / browseStatisticVO.getBrowserCount();
        }
        groupStatistic4AgentDTO.setBrowseCount(browseCount);
        groupStatistic4AgentDTO.setBrowserCount(browserCount);
        groupStatistic4AgentDTO.setAvgbrowseTimes(browseTimes);
        //购买次数 销售额
        Long saleCount = 0L;
        Double saleAmount = 0D;
        Map<Long, ProductSaleDetailDto> saleMap = tradeConsr.getSaleInfo4Group(Arrays.asList(bookGroupId), null);
        if (!MapUtils.isEmpty(saleMap) && saleMap.containsKey(bookGroupId)) {
            ProductSaleDetailDto productSaleDetailDto = saleMap.get(bookGroupId);
            saleCount = productSaleDetailDto.getSaleCount();
            saleAmount = productSaleDetailDto.getSaleMoney();
        }
        groupStatistic4AgentDTO.setSaleCount(saleCount);
        groupStatistic4AgentDTO.setSaleAmount(saleAmount);
        if (JoinGroupTypeEnum.ROBOT.getCode().equals(groupStatistic4AgentDTO.getJoinGroupType())) {
            //个人号信息
            List<AltAndCountDTO> altAndCountDTOS = bookGroupCipherUserDao.getAltFriendList(bookGroupId);
            if (!ListUtils.isEmpty(altAndCountDTOS)) {
                List<String> altList = altAndCountDTOS.stream().filter(s -> s.getAltId() != null).map(AltAndCountDTO::getAltId).collect(Collectors.toList());
                Map<String, RobotBaseInfoDTO> robotBaseInfoDTOMap = wechatGroupConsr.mapRobotInfo(altList);
                for (AltAndCountDTO altAndCountDTO : altAndCountDTOS) {
                    if (!MapUtils.isEmpty(robotBaseInfoDTOMap) && robotBaseInfoDTOMap.containsKey(altAndCountDTO.getAltId())) {
                        RobotBaseInfoDTO dto = robotBaseInfoDTOMap.get(altAndCountDTO.getAltId());
                        altAndCountDTO.setNickName(dto == null ? "" : dto.getNickName());
                    }
                }
            }
            groupStatistic4AgentDTO.setAltAndCountDTOS(altAndCountDTOS);
            //个人号配置资源
            List<BookGroupServe> list = bookGroupServeDao.getListByBookGroupId(bookGroupId);
            groupSet.setBookGroupServeStatistic(list, bookGroupId);
            groupStatistic4AgentDTO.setBookGroupServeList(list);
        }
        return groupStatistic4AgentDTO;
    }

    @Override
    public List<ListKeywordVO> getClassifyKeywordStatistic(Long classifyId) {
        ClassifyDTO classifyDTO = bookGroupClassifyDao.getById(classifyId);
        if (null == classifyDTO) {
            return new ArrayList<>();
        }
        Long bookGroupId = classifyDTO.getBookGroupId();
        //所有的关键词（群分类+书）
        List<ListKeywordVO> listKeywordVOS = new ArrayList<>();
        //按分类设置的关键词
        List<ListKeywordVO> classifyKeywordVOS = bookKeywordDao.getAppKeywordsByClassifyId(classifyId, bookGroupId, null);
        List<Long> keywordIdList = new ArrayList<>();
        if (!ListUtils.isEmpty(classifyKeywordVOS)) {
            keywordIdList = classifyKeywordVOS.stream().filter(s -> s.getKeywordId() != null).map(ListKeywordVO::getKeywordId).distinct().collect(Collectors.toList());
            listKeywordVOS.addAll(classifyKeywordVOS);
        }
        //按书设置的关键词
        List<ListKeywordVO> bookKeywordVOS = bookKeywordDao.getAppKeywordsByClassifyId(0L, bookGroupId, keywordIdList);
        if (!ListUtils.isEmpty(bookKeywordVOS)) {
            listKeywordVOS.addAll(bookKeywordVOS);
        }
        if (!ListUtils.isEmpty(listKeywordVOS)) {
            groupSet.setKeyWordStatistic(classifyId, bookGroupId, listKeywordVOS);
        }
        return listKeywordVOS;
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("新增微信用户和rays系统用户关联关系")
    @Override
    public void createWxWechatUserCorrelation(Long wechatUserId, WxWechatUserCorrelation wxWechatUserCorrelation) {
        if (wxWechatUserCorrelation==null){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"参数为空！");
        }
        if (wxWechatUserCorrelation.getBookGroupId()==null){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"bookGroupId参数为空！");
        }
        if (StringUtil.isEmpty(wxWechatUserCorrelation.getWxId())){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"wxUserId参数为空！");
        }
        wxWechatUserCorrelation.setWechatUserId(wechatUserId);
        //判断库里有没有
        WxWechatUserCorrelation old = wxWechatUserCorrelationDao.getByWxIdAndBookGroupId(wxWechatUserCorrelation.getBookGroupId(), wxWechatUserCorrelation.getWxId());
        if (old!=null){
            return;
        }
        wxWechatUserCorrelationDao.insert(wxWechatUserCorrelation);
    }

    @Override
    public SelfRobotBookGroupDTO getSelfRobotBookGroupInfoByUser(String wxUserId, Long bookGroupId) {
        SelfRobotBookGroupDTO dto = bookGroupCipherUserDao.getSelfRobotBookGroupInfoByUser(wxUserId, bookGroupId);
        if (null != dto) {
            GroupRobotDTO robotDTO = wechatGroupConsr.getGroupRobotByWxId(dto.getWxId());
            dto.setWxNickName(robotDTO.getNickName());
        }
        return dto;
    }

    @Override
    public PageBeanNew<UserBookInfoVO> listUser4ReadingActivity(UserSelectParamDTO userSelectParamDTO) {
        Integer currentPage = userSelectParamDTO.getCurrentPage();
        Integer numPerPage = userSelectParamDTO.getNumPerPage();
        Map<String, Object> map = new HashMap<>();
        //用户昵称id模糊查询
        if (!StringUtil.isEmpty(userSelectParamDTO.getUserQuery())) {
            List<String> wxUserIds = wechatGroupConsr.getByUserQuery(userSelectParamDTO.getUserQuery());
            if (!ListUtils.isEmpty(wxUserIds)) {
                map.put("wxUserIds", wxUserIds);
            } else {
                return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
            }
        }
        map.put("bookIds", userSelectParamDTO.getBookIds());
        map.put("robotId", userSelectParamDTO.getRobotId());
        map.put("invitedFilter", userSelectParamDTO.getInvitedFilter());
        List<Long> countlist = bookGroupCipherUserDao.listId4ReadingActivity(map);
        if (ListUtils.isEmpty(countlist)) {
            return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
        }
        map.put("pageNum", currentPage * numPerPage);
        map.put("numPerPage", numPerPage);
        List<Long> idList = bookGroupCipherUserDao.listId4ReadingActivity(map);
        List<UserBookInfoVO> list = bookGroupCipherUserDao.listUserByIds(idList);
        //填充用户信息、扫码书刊信息,小号信息
        groupSet.setUserBookInfo4ReadingActivity(list);
        return new PageBeanNew<>(currentPage, numPerPage, countlist.size(), list);
    }

    @ParamLog("生成小程序码")
    public void createBookGroupAppletUrl(Long bookGroupId,Long bookId, Long channelId, Long adviserId){
        BookAdviserDto bookAdviserDto = bookAdviserDao.getBase(bookId,channelId,adviserId);
        Long raysClassifyId = bookRaysClassifyDao.getClassifyIdByBookTemplateId(bookAdviserDto.getTempletId());
        if (null==raysClassifyId){
            LOGGER.error("书刊分类没有对应的小睿分类"+bookGroupId);
        }
        String page=null;//小程序跳转页 todo
        String appletId= createOneAppletId();
        BookAppletScene applet = bookAppletSceneDao.getByAppletId(appletId);
        while (null!=applet){
            appletId = createOneAppletId();
            applet = bookAppletSceneDao.getByAppletId(appletId);
        }
        String url = wechatConsr.create4MiniApp(777L, appletId, null, page);
        BookAppletScene bookAppletScene = new BookAppletScene();
        bookAppletScene.setBookGroupId(bookGroupId);
        bookAppletScene.setRaysClassifyId(raysClassifyId);
        bookAppletScene.setAppletId(appletId);
        bookAppletScene.setAppletUrl(url);
        bookAppletSceneDao.insert(bookAppletScene);
    }

    @ParamLog("生成一个小程序id")
    private String createOneAppletId() {
        Random random = new Random();
        String charStr = "0123456789abcdefghijklmnopqrstuvwxyz";
        String s = "";
        for (int i = 0; i < 20; i++) {
            int index = random.nextInt(charStr.length());
            s = s + charStr.charAt(index);
        }
        return s;
    }

    @Override
    public BookAppletSceneDTO getBookGroupAppletByAppletId(String appletId) {
        BookAppletScene bookAppletScene = bookAppletSceneDao.getByAppletId(appletId);
        BookAppletSceneDTO dto = new BookAppletSceneDTO();
        if (null != bookAppletScene){
            BeanUtils.copyProperties(bookAppletScene,dto);
        }
        return dto;
    }

    @Override
    public BookAppletSceneDTO getBookGroupAppletByBookGroupId(Long bookGroupId) {
        BookAppletScene bookAppletScene = bookAppletSceneDao.getByBookGroupId(bookGroupId);
        BookAppletSceneDTO dto = new BookAppletSceneDTO();
        if (null != bookAppletScene){
            BeanUtils.copyProperties(bookAppletScene,dto);
        }
        BookGroupDTO bookGroupDTO = bookGroupDao. getBookBaseInfoById(bookGroupId);
        dto.setBookName(StringUtil.addBracket(bookGroupDTO.getBookName()));
        //权益
        BookAdviserDto adviserDto = bookAdviserDao.getBase(bookGroupDTO.getBookId(),bookGroupDTO.getChannelId(),bookGroupDTO.getCreateUser());
        if (null!=adviserDto){
            RightsSettingDto rightsSettingDto = rightsSettingBiz.getByLabel(adviserDto.getTempletId(),
                    adviserDto.getSecondTempletId(),adviserDto.getGraLabelId(),adviserDto.getSubLabelId());
            if (null!= rightsSettingDto){
                dto.setRightsSettingDetail(rightsSettingDto.getDetail());
                dto.setRightsSettingIntroduce(rightsSettingDto.getIntroduce());
                dto.setRightsSettingCount(rightsSettingDto.getCount());
            }
        }
        return dto;
    }

    @Override
    public void updateBookGroupRaysClassify(Book book) {
        //小睿类型更新分类
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOByBookId(book.getBookId(),book.getChannelId(),book.getLastModifiedUser());
        if (null!=bookGroupDTO && JoinGroupTypeEnum.XIAORUI.getCode().equals(bookGroupDTO.getJoinGroupType())){
            Long raysClassifyId = bookRaysClassifyDao.getClassifyIdByBookTemplateId(book.getTempletId());
            if (null != raysClassifyId){
                bookAppletSceneDao.updateRaysClassifyIdByBookGroupId(raysClassifyId, bookGroupDTO.getId());
            }
        }
    }

    @Override
    public Long getBookGroupId4OldData(Long raysBookId) {
        return bookGroupDao.getBookGroupId4OldData(raysBookId);
    }

    @Override
    public void getByAppletScene(Long wechatUserId, String scene) {
        BookAppletScene bookAppletScene = bookAppletSceneDao.getByAppletId(scene);
        if (null==bookAppletScene){
            return;
        }
        BookGroupDTO bookGroupDTO = bookGroupDao. getBookBaseInfoById(bookAppletScene.getBookGroupId());
        if (null==bookGroupDTO){
            return;
        }
        //用户书刊埋点
        AppletUserBookcase appletUserBookcase = new AppletUserBookcase();
        appletUserBookcase.setWechatUserId(wechatUserId);
        appletUserBookcase.setAdviserId(bookGroupDTO.getCreateUser());
        appletUserBookcase.setBookId(bookGroupDTO.getBookId());
        appletUserBookcase.setChannelId(bookGroupDTO.getChannelId());
        appletUserBookcaseBiz.addUserBook(appletUserBookcase);
    }

}
