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

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.pcloud.appcenter.assist.dto.AssistTempletDTO;
import com.pcloud.book.applet.biz.AppletGroupSearchRecordBiz;
import com.pcloud.book.applet.dao.AppletLinkClickDao;
import com.pcloud.book.applet.dto.AppletGroupStatementDTO;
import com.pcloud.book.applet.dto.PvuvDTO;
import com.pcloud.book.applet.enums.DataRecordTypeEnum;
import com.pcloud.book.applet.enums.DataTypeEnum;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.constant.BookConstant;
import com.pcloud.book.book.dao.BookDao;
import com.pcloud.book.book.dao.BookLabelDao;
import com.pcloud.book.book.entity.BookLabel;
import com.pcloud.book.consumer.app.AssistTempletConsr;
import com.pcloud.book.consumer.common.ExportConsr;
import com.pcloud.book.consumer.label.LabelConsr;
import com.pcloud.book.consumer.message.MessageConsr;
import com.pcloud.book.consumer.promotion.PromotionConsr;
import com.pcloud.book.consumer.reader.ReaderConsr;
import com.pcloud.book.consumer.resource.ProductConsr;
import com.pcloud.book.consumer.settlement.SettlementConsr;
import com.pcloud.book.consumer.trade.TradeConsr;
import com.pcloud.book.consumer.wechatgroup.WechatGroupConsr;
import com.pcloud.book.copyright.biz.BookAuthUserBiz;
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.GroupAnnouncementBiz;
import com.pcloud.book.group.biz.GroupQrcodeBiz;
import com.pcloud.book.group.biz.WeixinQrcodeBiz;
import com.pcloud.book.group.dao.BookClassifyBuyRecordDao;
import com.pcloud.book.group.dao.BookGroupCipherUserDao;
import com.pcloud.book.group.dao.BookGroupClassifyDao;
import com.pcloud.book.group.dao.BookGroupDao;
import com.pcloud.book.group.dao.BookQrcodeUserDao;
import com.pcloud.book.group.dao.GroupQrcodeDao;
import com.pcloud.book.group.dao.JoinGroupCipherDao;
import com.pcloud.book.group.dao.LearningReportBrowseRecordDao;
import com.pcloud.book.group.dao.LearningReportTouchRecordDao;
import com.pcloud.book.group.dao.WeixinQrcodeDao;
import com.pcloud.book.group.dto.ActivityGroupDTO;
import com.pcloud.book.group.dto.BookClassifyDTO;
import com.pcloud.book.group.dto.BookGroupClassifyDTO;
import com.pcloud.book.group.dto.BookGroupDTO;
import com.pcloud.book.group.dto.BookGroupStatisticDTO;
import com.pcloud.book.group.dto.BookWxQrcodeDTO;
import com.pcloud.book.group.dto.ClassifyDTO;
import com.pcloud.book.group.dto.ClassifyLearningCountDto;
import com.pcloud.book.group.dto.ClassifyLearningReportDto;
import com.pcloud.book.group.dto.GroupAndUserNumberDTO;
import com.pcloud.book.group.dto.GroupClassifyQrcodeDTO;
import com.pcloud.book.group.dto.GroupDetailDTO;
import com.pcloud.book.group.dto.GroupNameAndMaxSeqDTO;
import com.pcloud.book.group.dto.GroupQrcode4ClassifyDTO;
import com.pcloud.book.group.dto.GroupQrcodeBaseDTO;
import com.pcloud.book.group.dto.GroupQrcodeInfoDTO;
import com.pcloud.book.group.dto.ListClassify4WechatDTO;
import com.pcloud.book.group.dto.ProAssocGroupAndUserNumberDTO;
import com.pcloud.book.group.dto.QrcodeNameAndProIdDTO;
import com.pcloud.book.group.dto.WeixinQrcodeDTO;
import com.pcloud.book.group.entity.BookGroupClassify;
import com.pcloud.book.group.entity.BookQrcodeUser;
import com.pcloud.book.group.entity.GroupQrcode;
import com.pcloud.book.group.entity.WeixinQrcode;
import com.pcloud.book.group.enums.JoinGroupTypeEnum;
import com.pcloud.book.group.enums.QrcodeUsedEnum;
import com.pcloud.book.group.enums.RankTypeEnum;
import com.pcloud.book.group.set.GroupSet;
import com.pcloud.book.group.tools.SendWeixinRequestTools;
import com.pcloud.book.group.vo.AddClassifyVO;
import com.pcloud.book.group.vo.AdviserClassifyParam;
import com.pcloud.book.group.vo.AdviserClassifyVO;
import com.pcloud.book.group.vo.BookGroupClassifyAnalysisVO;
import com.pcloud.book.group.vo.BookGroupClassifyVO;
import com.pcloud.book.group.vo.BookGroupQrcodeStatisticVO;
import com.pcloud.book.group.vo.ClassifyAndGroupCountVO;
import com.pcloud.book.group.vo.ClassifyAndUserCountVO;
import com.pcloud.book.group.vo.ClassifyNameVO;
import com.pcloud.book.group.vo.ClassifyQrcodeVO;
import com.pcloud.book.group.vo.ClassifyVO;
import com.pcloud.book.group.vo.GroupQrcode4ClassifyVO;
import com.pcloud.book.group.vo.GroupQrcodeBaseInfoVO;
import com.pcloud.book.group.vo.ListBookGroupQrcodeParamVO;
import com.pcloud.book.group.vo.ListClassify4WechatVO;
import com.pcloud.book.group.vo.ListClassifyVO;
import com.pcloud.book.group.vo.ListGroupClassifyParam;
import com.pcloud.book.group.vo.PcloudBookGroupClassifyVO;
import com.pcloud.book.group.vo.StatisticVO;
import com.pcloud.book.group.vo.SyncKeyworsVO;
import com.pcloud.book.group.vo.UpdateClassifyVO;
import com.pcloud.book.group.vo.UpdateRankVO;
import com.pcloud.book.keywords.dao.BookKeywordDao;
import com.pcloud.book.keywords.dao.KeywordDao;
import com.pcloud.book.keywords.entity.BookKeyword;
import com.pcloud.book.keywords.entity.Keyword;
import com.pcloud.book.record.biz.BookBrowseRecordBiz;
import com.pcloud.book.record.entity.RegionMap;
import com.pcloud.book.rightsSetting.biz.RightsSettingBiz;
import com.pcloud.book.rightsSetting.entity.BaseTempletClassify;
import com.pcloud.book.skill.dao.PcloudGroupActivityDao;
import com.pcloud.book.applet.dto.GroupActivity4AppletDTO;
import com.pcloud.book.skill.enums.ActivityGroupTypeEnum;
import com.pcloud.book.skill.enums.GroupUpdateTypeEnum;
import com.pcloud.book.util.common.ThreadPoolUtils;
import com.pcloud.book.util.properties.BookProps;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.core.constant.SystemCode;
import com.pcloud.common.core.enums.NotifyOriginTypeEnum;
import com.pcloud.common.page.PageBeanNew;
import com.pcloud.common.page.PageParam;
import com.pcloud.common.utils.DateUtils;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.ResponseHandleUtil;
import com.pcloud.common.utils.cache.redis.JedisClusterUtils;
import com.pcloud.common.utils.httpclient.UrlUtils;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.common.utils.string.StringUtilParent;
import com.pcloud.facade.tradecenter.dto.BookGroupSaleSearchDto;
import com.pcloud.facade.tradecenter.dto.QrGroupBuyDetailDto;
import com.pcloud.labelcenter.label.service.LabelService;
import com.pcloud.readercenter.wechat.dto.WechatUserRobotDto;
import com.pcloud.resourcecenter.product.dto.UpdateAppProductParamDTO;
import com.pcloud.resourcecenter.product.entity.Product;
import com.pcloud.resourcecenter.product.entity.Specification;
import com.pcloud.usercenter.party.adviser.entity.Adviser;
import com.pcloud.usercenter.party.adviser.service.AdviserService;
import com.pcloud.usercenter.party.agent.service.AgentService;
import com.pcloud.wechatgroup.group.dto.GroupMemberStatisDTO;
import com.pcloud.wechatgroup.group.dto.GroupRobotDTO;
import com.pcloud.wechatgroup.message.dto.GroupChatCountDTO;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
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.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author lily
 * @date 2019/4/17 11:20
 */
@Slf4j
@Component("bookGroupClassifyBiz")
public class BookGroupClassifyBizImpl implements BookGroupClassifyBiz {

    private static final Logger LOGGER = LoggerFactory.getLogger(BookGroupClassifyBizImpl.class);

    @Autowired
    private AdviserService  adviserService;
    @Autowired
    private AgentService agentService;
    @Autowired
    private WeixinQrcodeBiz weixinQrcodeBiz;
    @Autowired
    private BookGroupClassifyDao bookGroupClassifyDao;
    @Autowired
    private BookGroupBiz bookGroupBiz;
    @Autowired
    private ProductConsr productConsr;
    @Autowired
    private GroupQrcodeBiz groupQrcodeBiz;
    @Autowired
    private ReaderConsr readerConsr;
    @Autowired
    private BookClassifyBuyRecordDao bookClassifyBuyRecordDao;
    @Autowired
    private BookQrcodeUserDao bookQrcodeUserDao;
    @Autowired
    private PromotionConsr promotionConsr;
    @Autowired
    private WechatGroupConsr wechatGroupConsr;
    @Autowired
    private SettlementConsr settlementConsr;
    @Autowired
    private ExportConsr exportConsr;
    @Autowired
    private MessageConsr messageConsr;
    @Autowired
    private TradeConsr tradeConsr;
    @Autowired
    private GroupAnnouncementBiz groupAnnouncementBiz;
    @Autowired
    private LabelService labelService;
    @Autowired
    private BookKeywordDao bookKeywordDao;
    @Autowired
    private GroupSet groupSet;
    @Autowired
    private BookGroupClassifyBiz bookGroupClassifyBiz;
    @Autowired
    private LearningReportBrowseRecordDao learningReportBrowseRecordDao;
    @Autowired
    private LearningReportTouchRecordDao learningReportTouchRecordDao;
    @Autowired
    private JoinGroupCipherDao joinGroupCipherDao;
    @Autowired
    private BookAuthUserBiz bookAuthUserBiz;
    @Autowired
    private BookGroupCipherUserDao bookGroupCipherUserDao;
    @Autowired
    private BookGroupDao bookGroupDao;
    @Autowired
    private WeixinQrcodeDao weixinQrcodeDao;
    @Autowired
    private GroupQrcodeDao groupQrcodeDao;
    @Autowired
    private BookGroupAppBiz bookGroupAppBiz;
    @Autowired
    private KeywordDao keywordDao;
    @Autowired
    private BookDao bookDao;
    @Autowired
    private BookBrowseRecordBiz bookBrowseRecordBiz;
    @Autowired
    private LabelConsr labelConsr;
    @Autowired
    private AppletLinkClickDao appletLinkClickDao;
    @Autowired
    private RightsSettingBiz rightsSettingBiz;
    @Autowired
    private AssistTempletConsr assistTempletConsr;
    @Autowired
    private BookLabelDao bookLabelDao;
    @Autowired
    private PcloudGroupActivityDao pcloudGroupActivityDao;
    @Autowired
    private AppletGroupSearchRecordBiz appletGroupSearchRecordBiz;


    @Override
    @ParamLog("新增分类")
    @Transactional(rollbackFor = Exception.class)
    public void addClassify(AddClassifyVO addClassifyVO, Long partyId) {
        checkClassifyIsExist(addClassifyVO.getClassify(), null, addClassifyVO.getBookGroupId());
        final Map<Long, BookGroupStatisticDTO> statistic = bookGroupClassifyDao.getClassifyCountAbout(Collections.singletonList(addClassifyVO.getBookGroupId()));
        Integer classifyCount = 0;
        if (!CollectionUtils.isEmpty(statistic) && null != statistic.get(addClassifyVO.getBookGroupId())) {
            classifyCount = statistic.get(addClassifyVO.getBookGroupId()).getClassifyCount();
        }
        if (classifyCount >= 40) {
            throw new BookBizException(BookBizException.ERROR, "分类数量超出限制");
        }
        if (addClassifyVO.getPrice() == null) {
            addClassifyVO.setPrice(BigDecimal.ZERO);
        }
        BookGroupClassify bookGroupClassify = new BookGroupClassify();
        BeanUtils.copyProperties(addClassifyVO, bookGroupClassify);
        QrcodeNameAndProIdDTO qrcodeNameAndProId = bookGroupBiz.getQrcodeNameAndProId(addClassifyVO.getBookGroupId());
        if (Objects.isNull(qrcodeNameAndProId) || Objects.isNull(qrcodeNameAndProId.getProductId())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请先填写社群码信息！");
        }
        bookGroupClassify.setProductId(qrcodeNameAndProId.getProductId());
        bookGroupClassify.setCreateUser(partyId);
        Integer rank = bookGroupClassifyDao.getMaxRank(addClassifyVO.getBookGroupId());
        bookGroupClassify.setRank(rank);
        bookGroupClassifyDao.insert(bookGroupClassify);
        final Long wechatGroupNum = weixinQrcodeBiz.countWechatGroup();
        // 只有生产环境才有30个限制
        if ("pro".equalsIgnoreCase(BookProps.getSystemEnv())) {
            if(null == wechatGroupNum || wechatGroupNum <= 30) {
                log.info("[新增分类] : 可用微信群数量：{}个", wechatGroupNum);
                throw new BookBizException(BookBizException.PARAM_IS_NULL, "群二维码数量不足，您可以明天再创建群。");
            }
        }
        //添加分类时如果不是普通群则不分配群
        if (JoinGroupTypeEnum.GROUP_QRCODE.getCode().equals(qrcodeNameAndProId.getJoinGroupType())) {
            WeixinQrcodeDTO oneQrcode = weixinQrcodeBiz.getOneQrcode(null, null);
            if (oneQrcode == null) {
                throw new BookBizException(BookBizException.PARAM_IS_NULL, "系统二维码数量不足，请联系客服人员补充二维码数量！");
            }
            GroupQrcode groupQrcode = new GroupQrcode();
            groupQrcode.setWeixinGroupId(oneQrcode.getWeixinGroupId());
            groupQrcode.setQrcodeUrl(oneQrcode.getQrcodeUrl());
            groupQrcode.setCreateUser(partyId);
            groupQrcode.setWeixinQrcodeId(oneQrcode.getId());
            groupQrcode.setUserNumber(oneQrcode.getUserNumber()>3?oneQrcode.getUserNumber():3);
            groupQrcode.setGroupSeq(1);
            // 群长度超过16部分会被截取，导致群名称重复
            final String s = "1群";
            String groupName = qrcodeNameAndProId.getGroupQrcodeName() + addClassifyVO.getClassify() + s;
            if (groupName.length() > 15) {
                groupName = addClassifyVO.getClassify() + s;
                if (groupName.length() > 15) {
                    groupName = addClassifyVO.getClassify().substring(0, 16 - s.length()) + s;
                }
            }
            groupQrcode.setGroupName(groupName);
            groupQrcode.setClassifyId(bookGroupClassify.getId());
            groupQrcode.setQrcodeHeadUrl(readerConsr.getNineHeadUrl());
            groupQrcodeBiz.insert(groupQrcode);
            //获取该社群书下是否有群公告
            groupAnnouncementBiz.setAnForGroup(addClassifyVO.getBookGroupId(), null, oneQrcode.getWeixinGroupId());
            final String wechatGroupId = oneQrcode.getWeixinGroupId();
            Map<String, BookWxQrcodeDTO> groupVersion = weixinQrcodeBiz.getGroupVersion(Collections.singletonList(wechatGroupId));
            String ip = Optional.ofNullable(groupVersion.get(wechatGroupId)).orElse(new BookWxQrcodeDTO()).getWechatGroupIp();
            SendWeixinRequestTools.changeGroupName(oneQrcode.getRobotWxId(), oneQrcode.getWeixinGroupId(), groupQrcode.getGroupName(), ip);
        }
        //新增一个规格
        Long specId = addSpecification(bookGroupClassify.getPrice(), qrcodeNameAndProId.getProductId(), addClassifyVO.getChannelId(), bookGroupClassify.getClassify());
        bookGroupClassify.setProductSpecId(specId);
        //更新规格
        bookGroupClassifyDao.updateSpecId(bookGroupClassify.getId(), bookGroupClassify.getProductSpecId());
        //发送更新群名称请求
//        String robotId = wechatGroupConsr.getRobotIdByGroupId(oneQrcode.getWeixinGroupId());

        //同步关键词
        List<BookKeyword> bookKeywords = new ArrayList<>();
        List<SyncKeyworsVO> syncKeyworsVOS = bookKeywordDao.getKeywordsIdsByBookGroupId(addClassifyVO.getBookGroupId(),0L);
        syncKeyworsVOS.forEach(e -> {
            BookKeyword bookKeyword = new BookKeyword();
            bookKeyword.setBookGroupId(addClassifyVO.getBookGroupId());
            bookKeyword.setClassifyId(bookGroupClassify.getId());
            bookKeyword.setKeywordId(e.getKeywordsId());
            bookKeyword.setBookId(addClassifyVO.getBookId());
            bookKeyword.setChannelId(addClassifyVO.getChannelId());
            bookKeyword.setSetType(0);
            //获取最大排序值
            Integer seq = bookKeywordDao.getMaxRank(addClassifyVO.getBookGroupId(), bookKeyword.getClassifyId());
            bookKeyword.setRank(seq + 1);
            bookKeyword.setCreateUser(partyId);
            bookKeyword.setWarehouseId(e.getWarehouseId());
            bookKeyword.setIsWarehouse(e.getIsWarehouse());
            bookKeyword.setIsEdit(0);
            bookKeywords.add(bookKeyword);
        });
        bookKeywordDao.insert(bookKeywords);
        fillKeyword(bookKeywords);
        bookGroupAppBiz.addAppKeywordToBookGroupApp(bookKeywords);
    }

    @ParamLog("填充关键词模型")
    private void fillKeyword(List<BookKeyword> bookKeywords) {
        if (ListUtils.isEmpty(bookKeywords)) {
            return;
        }
        List<Long> keywordIds = bookKeywords.stream().filter(s -> s.getKeywordId() != null).map(BookKeyword::getKeywordId).distinct().collect(Collectors.toList());
        if (ListUtils.isEmpty(keywordIds)) {
            return;
        }
        List<Keyword> list = keywordDao.getListByIds(keywordIds);
        if (ListUtils.isEmpty(list)) {
            return;
        }
        Map<Long, Keyword> map = new HashMap<>();
        for (Keyword keyword : list) {
            map.put(keyword.getId(), keyword);
        }
        for (BookKeyword bookKeyword : bookKeywords) {
            bookKeyword.setKeyword(map.get(bookKeyword.getKeywordId()));
        }
    }

    @ParamLog("新增商品对应规格")
    private Long addSpecification(BigDecimal price, Long productId, Long channelId, String classify) {
        UpdateAppProductParamDTO updateAppProductParamDTO = new UpdateAppProductParamDTO();
        updateAppProductParamDTO.setProductId(productId);
        updateAppProductParamDTO.setChannelId(channelId);
        List<Specification> specificationList = new ArrayList<>();
        Specification specification = new Specification();
        specification.setRetailPrice(price.doubleValue());
        specification.setSpecificationName(classify);
        specificationList.add(specification);
        updateAppProductParamDTO.setSpecificationList(specificationList);
        Product product = productConsr.postUpdateBookGroupProduct(updateAppProductParamDTO);
        if (product == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "新增分类对应商品失败");
        }
        List<Specification> spec = product.getSpecification();
        if (spec != null) {
            return spec.get(0).getSpecificationId();
        } else {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "新增分类对应商品失败");
        }
    }

    @ParamLog("新增商品对应规格")
    private void deleteSpecification(Long productId, Long channelId, Long specId) {
        UpdateAppProductParamDTO updateAppProductParamDTO = new UpdateAppProductParamDTO();
        updateAppProductParamDTO.setProductId(productId);
        updateAppProductParamDTO.setChannelId(channelId);
        List<Long> specIds = new ArrayList<>();
        specIds.add(specId);
        updateAppProductParamDTO.setDelSpecificationIds(specIds);
        productConsr.postUpdateBookGroupProduct(updateAppProductParamDTO);
    }


    @ParamLog("校验分类是否存在")
    private void checkClassifyIsExist(String classify, Long classfiyId, Long bookGroupId) {
        Boolean isHaveThisClassify = bookGroupClassifyDao.isHaveThisClassify(classify, classfiyId, bookGroupId);
        if (isHaveThisClassify) {
            throw new BookBizException(BookBizException.ERROR, "已存在该分类!");
        }
        if (classify != null && classify.contains("#")) {
            throw new BookBizException(BookBizException.ERROR, "名称不能包含#!");
        }
    }

    @Override
    @ParamLog("获取社群下有多少分类")
    public Integer getClassifyCount(Long bookGroupId) {
        Integer count = bookGroupClassifyDao.getClassifyCount(bookGroupId);
        return count;
    }

    @Override
    @ParamLog("更新分类")
    public void updateClassify(UpdateClassifyVO updateClassifyVO, Long partyId) {
        checkClassifyIsExist(updateClassifyVO.getClassify(), updateClassifyVO.getId(), updateClassifyVO.getBookGroupId());
        if (updateClassifyVO.getPrice() == null) {
            updateClassifyVO.setPrice(BigDecimal.ZERO);
        }
        //获取分类基本信息
        ClassifyDTO oldClassify = bookGroupClassifyDao.getById(updateClassifyVO.getId());
        BookGroupClassify bookGroupClassify = new BookGroupClassify();
        BeanUtils.copyProperties(updateClassifyVO, bookGroupClassify);
        bookGroupClassifyDao.update(bookGroupClassify);
        //修改规格信息
        updateSpec(oldClassify, updateClassifyVO);
    }

    @ParamLog("更新规格信息")
    private void updateSpec(ClassifyDTO oldClassify, UpdateClassifyVO updateClassifyVO) {
        BigDecimal oldPrice = oldClassify.getPrice() == null ? BigDecimal.ZERO : oldClassify.getPrice();
        BigDecimal newPrice = updateClassifyVO.getPrice() == null ? BigDecimal.ZERO : updateClassifyVO.getPrice();
        if (oldPrice.equals(newPrice) && oldClassify.getClassify().equalsIgnoreCase(updateClassifyVO.getClassify())) {
            return;
        }
        UpdateAppProductParamDTO updateAppProductParamDTO = new UpdateAppProductParamDTO();
        updateAppProductParamDTO.setProductId(oldClassify.getProductId());
        updateAppProductParamDTO.setChannelId(oldClassify.getChannelId());
        List<Specification> specificationList = new ArrayList<>();
        Specification specification = new Specification();
        specification.setRetailPrice(newPrice.doubleValue());
        specification.setSpecificationName(updateClassifyVO.getClassify());
        specification.setSpecificationId(oldClassify.getProductSpecId());
        specificationList.add(specification);
        updateAppProductParamDTO.setSpecificationList(specificationList);
        productConsr.postUpdateBookGroupProduct(updateAppProductParamDTO);
    }

    @Override
    @ParamLog("分类列表")
    public List<ListClassifyVO> listAllClassify(Long bookGroupId) {
        //获取排序方式
        Integer rankType = bookGroupBiz.getRankType(bookGroupId);
        List<ListClassifyVO> classifys;
        if (RankTypeEnum.BY_RANK.value.equals(rankType)) {
            classifys = bookGroupClassifyDao.listAllClassifyByRank(bookGroupId);
            //设置群总人数与群总数
            setGroupNumberAndUserNumber(classifys);
        } else {
            classifys = bookGroupClassifyDao.listAllClassifyByUser(bookGroupId);
        }
        if (ListUtils.isEmpty(classifys)) {
            return new ArrayList<>();
        }
        List<String> cityCodes = classifys.stream().filter(e -> null != e.getCityCode()).
                map(e -> e.getCityCode()).distinct().collect(Collectors.toList());
        if (ListUtils.isEmpty(cityCodes)) {
            return classifys;
        }
        Map<String, RegionMap> regionMapMap = bookBrowseRecordBiz.getCitysByCodes(cityCodes);
        if (MapUtils.isNotEmpty(regionMapMap)){
            classifys.forEach(listClassifyVO -> {
                if (null == listClassifyVO.getCityCode()) {
                    return;
                }
                RegionMap regionMap = regionMapMap.get(listClassifyVO.getCityCode());
                if (regionMapMap.containsKey(listClassifyVO.getCityCode()) && null != regionMap){
                    listClassifyVO.setCityName(regionMap.getRegionName());
                }
            });
        }
        return classifys;
    }

    @ParamLog("设置群数量与群总人数")
    private void setGroupNumberAndUserNumber(List<ListClassifyVO> classifys) {
        if (ListUtils.isEmpty(classifys)) {
            return;
        }
        List<Long> classifyIds = new ArrayList<>();
        for (ListClassifyVO listClassifyVO : classifys) {
            classifyIds.add(listClassifyVO.getId());
        }
        Map<Long, GroupAndUserNumberDTO> groupAndUserNumberMap = groupQrcodeBiz.listGroupAndUserNumber(classifyIds);
        for (ListClassifyVO listClassifyVO : classifys) {
            if (groupAndUserNumberMap != null) {
                GroupAndUserNumberDTO groupAndUserNumberDTO = groupAndUserNumberMap.get(listClassifyVO.getId());
                listClassifyVO.setQrcodeNumber(groupAndUserNumberDTO == null ? 0 : groupAndUserNumberDTO.getGroupCount());
                listClassifyVO.setUserNumberTotal(groupAndUserNumberDTO == null ? 0 : groupAndUserNumberDTO.getUserCount());
            } else {
                listClassifyVO.setQrcodeNumber(0);
                listClassifyVO.setUserNumberTotal(0);
            }
        }
    }

    @Override
    @ParamLog("删除分类")
    @Transactional(rollbackFor = Exception.class)
    public void deleteClassify(Long classifyId, Long partyId) {
        //获取分类基本信息
        ClassifyDTO classifyDTO = bookGroupClassifyDao.getById(classifyId);
        if (classifyDTO == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "该分类不存在");
        }
        bookGroupClassifyDao.deleteClassify(classifyId, partyId);
        groupQrcodeBiz.deleteByClassifyId(classifyId);
        //删除此商品对应规格
        deleteSpecification(classifyDTO.getProductId(), classifyDTO.getChannelId(), classifyDTO.getProductSpecId());
        //发送topic
        groupSet.sendGroupClassifyDeleteTopic(classifyId);
        readerConsr.deleteGroupRecore(Lists.newArrayList(classifyId), ActivityGroupTypeEnum.NORMAL_GROUP.value, GroupUpdateTypeEnum.DELETE.value, null);
    }

    @Override
    @ParamLog("获取分类基本信息")
    public ClassifyVO getClassify(Long classifyId) {
        ClassifyVO classifyVO = bookGroupClassifyDao.getClassify(classifyId);
        if (classifyVO != null) {
            BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(classifyVO.getBookGroupId());
            if (bookGroupDTO != null) {
                classifyVO.setJoinGroupType(bookGroupDTO.getJoinGroupType());
            }
            String cityCode = classifyVO.getCityCode();
            if (null != cityCode) {
                Map<String, RegionMap> regionMapMap = bookBrowseRecordBiz.getCitysByCodes(Lists.newArrayList(cityCode));
                if (MapUtils.isNotEmpty(regionMapMap)  && null != regionMapMap.get(cityCode)){
                    classifyVO.setCityName(regionMapMap.get(cityCode).getRegionName());
                }
            }
        }
        return classifyVO;
    }

    @Override
    @ParamLog("根据主键id获取群分类")
    public  Map<Long, String> getClassifyByIds(List<Long> weixinGroupClassifyPrimaryIds) {
        if (ListUtils.isEmpty(weixinGroupClassifyPrimaryIds)) {
            return new HashMap<>();
        }
        List<BookGroupClassify> bookGroupClassifyList = bookGroupClassifyDao.getClassifyByIds(weixinGroupClassifyPrimaryIds);
        Map<Long, String> classifyMap = new HashMap<>();
        bookGroupClassifyList.stream().forEach(eachBookGroupClassify ->{
            Long key = eachBookGroupClassify.getId();
            String value = eachBookGroupClassify.getClassify();
            classifyMap.put(key, value);
        });
        return classifyMap;
    }

    @Override
    @ParamLog("根据规格获取分类基本信息（图书，运营，二维码，分类）")
    public ClassifyDTO getBaseInfoBySpecId(Long productSpecId) {
        ClassifyDTO classifyDTO = bookGroupClassifyDao.getBaseInfoBySpecId(productSpecId);
        return classifyDTO;
    }


    @Override
    @ParamLog("修改排序值")
    public void updateClassifyRank(UpdateRankVO updateRankVO, Long partyId) {
        BookGroupClassify bookGroupClassify = new BookGroupClassify();
        bookGroupClassify.setId(updateRankVO.getClassifyId());
        bookGroupClassify.setRank(updateRankVO.getRank());
        bookGroupClassify.setUpdateUser(partyId);
        bookGroupClassifyDao.updateClassifyRank(bookGroupClassify);
    }

    @Override
    @ParamLog("获取所有分类名")
    public List<ClassifyNameVO> listClassify(Long bookGroupId) {
        //获取排序方式
        Integer rankType = bookGroupBiz.getRankType(bookGroupId);
        List<ClassifyNameVO> classifys;
        if (RankTypeEnum.BY_RANK.value.equals(rankType)) {
            classifys = bookGroupClassifyDao.listClassifyByRank(bookGroupId);
        } else {
            classifys = bookGroupClassifyDao.listClassifyByUser(bookGroupId);
        }
        return classifys;
    }

    @Override
    @ParamLog("获取分类与群数量")
    public ClassifyAndGroupCountVO getClassifyAndGroupCount(Long bookGroupId) {
        ClassifyAndGroupCountVO classifyAndGroupCountVO = new ClassifyAndGroupCountVO();
        Integer groupCount = bookGroupClassifyDao.getGroupCount(bookGroupId);
        //获取分类数量
        final Map<Long, BookGroupStatisticDTO> statistic = bookGroupClassifyDao.getClassifyCountAbout(Collections.singletonList(bookGroupId));
        if (CollectionUtils.isEmpty(statistic) || null == statistic.get(bookGroupId)) {
            classifyAndGroupCountVO.setClassifyCount(0);
        } else {
            classifyAndGroupCountVO.setClassifyCount(statistic.get(bookGroupId).getClassifyCount());
        }
        classifyAndGroupCountVO.setGroupCount(groupCount);
        Integer friendsCount = bookGroupCipherUserDao.getFriendsCountByBookGroup(bookGroupId);
        classifyAndGroupCountVO.setFriendsCount(friendsCount);
        return classifyAndGroupCountVO;
    }

    @Override
    @ParamLog("获取分类数与用户总数")
    public ClassifyAndUserCountVO getClassifyAndUserCount(Long bookGroupId) {
        ClassifyAndUserCountVO classifyAndUserCountVO = new ClassifyAndUserCountVO();
        final Map<Long, BookGroupStatisticDTO> statistic = bookGroupClassifyDao.getClassifyCountAbout(Collections.singletonList(bookGroupId));
        if (CollectionUtils.isEmpty(statistic) || null == statistic.get(bookGroupId)) {
            classifyAndUserCountVO.setClassifyCount(0);
        } else {
            classifyAndUserCountVO.setClassifyCount(statistic.get(bookGroupId).getClassifyCount());
        }
        Integer userCount = bookGroupClassifyDao.getUserNumberCount(bookGroupId);
        classifyAndUserCountVO.setUserCount(userCount);
        return classifyAndUserCountVO;
    }

    @Override
    @ParamLog("获取分类社群码名称以及最大群数量")
    public GroupNameAndMaxSeqDTO getGroupNameAndMaxSeq(Long classifyId) {
        return bookGroupClassifyDao.getGroupNameAndMaxSeq(classifyId);
    }

    @Override
    @ParamLog("获取分类二维码相关标识")
    public GroupClassifyQrcodeDTO getClassifyQrcodeInfo(String weixinGroupId) {
        return bookGroupClassifyDao.getClassifyQrcodeInfo(weixinGroupId);
    }

    @Override
    @ParamLog("获取分类二维码相关标识")
    public List<GroupClassifyQrcodeDTO> listClassifyQrcodeInfo(List<Long> classifyIds) {
        return bookGroupClassifyDao.listClassifyQrcodeInfo(classifyIds);
    }

    @Override
    @ParamLog("客户端获取分类信息")
    public List<ListClassify4WechatVO> listClassify4Wechat(Long bookGroupId, Long wechatUserId) {
        //获取排序方式
        Integer rankType = bookGroupBiz.getRankType(bookGroupId);
        List<ListClassify4WechatVO> listClassify4WechatVOS = bookGroupClassifyDao.listClassify4Wechat(bookGroupId, rankType);
        if (listClassify4WechatVOS == null) {
            return new ArrayList<>();
        }
        //设置二维码信息
        setGroupQrcodeInfo(listClassify4WechatVOS);
        //获取头像信息
        //setUserHeader(listClassify4WechatVOS);
        //设置是否购买
        setIsBuy(listClassify4WechatVOS, Collections.singletonList(wechatUserId));
        return listClassify4WechatVOS;
    }

    @Override
    @ParamLog("APP获取分类信息")
    public List<ListClassify4WechatVO> listClassify4APP(Long bookGroupId, Long wechatUserId) {
        List<Long> appWechatUserIds = readerConsr.getAppWechatUserIds(wechatUserId);
        //获取排序方式
        Integer rankType = bookGroupBiz.getRankType(bookGroupId);
        List<ListClassify4WechatVO> listClassify4WechatVOS = bookGroupClassifyDao.listClassify4Wechat(bookGroupId, rankType);
        if (listClassify4WechatVOS == null) {
            return new ArrayList<>();
        }
        //设置二维码信息
        setGroupQrcodeInfo(listClassify4WechatVOS);
        //设置是否购买
        setIsBuy(listClassify4WechatVOS, appWechatUserIds);
        return listClassify4WechatVOS;
    }

    @ParamLog(value = "设置是否购买", isBefore = false)
    private void setIsBuy(List<ListClassify4WechatVO> listClassify4Wechats, List<Long> wechatUserIds) {
        if (ListUtils.isEmpty(listClassify4Wechats)) {
            return;
        }
        if (ListUtils.isEmpty(wechatUserIds)) {
            return;
        }
        List<Long> classifyIds = new ArrayList<>();
        for (ListClassify4WechatVO listClassify4WechatVO : listClassify4Wechats) {
            classifyIds.add(listClassify4WechatVO.getClassifyId());
        }
        //根据二维码获取二维码基本信息
        List<Long> buyClassifyIds = bookClassifyBuyRecordDao.checkUsersBuy(classifyIds, wechatUserIds);
        if (ListUtils.isEmpty(buyClassifyIds)) {
            return;
        }
        for (ListClassify4WechatVO listClassify4WechatVO : listClassify4Wechats) {
            if (buyClassifyIds.contains(listClassify4WechatVO.getClassifyId())) {
                listClassify4WechatVO.setBuy(true);
            }
        }
    }

    @Override
    @ParamLog("客户端根据群分类获取二维码")
    public GroupQrcode4ClassifyVO getGroupQrcode4ClassifyWechat(Long classifyId, Long wechatUserId) {

        // 临时替换为企业微信加好友流程
        if (JedisClusterUtils.exists("WECHAT_GROUP_BAN_PROCESS") && Objects.isNull(classifyId)) {
            GroupQrcode4ClassifyVO vo = new GroupQrcode4ClassifyVO();
            vo.setQrcodeUrl(JedisClusterUtils.get("WECHAT_GROUP_BAN_PROCESS"));
            return vo;
        }

        //获取分类基本信息
        ClassifyVO classify = bookGroupClassifyDao.getClassify(classifyId);
        if (classify == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "社群码不存在，请刷新后重试");
        }

        if (new BigDecimal(0).compareTo(classify.getPrice()) < 0) {
            //校验用户是否正版授权
            Boolean isAuth = bookAuthUserBiz.checkIsHaveAuth(classify.getBookId(), classify.getChannelId(), classify.getCreateUser(), wechatUserId, 1,null,null);
            if(!isAuth) {
                //校验用户是否购买
                Boolean isBuy = bookClassifyBuyRecordDao.checkUserBuy(wechatUserId, classifyId);
                if (!isBuy) {
                    throw new BookBizException(BookBizException.PARAM_IS_NULL, "您还未购买，请购买后使用！");
                }
            }
        }

        //获取用户是否分配过二维码
        GroupQrcode4ClassifyVO groupQrcode4ClassifyVO = bookQrcodeUserDao.getUserQrcode(classifyId, wechatUserId);
        if (groupQrcode4ClassifyVO == null) {
            //获取分类对应的二维码
            groupQrcode4ClassifyVO = bookGroupClassifyDao.getClassifyQrcode(classifyId, classify.getChangeNumber());
            if (groupQrcode4ClassifyVO == null) {
                groupQrcode4ClassifyVO = new GroupQrcode4ClassifyVO();
                groupQrcode4ClassifyVO.setClassifyId(classifyId);
            } else {
                BookQrcodeUser bookQrcodeUser = new BookQrcodeUser();
                bookQrcodeUser.setClassifyId(classifyId);
                bookQrcodeUser.setGroupQrcodeId(groupQrcode4ClassifyVO.getGroupQrcodeId());
                bookQrcodeUser.setWechatUserId(wechatUserId);
                bookQrcodeUser.setCreateUser(wechatUserId);
                try {
                    bookQrcodeUserDao.insert(bookQrcodeUser);
                } catch (DataIntegrityViolationException e) {
                    LOGGER.error("已存在该用户！");
                }
            }
        }
        String spareQr = getSpareQr(classify.getBookGroupId());
        groupQrcode4ClassifyVO.setSpareQr(spareQr);
        groupQrcode4ClassifyVO.setClassify(classify.getClassify());
        return groupQrcode4ClassifyVO;
    }

    @Override
    @ParamLog("[getWxGroupIdByClassifyIdAndWechatId]")
    public GroupQrcodeBaseInfoVO getWxGroupIdByClassifyIdAndWechatId(Long classifyId, Long wechatUserId) {
        if(null == classifyId || null == wechatUserId) {
            return null;
        }
        final GroupQrcode4ClassifyVO wechat = this.getGroupQrcode4ClassifyWechat(classifyId, wechatUserId);
        if(null == wechat) {
            return null;
        }
        final GroupQrcodeBaseInfoVO baseById = this.groupQrcodeBiz.getBaseById(wechat.getGroupQrcodeId());
        return baseById;
    }

    @ParamLog("获取备用二维码")
    private String getSpareQr(Long bookGroupId) {
        //获取备用二维码
        String spareQr = bookGroupBiz.getSpareQr(bookGroupId);
        if (StringUtil.isEmpty(spareQr)) {
            spareQr = promotionConsr.getSpareQr();
        }
        return spareQr;
    }

    @Override
    @ParamLog("获取编辑所有的分类")
    public PageBeanNew<BookGroupClassifyVO> listGroupClassifyByAdviser(ListGroupClassifyParam listGroupClassifyParam, Long adviserId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("adviserId", adviserId);
        if (!StringUtil.isEmpty(listGroupClassifyParam.getName())) {
            paramMap.put("name", listGroupClassifyParam.getName());
        }
        paramMap.put("bookIds", listGroupClassifyParam.getBookIds());
        paramMap.put("proLabelId",listGroupClassifyParam.getProLabelId());
        paramMap.put("depLabelId",listGroupClassifyParam.getDepLabelId());
        paramMap.put("purLabelId",listGroupClassifyParam.getPurLabelId());
        PageParam pageParam = new PageParam(listGroupClassifyParam.getCurrentPage(), listGroupClassifyParam.getNumPerPage());
        PageBeanNew<BookGroupClassifyVO> pageBeanNew = bookGroupClassifyDao.listPageNew(pageParam, paramMap, "listGroupClassifyByAdviser");
        if (pageBeanNew == null) {
            return new PageBeanNew<>(listGroupClassifyParam.getCurrentPage(), listGroupClassifyParam.getNumPerPage(), new ArrayList<>());
        }
        //遍历填充标签
        List<BookGroupClassifyVO> bookGroupClassifyVOS = pageBeanNew.getRecordList();
        if (!ListUtils.isEmpty(bookGroupClassifyVOS)) {
            List<Long> labelIds = new ArrayList<>();
            List<Long> classifyIds = new ArrayList<>();
            for (BookGroupClassifyVO bookGroupClassifyVO : bookGroupClassifyVOS) {
                classifyIds.add(bookGroupClassifyVO.getClassifyId());
                if (bookGroupClassifyVO.getProLabelId() != null) {
                    labelIds.add(bookGroupClassifyVO.getProLabelId());
                }
                if (bookGroupClassifyVO.getPurLabelId() != null) {
                    labelIds.add(bookGroupClassifyVO.getPurLabelId());
                }
                if (bookGroupClassifyVO.getDepLabelId() != null) {
                    labelIds.add(bookGroupClassifyVO.getDepLabelId());
                }
            }
            Map<Long, Integer> activeCountMap = wechatGroupConsr.get7DayActiveUserCountByClassify(classifyIds);
            Map<Long, String> labelMap = new HashMap<>();
            if (!ListUtils.isEmpty(labelIds)) {
                labelMap = ResponseHandleUtil.parseMap(labelService.getLabelName(labelIds), Long.class, String.class);
            }
            for (BookGroupClassifyVO bookGroupClassifyVO : bookGroupClassifyVOS) {
                if (!MapUtils.isEmpty(labelMap)) {
                    Long proLabelId = bookGroupClassifyVO.getProLabelId();
                    Long purLabelId = bookGroupClassifyVO.getPurLabelId();
                    Long depLabelId = bookGroupClassifyVO.getDepLabelId();
                    if (proLabelId != null) {
                        bookGroupClassifyVO.setProLabelName(labelMap.get(proLabelId));
                    }
                    if (purLabelId != null) {
                        bookGroupClassifyVO.setPurLabelName(labelMap.get(purLabelId));
                    }
                    if (depLabelId != null) {
                        bookGroupClassifyVO.setDepLabelName(labelMap.get(depLabelId));
                    }
                }
                //最近7天活跃人数
                Integer count = activeCountMap.get(bookGroupClassifyVO.getClassifyId());
                if (count == null) {
                    bookGroupClassifyVO.setWeekActiveNumber(0);
                } else {
                    bookGroupClassifyVO.setWeekActiveNumber(count);
                }
            }
        }
        return pageBeanNew;
    }

    @Override
    @ParamLog("获取社群码统计数据（分类数，群总人数，群数量）")
    public Map<Long, BookGroupStatisticDTO> getBookGroupStatistic(List<Long> bookGroupIds) {
        return bookGroupClassifyDao.getBookGroupStatistic(bookGroupIds);
    }

    @Override
    @ParamLog("获取单个群统计")
    public PageBeanNew<BookGroupQrcodeStatisticVO> listBookGroupQrcodeStatistic(ListBookGroupQrcodeParamVO listBookGroupQrcodeParamVO, Long adviserId) {
        PageParam pageParam = new PageParam(listBookGroupQrcodeParamVO.getCurrentPage(), listBookGroupQrcodeParamVO.getNumPerPage());
        Map<String, Object> paramMap = new HashMap<>();
        if (!ListUtils.isEmpty(listBookGroupQrcodeParamVO.getClassifyIds())) {
            paramMap.put("classifyIds", listBookGroupQrcodeParamVO.getClassifyIds());
        }
        paramMap.put("bookGroupId", listBookGroupQrcodeParamVO.getBookGroupId());
        PageBeanNew<BookGroupQrcodeStatisticVO> pageBeanNew = bookGroupClassifyDao.listPageNew(pageParam, paramMap, "listBookGroupQrcodeStatistic");
        if (pageBeanNew == null || pageBeanNew.getRecordList() == null) {
            return new PageBeanNew<>(pageBeanNew.getCurrentPage(), pageBeanNew.getNumPerPage(), new ArrayList<>());
        }
        //设置累计进群人数与今日进群人数
        setJoinUserNumberTotalAndToday(pageBeanNew.getRecordList());
        //设置活跃人数与总发言数
        setActiveNumberAndChatCount(pageBeanNew.getRecordList(), listBookGroupQrcodeParamVO.getBookGroupId());
        //设置收益
        setIncome(pageBeanNew.getRecordList(), adviserId);
        //设置购买次数与用户数
        setBuyUserNumberAndBuyCount(pageBeanNew.getRecordList());
        return pageBeanNew;
    }


    @Override
    @ParamLog("单个群统计导出")
    public void bookGroupQrcodeStatisticExport(List<Long> classifyIds, Long bookGroupId, Long adviserId) {
        ThreadPoolUtils.EXPORT_THREAD_POOL.execute(() -> {
            try {
                BookGroupDTO bookGroupInfo = bookGroupBiz.getBookGroupInfo(bookGroupId);
                if (bookGroupInfo == null) {
                    return;
                }
                Date sendDate = new Date();
                List<BookGroupQrcodeStatisticVO> groupQrcodeStatistics = bookGroupClassifyDao.listBookGroupQrcodeStatistic(classifyIds, bookGroupId);
                if (ListUtils.isEmpty(groupQrcodeStatistics)) {
                    return;
                }
                //设置累计进群人数与今日进群人数
                setJoinUserNumberTotalAndToday(groupQrcodeStatistics);
                //设置活跃人数与总发言数
                setActiveNumberAndChatCount(groupQrcodeStatistics, bookGroupId);
                //设置收益
                setIncome(groupQrcodeStatistics, adviserId);
                //设置购买次数与用户数
                setBuyUserNumberAndBuyCount(groupQrcodeStatistics);
                //导出数据
                exportData(groupQrcodeStatistics, sendDate, adviserId, bookGroupInfo.getGroupQrcodeName());
            } catch (Exception e) {
                LOGGER.error("导出失败classifyIds:" + classifyIds + "bookGroupId" + bookGroupId + "adviserId" + adviserId);
            }
        });
    }

    @Override
    public StatisticVO getStatistic4Adviser(Long adviserId) {
        return bookGroupClassifyDao.getStatistic4Adviser(adviserId);
    }

    @Override
    public Map<String, GroupQrcodeBaseDTO> listGroupQrcodeBaseInfo(List<String> weixinGroupIds) {
        if (ListUtils.isEmpty(weixinGroupIds)) {
            return null;
        }
        return bookGroupClassifyDao.listGroupQrcodeBaseInfo(weixinGroupIds);
    }

    @Override
    @ParamLog("获取商品关联群数量与人数")
    public ProAssocGroupAndUserNumberDTO getProAssocGroupAndUserNumber(Long productId) {
//        //获取商品关联的分类
//        List<Long> classifyIds = bookKeywordBiz.getAssocClassifyIds(productId);
        ProAssocGroupAndUserNumberDTO proAssocGroupAndUserNumberDTO = bookGroupClassifyDao.getProAssocGroupAndUserNumber(productId);
        return proAssocGroupAndUserNumberDTO;
    }

    @ParamLog(value = "设置购买用户数与购买次数", isAfterReturn = false, isBefore = false)
    private void setBuyUserNumberAndBuyCount(List<BookGroupQrcodeStatisticVO> groupQrcodeStatistics) {
        if (ListUtils.isEmpty(groupQrcodeStatistics)) {
            return;
        }
        List<BookGroupSaleSearchDto> list = new ArrayList<>();
        for (BookGroupQrcodeStatisticVO bookGroupQrcodeStatisticVO : groupQrcodeStatistics) {
            if (bookGroupQrcodeStatisticVO.getGroupQrcodeId() != null) {
                BookGroupSaleSearchDto bookGroupSaleSearchDto = new BookGroupSaleSearchDto();
                bookGroupSaleSearchDto.setGroupQrcodeId(bookGroupQrcodeStatisticVO.getGroupQrcodeId());
                bookGroupSaleSearchDto.setClassifyId(bookGroupQrcodeStatisticVO.getClassifyId());
                list.add(bookGroupSaleSearchDto);
            }
        }
        Map<Long, QrGroupBuyDetailDto> buyMap = tradeConsr.getQrGroupSaleInfo(list);
        for (BookGroupQrcodeStatisticVO bookGroupQrcodeStatisticVO : groupQrcodeStatistics) {
            if (buyMap != null) {
                QrGroupBuyDetailDto qrGroupBuyDetailDto = buyMap.get(bookGroupQrcodeStatisticVO.getGroupQrcodeId());
                bookGroupQrcodeStatisticVO.setBuyCount(qrGroupBuyDetailDto == null ? 0L : qrGroupBuyDetailDto.getBuyCount());
                bookGroupQrcodeStatisticVO.setBuyUserNumber(qrGroupBuyDetailDto == null ? 0L : qrGroupBuyDetailDto.getPayPersonCount());
            } else {
                bookGroupQrcodeStatisticVO.setBuyCount(0L);
                bookGroupQrcodeStatisticVO.setBuyUserNumber(0L);
            }
        }


    }

    @ParamLog(value = "导出数据")
    private void exportData(List<BookGroupQrcodeStatisticVO> groupQrcodeStatistics, Date sendDate, Long adviserId, String bookGroupName) {
        if (ListUtils.isEmpty(groupQrcodeStatistics)) {
            return;
        }
        List<Object[]> dataList = new ArrayList<Object[]>();
        for (int i = 0, size = groupQrcodeStatistics.size(); i < size; i++) {
            BookGroupQrcodeStatisticVO bookGroupQrcodeStatisticVO = groupQrcodeStatistics.get(i);
            Object[] obj = new Object[11];
            obj[0] = i + 1;
            obj[1] = bookGroupQrcodeStatisticVO.getGroupName();
            obj[2] = bookGroupQrcodeStatisticVO.getClassify();
            obj[3] = bookGroupQrcodeStatisticVO.getGroupUserNumber();
            obj[4] = bookGroupQrcodeStatisticVO.getJoinUserNumberToday();
            obj[5] = bookGroupQrcodeStatisticVO.getJoinUserNumberTotal();
            obj[6] = bookGroupQrcodeStatisticVO.getActiveUserCount();
            obj[7] = bookGroupQrcodeStatisticVO.getChatCount();
            obj[8] = bookGroupQrcodeStatisticVO.getBuyCount();
            obj[9] = bookGroupQrcodeStatisticVO.getBuyUserNumber();
            obj[10] = bookGroupQrcodeStatisticVO.getIncome();
            dataList.add(obj);
        }
        String[] rowsName = {"序号", "群名称", "群分类", "当前群总人数", "今日进群人数", "累计进群人数", "活跃人数",
                "总发言数", "购买次数", "购买人数", "收益"};
        String fileName = bookGroupName + "单个群统计-" + DateUtils.getStrFormTime("yyyyMMdd", new Date());
        String fileUrl = exportConsr.exportExcel(fileName, rowsName, dataList);
        String letterType = "pcloud_book_download";
        String content = String.format("{\"commitTime\":\"%s\",\"type\":\"%s\"}", DateUtils.formatDate(sendDate), fileName);
        messageConsr.sendLetter(adviserId, adviserId, content, SystemCode.adviser.code, letterType, fileUrl, fileName, NotifyOriginTypeEnum.BOOK_GROUP.value, null);
    }

    @ParamLog(value = "设置收益", isAfterReturn = false, isBefore = false)
    private void setIncome(List<BookGroupQrcodeStatisticVO> groupQrcodeStatistics, Long adviserId) {
        if (ListUtils.isEmpty(groupQrcodeStatistics)) {
            return;
        }
        List<Long> groupQrcodeIds = new ArrayList<>();
        for (BookGroupQrcodeStatisticVO bookGroupQrcodeStatisticVO : groupQrcodeStatistics) {
            if (bookGroupQrcodeStatisticVO.getGroupQrcodeId() != null) {
                groupQrcodeIds.add(bookGroupQrcodeStatisticVO.getGroupQrcodeId());
            }
        }
        Map<Long, BigDecimal> wxGroupQrcodeIncomeMap = settlementConsr.getWXGroupQrcodeIncomeByAdviser(groupQrcodeIds, adviserId);
        for (BookGroupQrcodeStatisticVO bookGroupQrcodeStatisticVO : groupQrcodeStatistics) {
            if (wxGroupQrcodeIncomeMap != null) {
                bookGroupQrcodeStatisticVO.setIncome(wxGroupQrcodeIncomeMap.get(bookGroupQrcodeStatisticVO.getGroupQrcodeId()) == null ? new BigDecimal(0) : wxGroupQrcodeIncomeMap.get(bookGroupQrcodeStatisticVO.getGroupQrcodeId()));
            } else {
                bookGroupQrcodeStatisticVO.setIncome(new BigDecimal(0));
            }
        }
    }

    @ParamLog(value = "设置活跃人数与总发言数", isAfterReturn = false, isBefore = false)
    private void setActiveNumberAndChatCount(List<BookGroupQrcodeStatisticVO> groupQrcodeStatistics, Long bookGroupId) {
        if (ListUtils.isEmpty(groupQrcodeStatistics)) {
            return;
        }
        List<Long> groupQrcodeIds = new ArrayList<>();
        for (BookGroupQrcodeStatisticVO bookGroupQrcodeStatisticVO : groupQrcodeStatistics) {
            if (bookGroupQrcodeStatisticVO.getGroupQrcodeId() != null) {
                groupQrcodeIds.add(bookGroupQrcodeStatisticVO.getGroupQrcodeId());
            }
        }
        Map<Long, GroupChatCountDTO> groupChatCountMap = wechatGroupConsr.getChatCountByGroup(groupQrcodeIds, bookGroupId);
        for (BookGroupQrcodeStatisticVO bookGroupQrcodeStatisticVO : groupQrcodeStatistics) {
            if (groupChatCountMap != null) {
                GroupChatCountDTO groupChatCountDTO = groupChatCountMap.get(bookGroupQrcodeStatisticVO.getGroupQrcodeId());
                bookGroupQrcodeStatisticVO.setChatCount(groupChatCountDTO == null ? 0 : groupChatCountDTO.getChatCount());
                bookGroupQrcodeStatisticVO.setActiveUserCount(groupChatCountDTO == null ? 0 : groupChatCountDTO.getActiveUserCount());
            } else {
                bookGroupQrcodeStatisticVO.setChatCount(0);
                bookGroupQrcodeStatisticVO.setActiveUserCount(0);
            }
        }
    }


    @ParamLog(value = "设置累计进群人数与今日进群人数", isAfterReturn = false, isBefore = false)
    private void setJoinUserNumberTotalAndToday(List<BookGroupQrcodeStatisticVO> groupQrcodeStatistics) {
        if (ListUtils.isEmpty(groupQrcodeStatistics)) {
            return;
        }
        List<String> weixinGroupIds = new ArrayList<>();
        for (BookGroupQrcodeStatisticVO bookGroupQrcodeStatisticVO : groupQrcodeStatistics) {
            if (!StringUtil.isEmpty(bookGroupQrcodeStatisticVO.getWeixinGroupId())) {
                weixinGroupIds.add(bookGroupQrcodeStatisticVO.getWeixinGroupId());
            }
        }
        Map<String, GroupMemberStatisDTO> groupMemberStatisMap = wechatGroupConsr.listGroupMemberStatisInfo(weixinGroupIds);
        for (BookGroupQrcodeStatisticVO bookGroupQrcodeStatisticVO : groupQrcodeStatistics) {
            if (groupMemberStatisMap != null) {
                GroupMemberStatisDTO groupMemberStatisDTO = groupMemberStatisMap.get(bookGroupQrcodeStatisticVO.getWeixinGroupId());
                bookGroupQrcodeStatisticVO.setJoinUserNumberTotal(groupMemberStatisDTO == null ? 0 : groupMemberStatisDTO.getJoinCount());
                bookGroupQrcodeStatisticVO.setJoinUserNumberToday(groupMemberStatisDTO == null ? 0 : groupMemberStatisDTO.getJoinCountToday());
            } else {
                bookGroupQrcodeStatisticVO.setJoinUserNumberTotal(0);
                bookGroupQrcodeStatisticVO.setJoinUserNumberToday(0);
            }
        }
    }


    @ParamLog("设置用户头像")
    private void setUserHeader(List<ListClassify4WechatVO> listClassify4WechatVOS) {
        if (ListUtils.isEmpty(listClassify4WechatVOS)) {
            return;
        }
        List<WechatUserRobotDto> wechatUserRand = readerConsr.selectRobotsRandom(listClassify4WechatVOS.size() * 9);
        if (ListUtils.isEmpty(wechatUserRand)) {
            return;
        }
        for (int i = 0; i < listClassify4WechatVOS.size(); i++) {
            ListClassify4WechatVO listClassify4WechatVO = listClassify4WechatVOS.get(i);
            List<WechatUserRobotDto> wechatUsers;
            if (wechatUserRand.size() >= (i + 1) * 9) {
                wechatUsers = wechatUserRand.subList(i * 9, (i + 1) * 9);
            } else {
                wechatUsers = wechatUserRand.subList(wechatUserRand.size() - 9 > 0 ? 0 : wechatUserRand.size() - 9, wechatUserRand.size());
            }
            List<String> headUrls = wechatUsers.stream().map(a -> a.getWechatUserHeadUrl()).collect(Collectors.toList());
            listClassify4WechatVO.setHeadUrl(headUrls);
        }
    }

    /**
     * @Author:lili
     * @Desr:设置分类下当前使用二维码
     * @Date:2019/4/29 14:37
     */
    private void setGroupQrcodeInfo(List<ListClassify4WechatVO> listClassify4Wechats) {
        if (ListUtils.isEmpty(listClassify4Wechats)) {
            return;
        }
        List<Long> groupQrcodeIds = new ArrayList<>();
        for (ListClassify4WechatVO listClassify4WechatVO : listClassify4Wechats) {
            groupQrcodeIds.add(listClassify4WechatVO.getGroupQrcodeId());
        }
        //根据二维码获取二维码基本信息
        Map<Long, GroupQrcodeInfoDTO> groupQrcodeMap = groupQrcodeBiz.listQrcodeInfoByIds(groupQrcodeIds);
        if (MapUtils.isEmpty(groupQrcodeMap)) {
            return;
        }
        for (ListClassify4WechatVO listClassify4WechatVO : listClassify4Wechats) {
            GroupQrcodeInfoDTO groupQrcodeInfoDTO = groupQrcodeMap.get(listClassify4WechatVO.getGroupQrcodeId());
            if (groupQrcodeInfoDTO != null) {
                listClassify4WechatVO.setUserNumber(groupQrcodeInfoDTO.getUserNumber());
                listClassify4WechatVO.setGroupSeq(groupQrcodeInfoDTO.getGroupSeq());
                List<String> headUrls = BookConstant.getRandomHeadUrl(groupQrcodeInfoDTO.getUserNumber() > 9 ? 9 : groupQrcodeInfoDTO.getUserNumber());
                listClassify4WechatVO.setHeadUrl(headUrls);
            }
        }
    }

    /**
     * @Author:lili
     * @Desr:设置分类下当前使用二维码
     * @Date:2019/4/29 14:37
     */
    private void setGroupQrcodeInfo4Heals(List<ListClassify4WechatDTO> listClassify4Wechats) {
        if (ListUtils.isEmpty(listClassify4Wechats)) {
            return;
        }
        List<Long> groupQrcodeIds = new ArrayList<>();
        for (ListClassify4WechatDTO listClassify4WechatVO : listClassify4Wechats) {
            groupQrcodeIds.add(listClassify4WechatVO.getGroupQrcodeId());
        }
        //根据二维码获取二维码基本信息
        Map<Long, GroupQrcodeInfoDTO> groupQrcodeMap = groupQrcodeBiz.listQrcodeInfoByIds(groupQrcodeIds);
        if (MapUtils.isEmpty(groupQrcodeMap)) {
            return;
        }
        for (ListClassify4WechatDTO listClassify4WechatVO : listClassify4Wechats) {
            GroupQrcodeInfoDTO groupQrcodeInfoDTO = groupQrcodeMap.get(listClassify4WechatVO.getGroupQrcodeId());
            if (groupQrcodeInfoDTO != null) {
                listClassify4WechatVO.setUserNumber(groupQrcodeInfoDTO.getUserNumber());
                listClassify4WechatVO.setGroupSeq(groupQrcodeInfoDTO.getGroupSeq());
                List<String> headUrls = BookConstant.getRandomHeadUrl(groupQrcodeInfoDTO.getUserNumber() > 9 ? 9 : groupQrcodeInfoDTO.getUserNumber());
                listClassify4WechatVO.setHeadUrl(headUrls);
            }
        }
    }

    /**
     * 获取社群书分类列表(编辑)
     * @param adviserId
     * @param bookGroupClassify
     * @return
     */
    @Override
    @ParamLog("获取社群书分类列表(编辑)")
    public PageBeanNew<ClassifyDTO> listSimpleBookGroupClassify4Adviser(Long adviserId, BookGroupClassify bookGroupClassify,PageParam pageParam) {
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("adviserId",adviserId);
        if(!StringUtil.isEmpty(bookGroupClassify.getClassify())){
            paramMap.put("classify",bookGroupClassify.getClassify());
        }
        if(!ListUtils.isEmpty(bookGroupClassify.getBookGroupIds())){
            paramMap.put("bookGroupIds",bookGroupClassify.getBookGroupIds());
        }
        return bookGroupClassifyDao.listPageNew(pageParam,paramMap,"listSimpleBookGroupClassify4Adviser");
    }

    @Override
    @ParamLog("获取编辑的分类")
    public PageBeanNew<AdviserClassifyVO> listAdviserClassify(Long adviserId, AdviserClassifyParam adviserClassifyParam) {
        PageParam pageParam = new PageParam(adviserClassifyParam.getCurrentPage(), adviserClassifyParam.getNumPerPage());
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("adviserId", adviserId);
        paramMap.put("classify", adviserClassifyParam.getClassify());
        paramMap.put("bookId", adviserClassifyParam.getBookId());
        PageBeanNew<AdviserClassifyVO> pageBeanNew = bookGroupClassifyDao.listPageNew(pageParam, paramMap, "listAdviserClassify");
        if (pageBeanNew == null) {
            return new PageBeanNew<>(adviserClassifyParam.getCurrentPage(), adviserClassifyParam.getNumPerPage(), new ArrayList<>());
        }
        return pageBeanNew;
    }

    @Override
    public Map<Long, BookClassifyDTO> getGroupClassifyCount(List<Long> bookIds) {
        if (!ListUtils.isEmpty(bookIds)){
            return bookGroupClassifyDao.getGroupClassifyCount(bookIds);
        }else {
            return new HashMap<>();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("更新是否开启微学习报告")
    @Override
    public void updateHasOpenLearningReport(Long classifyId, Boolean hasOpenLearningReport, Long partyId) {
        bookGroupClassifyDao.updateHasOpenLearningReport(classifyId,hasOpenLearningReport,partyId);
    }

    @ParamLog("获取群分类学习报告相关列表")
    @Override
    public PageBeanNew<ClassifyLearningReportDto> listClassifyForLearningReport(Integer currentPage, Integer numPerPage, String keyword, Long partyId) {
        PageParam pageParam = new PageParam(currentPage, numPerPage);
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("keyword", keyword);
        paramMap.put("partyId", partyId);
        PageBeanNew<ClassifyLearningReportDto> pageBeanNew = bookGroupClassifyDao.listPageNew(pageParam, paramMap, "listClassifyForLearningReport");
        if (pageBeanNew == null) {
            return new PageBeanNew<>(currentPage, numPerPage, new ArrayList<>());
        }
        //遍历填充标签
        List<ClassifyLearningReportDto> list = pageBeanNew.getRecordList();
        if (!ListUtils.isEmpty(list)) {
            List<Long> labelIds = new ArrayList<>();
            List<Long> classifyIds = new ArrayList<>();
            for (ClassifyLearningReportDto classifyLearningReportDto : list) {
                classifyIds.add(classifyLearningReportDto.getClassifyId());
                if (classifyLearningReportDto.getProLabelId() != null) {
                    labelIds.add(classifyLearningReportDto.getProLabelId());
                }
                if (classifyLearningReportDto.getPurLabelId() != null) {
                    labelIds.add(classifyLearningReportDto.getPurLabelId());
                }
                if (classifyLearningReportDto.getDepLabelId() != null) {
                    labelIds.add(classifyLearningReportDto.getDepLabelId());
                }
            }
            Map<Long, Integer> browseCountMap = new HashMap<>();
            Map<Long, Integer> touchCountMap = new HashMap<>();
            if (!ListUtils.isEmpty(classifyIds)) {
                List<ClassifyLearningCountDto> browseCountList = learningReportBrowseRecordDao.getCountGroupByClassifyId(classifyIds);
                List<ClassifyLearningCountDto> touchCountList = learningReportTouchRecordDao.getCountGroupByClassifyId(classifyIds);
                for (ClassifyLearningCountDto classifyLearningCountDto:browseCountList){
                    browseCountMap.put(classifyLearningCountDto.getClassifyId(),classifyLearningCountDto.getCount());
                }
                for (ClassifyLearningCountDto classifyLearningCountDto:touchCountList){
                    touchCountMap.put(classifyLearningCountDto.getClassifyId(),classifyLearningCountDto.getCount());
                }
            }
            Map<Long, String> labelMap = new HashMap<>();
            if (!ListUtils.isEmpty(labelIds)) {
                labelMap = ResponseHandleUtil.parseMap(labelService.getLabelName(labelIds), Long.class, String.class);
            }
            for (ClassifyLearningReportDto classifyLearningReportDto : list) {
                if (!MapUtils.isEmpty(labelMap)) {
                    Long proLabelId = classifyLearningReportDto.getProLabelId();
                    if (proLabelId != null) {
                        classifyLearningReportDto.setProLabelName(labelMap.get(proLabelId));
                    }
                    Long purLabelId = classifyLearningReportDto.getPurLabelId();
                    if (purLabelId != null) {
                        classifyLearningReportDto.setPurLabelName(labelMap.get(purLabelId));
                    }
                    Long depLabelId = classifyLearningReportDto.getDepLabelId();
                    if (depLabelId != null) {
                        classifyLearningReportDto.setDepLabelName(labelMap.get(depLabelId));
                    }
                }
                Integer browseCount = browseCountMap.get(classifyLearningReportDto.getClassifyId());
                if (browseCount == null) {
                    browseCount = 0;
                }
                Integer touchCount = touchCountMap.get(classifyLearningReportDto.getClassifyId());
                if (touchCount == null) {
                    touchCount = 0;
                }
                classifyLearningReportDto.setLearningReportBrowseCount(browseCount);
                classifyLearningReportDto.setLearningReportTouchCount(touchCount);
            }
        }
        return pageBeanNew;

    }


    @ParamLog("拖动排序")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void dragSortClassify(List<Long> classifyIds) {
        if (ListUtils.isEmpty(classifyIds)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数为空！");
        }
        bookGroupClassifyDao.dragSortClassify(classifyIds);
    }

    @Override
    public BigDecimal getPayPrice(Long qrcodeId, String wxId) {
        return joinGroupCipherDao.getPayPrice(wxId, qrcodeId);
    }

    @Override
    public void clickClassify(Long wechatUserId, Long bookGroupId, Long classifyId) {
        bookGroupClassifyDao.addClickClassify(wechatUserId,bookGroupId,classifyId);
    }


    @Override
    public List<ListClassifyVO> getClassifyIngoreDelete(Long bookGroupId) {
        List<ListClassifyVO> classifyVOS = bookGroupClassifyDao.getClassifyIngoreDelete(bookGroupId);
        if (ListUtils.isEmpty(classifyVOS)){
            return new ArrayList<>();
        }
        return classifyVOS;
    }

    @ParamLog("个人号模式获取一个群")
    @Override
    public String getSelfGroup(Long classifyId, Integer changeNumber, String altId) {
        GroupRobotDTO groupRobotDTO = wechatGroupConsr.getGroupRobotByWxId(altId);
        if (groupRobotDTO == null) {
            return null;
        }
        ClassifyVO classifyVO = bookGroupClassifyDao.getClassify(classifyId);
        if (classifyVO==null){
            return null;
        }
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(classifyVO.getBookGroupId());
        if (bookGroupDTO==null){
            return null;
        }
        //先判断有没有已经存在的群
        List<GroupQrcode> groupQrcodes = groupQrcodeDao.getUsingGroupQrcodeByClassifyId(classifyId, changeNumber);
        log.info("查询到该分类下已经存在的群" + groupQrcodes.toString());
        if (!ListUtils.isEmpty(groupQrcodes)) {
            for (GroupQrcode groupQrcode:groupQrcodes){
                //判断这个群是否跟这个小号对应，如果对应就返回该群，如果不对应证明已经切小号了，重新分配新的群
                WeixinQrcode weixinQrcode = weixinQrcodeDao.getByGroupId(groupQrcode.getWeixinGroupId());
                if (weixinQrcode != null && groupRobotDTO.getVersion() != null && groupRobotDTO.getVersion().equals(weixinQrcode.getGeneration())) {
                    log.info("返回已经有的能对应上的群" + groupQrcode.getWeixinGroupId());
                    return groupQrcode.getWeixinGroupId();
                }
            }
        }
        //没有找到合适的群，根据机器人id重新切一个群
        WeixinQrcodeDTO weixinQrcodeDTO = weixinQrcodeBiz.getOneQrcode(JoinGroupTypeEnum.ROBOT.getCode(), altId);
        if (weixinQrcodeDTO != null) {
            log.info("没有找到合适的群，根据机器人id重新切一个群"+weixinQrcodeDTO.toString());
            groupQrcodeBiz.dealAfterChangeANewGroup(weixinQrcodeDTO, classifyId);
            return weixinQrcodeDTO.getWeixinGroupId();
        }
        log.info("没有可用的群classifyId="+classifyId+"altId="+altId+"changeNumber="+changeNumber);
        return null;
    }

    @ParamLog("根据类型获取分类数量")
    @Override
    public Integer getClassifyCountByJoinGroupType(Integer joinGroupType) {
        return bookGroupClassifyDao.getClassifyCountByJoinGroupType(joinGroupType);
    }

    @Override
    public GroupQrcode4ClassifyVO getGroupQrcode4Applet(Long classifyId, Long wechatUserId) {
        //获取分类基本信息
        ClassifyVO classify = bookGroupClassifyDao.getClassify(classifyId);
        if (classify == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "社群码不存在，请刷新后重试");
        }

        //获取用户是否分配过二维码
        GroupQrcode4ClassifyVO groupQrcode4ClassifyVO = bookQrcodeUserDao.getUserQrcode(classifyId, wechatUserId);
        if (groupQrcode4ClassifyVO == null) {
            //获取分类对应的二维码
            groupQrcode4ClassifyVO = bookGroupClassifyDao.getClassifyQrcode(classifyId, classify.getChangeNumber());
            if (groupQrcode4ClassifyVO == null) {
                groupQrcode4ClassifyVO = new GroupQrcode4ClassifyVO();
                groupQrcode4ClassifyVO.setClassifyId(classifyId);
            } else {
                BookQrcodeUser bookQrcodeUser = new BookQrcodeUser();
                bookQrcodeUser.setClassifyId(classifyId);
                bookQrcodeUser.setGroupQrcodeId(groupQrcode4ClassifyVO.getGroupQrcodeId());
                bookQrcodeUser.setWechatUserId(wechatUserId);
                bookQrcodeUser.setCreateUser(wechatUserId);
                try {
                    bookQrcodeUserDao.insert(bookQrcodeUser);
                } catch (DataIntegrityViolationException e) {
                    LOGGER.error("已存在该用户！");
                }
            }
        }
        String spareQr = getSpareQr(classify.getBookGroupId());
        groupQrcode4ClassifyVO.setSpareQr(spareQr);
        groupQrcode4ClassifyVO.setClassify(classify.getClassify());
        return groupQrcode4ClassifyVO;
    }

    @Override
    public GroupQrcode4ClassifyVO getGroupQrcodeInfo4Heals(Long classifyId, Long wechatUserId) {
        //获取分类基本信息
        ClassifyVO classify = bookGroupClassifyDao.getClassify(classifyId);
        if (classify == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "社群码不存在，请刷新后重试");
        }

        //获取用户是否分配过二维码
        GroupQrcode4ClassifyVO groupQrcode4ClassifyVO = bookQrcodeUserDao.getUserQrcode(classifyId, wechatUserId);
        if (groupQrcode4ClassifyVO == null) {
            //获取分类对应的二维码
            groupQrcode4ClassifyVO = bookGroupClassifyDao.getClassifyQrcode(classifyId, classify.getChangeNumber());
            if (groupQrcode4ClassifyVO == null) {
                groupQrcode4ClassifyVO = new GroupQrcode4ClassifyVO();
                groupQrcode4ClassifyVO.setClassifyId(classifyId);
            } else {
                BookQrcodeUser bookQrcodeUser = new BookQrcodeUser();
                bookQrcodeUser.setClassifyId(classifyId);
                bookQrcodeUser.setGroupQrcodeId(groupQrcode4ClassifyVO.getGroupQrcodeId());
                bookQrcodeUser.setWechatUserId(wechatUserId);
                bookQrcodeUser.setCreateUser(wechatUserId);
                bookQrcodeUser.setFromType(QrcodeUsedEnum.HEALS.value);
                try {
                    bookQrcodeUserDao.insert(bookQrcodeUser);
                } catch (DataIntegrityViolationException e) {
                    LOGGER.error("已存在该用户！");
                }
            }
        }
        String spareQr = getSpareQr(classify.getBookGroupId());
        groupQrcode4ClassifyVO.setSpareQr(spareQr);
        groupQrcode4ClassifyVO.setClassify(classify.getClassify());
        return groupQrcode4ClassifyVO;
    }

    @Override
    public List<GroupQrcode4ClassifyDTO> getQrcodeByClassifyId4Heals(Long classifyId) {
        if(null==classifyId){
            return new ArrayList<>();
        }
        //获取分类基本信息
        ClassifyVO classify = bookGroupClassifyDao.getClassify(classifyId);
        if (classify == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "社群码不存在，请刷新后重试");
        }
        List<GroupQrcode4ClassifyDTO> list=bookGroupClassifyDao.getQrcodeByClassifyId4Heals(classifyId, classify.getChangeNumber());
        return list;
    }

    @Override
    public GroupQrcode4ClassifyVO getGroupQrcodeByClassify(Long classifyId, Long wechatUserId) {
        //获取分类基本信息
        ClassifyVO classify = bookGroupClassifyDao.getClassify(classifyId);
        if (classify == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "社群码不存在，请刷新后重试");
        }

        //获取分类对应的二维码
        GroupQrcode4ClassifyVO groupQrcode4ClassifyVO = bookGroupClassifyDao.getClassifyQrcode(classifyId, classify.getChangeNumber());
        if (groupQrcode4ClassifyVO == null) {
            groupQrcode4ClassifyVO = new GroupQrcode4ClassifyVO();
            groupQrcode4ClassifyVO.setClassifyId(classifyId);
        } else {
            BookQrcodeUser bookQrcodeUser = new BookQrcodeUser();
            bookQrcodeUser.setClassifyId(classifyId);
            bookQrcodeUser.setGroupQrcodeId(groupQrcode4ClassifyVO.getGroupQrcodeId());
            bookQrcodeUser.setWechatUserId(wechatUserId);
            bookQrcodeUser.setCreateUser(wechatUserId);
            bookQrcodeUser.setFromType(QrcodeUsedEnum.RAYS.value);
            try {
                bookQrcodeUserDao.insert(bookQrcodeUser);
            } catch (DataIntegrityViolationException e) {
                LOGGER.error("已存在该用户！");
            }
        }

        String spareQr = getSpareQr(classify.getBookGroupId());
        groupQrcode4ClassifyVO.setSpareQr(spareQr);
        groupQrcode4ClassifyVO.setClassify(classify.getClassify());
        return groupQrcode4ClassifyVO;
    }

    @Override
    public PageBeanNew<PcloudBookGroupClassifyVO> listGroupClassify4Pcloud(String name, Long proLabelId, Long depLabelId,Long purLabelId,Long firstClassifyId,Long gradeLabelId,Long subjectLabelId,Long agentId,Long adviserId, Integer currentPage, Integer numPerPage
            , String cityCode) {
        // 根据数命查bookid
        List<Long> ids = new ArrayList<>();
        if (!StringUtil.isEmpty(name)) {
            ids = bookDao.getBookIdsByBookName(name);
        }
        PageParam pageParam = new PageParam(currentPage, numPerPage);
        final Map<String, Object> map = Maps.newHashMap();
        map.put("list", ids);
        map.put("name", StringUtil.isEmpty(name) ? null : name);
        map.put("proLabelId", proLabelId);
        map.put("depLabelId", depLabelId);
        map.put("purLabelId", purLabelId);
        map.put("firstClassifyId", firstClassifyId);
        map.put("gradeLabelId", gradeLabelId);
        map.put("subjectLabelId", subjectLabelId);
        map.put("agentId", agentId);
        map.put("adviserId", adviserId);
        map.put("cityCode", cityCode);
        PageBeanNew<PcloudBookGroupClassifyVO> pageBeanNew = bookGroupClassifyDao.listPageNew(pageParam, map, "listGroupClassify4Pcloud");

        pageBeanNew.getRecordList().forEach(item->{
            Adviser adviser = ResponseHandleUtil.parseResponse(adviserService.getById(item.getAdviserId()), Adviser.class);

            String agentName = ResponseHandleUtil.parseResponse(agentService.getNameById(item.getAgentId()), String.class);

            item.setAdviserName(adviser.getName());
            item.setPhone(adviser.getPhone());
            item.setAgentName(agentName);

        });
        if (null != pageBeanNew && !ListUtils.isEmpty(pageBeanNew.getRecordList())){
            setCityName(pageBeanNew.getRecordList());
        }

        return pageBeanNew;
    }

    private void setCityName(List<PcloudBookGroupClassifyVO> recordList) {
        log.info("设置城市名称");
        if (ListUtils.isEmpty(recordList)){
            return;
        }
        List<String> cityCodes = recordList.stream().map(e -> e.getCityCode()).distinct().collect(Collectors.toList());
        if (ListUtils.isEmpty(cityCodes)) {
            return;
        }
        Map<String, RegionMap> regionMapMap = bookBrowseRecordBiz.getCitysByCodes(cityCodes);
        if (MapUtils.isNotEmpty(regionMapMap)){
            recordList.forEach(classifyVO -> {
                RegionMap regionMap = regionMapMap.get(classifyVO.getCityCode());
                if (regionMapMap.containsKey(classifyVO.getCityCode()) && null != regionMap){
                    classifyVO.setCityName(regionMap.getRegionName());
                }
            });
        }
    }

    @Override
    public List<ListClassify4WechatDTO> listClassify4Heals(List<Long> classifyIds, Long wechatUserId) {
        if(ListUtils.isEmpty(classifyIds)){
            return new ArrayList<>();
        }
        List<ListClassify4WechatDTO> listClassify4WechatVOS = bookGroupClassifyDao.listClassify4Heals(classifyIds, 0);
        if (listClassify4WechatVOS == null) {
            return new ArrayList<>();
        }
        //设置二维码信息
        setGroupQrcodeInfo4Heals(listClassify4WechatVOS);
        //获取头像信息
        //setUserHeader(listClassify4WechatVOS);
        //设置是否购买
        //setIsBuy(listClassify4WechatVOS, Collections.singletonList(wechatUserId));
        return listClassify4WechatVOS;
    }

    @Override
    public List<GroupQrcode4ClassifyDTO> getQrcodeByClassifyIds4Heals(List<Long> classifyIds) {
            if(ListUtils.isEmpty(classifyIds)){
                return new ArrayList<>();
            }
            List<GroupQrcode4ClassifyDTO> list=bookGroupClassifyDao.getQrcodeByClassifyIds4Heals(classifyIds);
            return list;
    }

    @Override
    public List<BookGroupClassifyDTO> getBookGroupClassifyByClassifyIds(List<Long> classifyIds) {
        if(ListUtils.isEmpty(classifyIds)){
            return new ArrayList<>();
        }
        List<BookGroupClassifyDTO> bookGroupClassifyByClassifyIds = bookGroupClassifyDao.getBookGroupClassifyByClassifyIds(classifyIds);
        return bookGroupClassifyByClassifyIds;
    }

    @Override
    public PageBeanNew<BookGroupClassifyAnalysisVO> listGroupClassify4Analysis(String name, Long proLabelId, Long depLabelId, Long purLabelId, Long firstClassify, Long secondClassify, Long gradeLabelId, Long subjectLabelId, Integer linkOnly, Integer browseQty, Integer clickQty, Integer currentPage, Integer numPerPage, String cityCode, Long thirdClassify) {
        PageParam pageParam = new PageParam(currentPage, numPerPage);
        BaseTempletClassify baseTempletClassify =new BaseTempletClassify();
        baseTempletClassify.setFirstClassify(firstClassify);
        baseTempletClassify.setSecondClassify(secondClassify);
        baseTempletClassify.setThirdClassify(thirdClassify);
        baseTempletClassify.setSubjectLabelId(subjectLabelId);
        baseTempletClassify.setGradeLabelId(gradeLabelId);
        if (null != baseTempletClassify.getFirstClassify()){
            rightsSettingBiz.setClassifyAndLabel(baseTempletClassify);
        }
        final Map<String, Object> map = Maps.newHashMap();
        map.put("name", StringUtil.isEmpty(name) ? null : name);
        map.put("proLabelId", proLabelId);
        map.put("depLabelId", depLabelId);
        map.put("purLabelId", purLabelId);
        map.put("cityCode", cityCode);
        map.put("linkOnly", linkOnly);

        map.put("firstClassify", baseTempletClassify.getFirstClassify());
        map.put("secondClassify", baseTempletClassify.getSecondClassify());
        map.put("thirdClassify", baseTempletClassify.getThirdClassify());
        map.put("gradeLabelId", baseTempletClassify.getGradeLabelId());
        map.put("subjectLabelId", baseTempletClassify.getSubjectLabelId());
        PageBeanNew<BookGroupClassifyAnalysisVO> pageBeanNew = bookGroupClassifyDao.listPageNew(pageParam, map, "listGroupClassify4Analysis");
        List<BookGroupClassifyAnalysisVO> recordList = pageBeanNew.getRecordList();
        if(CollectionUtils.isEmpty(recordList)){
            return pageBeanNew;
        }
        // 处理属性值
        for(BookGroupClassifyAnalysisVO vo : recordList){
            // 截取字符串
            String filterStr = StringUtilParent.replaceHtml(vo.getDesc());
            String subStr = filterStr.length() > 60 ? filterStr.substring(0, 60) + "..." : filterStr;
            vo.setDesc(subStr);
        }
        // 设置分类
        setLabelContent(recordList);
        // 设置标签
        setLabel(recordList);
        // 设置城市
        setCityNameByAnalysis(recordList);
        // 设置 PV/UV
        fillStatistic(recordList.stream().filter(x->x.getGroupType() == 0).collect(Collectors.toList()), browseQty, clickQty, DataTypeEnum.rays_group);
        fillStatistic(recordList.stream().filter(x->x.getGroupType() == 1).collect(Collectors.toList()), browseQty, clickQty, DataTypeEnum.third_group);
        // 填充微信文章入群链接
        // fillGroupUrl(recordList);
        return pageBeanNew;
    }

    @Override
    public Map<Long, GroupDetailDTO> getGroupMap(List<Long> groupIds, Integer groupType) {
        if (ListUtils.isEmpty(groupIds) || null == groupType) {
            return  new HashMap<>();
        }
        Map<Long, GroupDetailDTO> groupDetailDTOMap = new HashMap<>();
        Map<Long, GroupActivity4AppletDTO> appletDTOMap = new HashMap<>();
        if (ActivityGroupTypeEnum.THIRD_GROUP.value.equals(groupType)) {
            //第三方群
            appletDTOMap  = pcloudGroupActivityDao.getThirdPartByIds(groupIds);
        } else {
            //群分类
            appletDTOMap = pcloudGroupActivityDao.getGroupClassifyByIds(groupIds);
        }
        for(GroupActivity4AppletDTO groupActivity4AppletDTO: appletDTOMap.values()){
            GroupDetailDTO groupDetailDTO = new GroupDetailDTO();
            ActivityGroupDTO activityGroupDTO = new ActivityGroupDTO();
            // 填充头像
            fillGroupActivityHead(Collections.singletonList(groupActivity4AppletDTO));
            BeanUtils.copyProperties(groupActivity4AppletDTO, activityGroupDTO);
            String filterStr = StringUtilParent.replaceHtml(groupActivity4AppletDTO.getDesc());
            String subStr = filterStr.length() > 60 ? filterStr.substring(0, 60) + "..." : filterStr;
            //填充简介
            groupDetailDTO.setGroupDesc(subStr);
            groupActivity4AppletDTO.setCutDesc(subStr);
            //填充群名称
            groupDetailDTO.setGroupName(groupActivity4AppletDTO.getName());
            groupDetailDTO.setActivityGroupDTO(activityGroupDTO);
            groupDetailDTOMap.put(groupActivity4AppletDTO.getId(), groupDetailDTO);
        }
        return groupDetailDTOMap;
    }

    private void fillGroupActivityHead(List<GroupActivity4AppletDTO> groupActivity4AppletList) {
        if (!ListUtils.isEmpty(groupActivity4AppletList)) {
            for (GroupActivity4AppletDTO groupActivity4AppletDTO : groupActivity4AppletList) {
                //第三方群获取头像 end  add by Pansy
                Integer integer = 1;
                if(null != groupActivity4AppletDTO.getGroupType() && groupActivity4AppletDTO.getGroupType().intValue() == integer.intValue()){
                   rightsSettingBiz.fillThirdGroupHeadList(groupActivity4AppletDTO);
                }
                //第三方群获取头像 end

                String filterStr = StringUtilParent.replaceHtml(groupActivity4AppletDTO.getDesc());
                String subStr = filterStr.length() > 60 ? filterStr.substring(0, 60) + "..." : filterStr;
                groupActivity4AppletDTO.setCutDesc(subStr);
                // 通过群分类ID获取群二维码
                Long classifyId = groupActivity4AppletDTO.getClassifyId();
                if(classifyId != null && classifyId != 0) {
                    String groupQrCode = groupQrcodeBiz.getChangeGroupQrCode(classifyId);
                    // 通过群二维码链接反查群ID 并补充信息
                    if (!StringUtil.isEmpty(groupQrCode)){ //2020/06/30 add by pansy 第三方群为空
                        ClassifyQrcodeVO groupQrcodeInfo = groupQrcodeBiz.getGroupQrcodeInfo(groupQrCode, classifyId);
                        groupActivity4AppletDTO.setBookGroupQrcodeId(groupQrcodeInfo.getId());
                        groupActivity4AppletDTO.setGroupName(groupQrcodeInfo.getGroupName());
                        groupActivity4AppletDTO.setGroupPic(groupQrcodeInfo.getQrcodeUrl());
                        groupActivity4AppletDTO.setUserNumber(groupQrcodeInfo.getUserNumber());

                        //头像列表从缓存里取
                        List<String> headUrlList = appletGroupSearchRecordBiz
                                .getHeadUrlList(groupActivity4AppletDTO.getUserNumber(), groupActivity4AppletDTO.getBookGroupQrcodeId());

                        groupActivity4AppletDTO.setHeadUrlList(headUrlList);

                        List<AppletGroupStatementDTO> statementDTOS = appletGroupSearchRecordBiz
                                .getStatementList(groupActivity4AppletDTO.getUserNumber(), headUrlList,
                                        groupActivity4AppletDTO.getBookGroupQrcodeId());
                        groupActivity4AppletDTO.setStatementDTOList(statementDTOS);
                    }
                }
            }
        }
    }
    private void setLabelContent(List<BookGroupClassifyAnalysisVO> recordList) {
        log.info("权益设置标签具体内容");
        if (ListUtils.isEmpty(recordList)){
            return;
        }
        List<Long> firstClassifyIds = new ArrayList<>();
        List<Long> secondClassifyIds = new ArrayList<>();
        List<Long> thirdClassifyIds = new ArrayList<>();
        List<Long> classifyIds = new ArrayList<>();
        List<Long> gradeLabelIds = new ArrayList<>();
        List<Long> subjectLabelIds = new ArrayList<>();
        List<Long> labelIds = new ArrayList<>();
        for (BookGroupClassifyAnalysisVO vo : recordList) {
            firstClassifyIds.add(vo.getFirstClassify());
            secondClassifyIds.add(vo.getSecondClassify());
            thirdClassifyIds.add(vo.getThirdClassify());
            gradeLabelIds.add(vo.getGradeLabelId());
            subjectLabelIds.add(vo.getSubjectLabelId());
        }
        if (!ListUtils.isEmpty(firstClassifyIds)){
            classifyIds.addAll(firstClassifyIds);
        }
        if (!ListUtils.isEmpty(secondClassifyIds)){
            classifyIds.addAll(secondClassifyIds);
        }
        if (!ListUtils.isEmpty(thirdClassifyIds)){
            classifyIds.addAll(thirdClassifyIds);
        }
        if (!ListUtils.isEmpty(gradeLabelIds)){
            labelIds.addAll(gradeLabelIds);
        }
        if (!ListUtils.isEmpty(subjectLabelIds)){
            labelIds.addAll(subjectLabelIds);
        }
        Map<Long, AssistTempletDTO> classifyMap = new HashMap<>();
        Map<Long, BookLabel>  labelMap= new HashMap<>();
        if (!ListUtils.isEmpty(classifyIds)){
            classifyMap = assistTempletConsr.mapByIds4Classify(classifyIds);
        }
        if (!ListUtils.isEmpty(labelIds)){
            labelMap = bookLabelDao.getMapByIds(labelIds);
        }
        for (BookGroupClassifyAnalysisVO vo : recordList){
            if (!MapUtils.isEmpty(classifyMap) && classifyMap.containsKey(vo.getFirstClassify())){
                vo.setFirstClassifyName(classifyMap.get(vo.getFirstClassify()).getTempletName());
            }
            if (!MapUtils.isEmpty(classifyMap) && classifyMap.containsKey(vo.getSecondClassify())){
                vo.setSecondClassifyName(classifyMap.get(vo.getSecondClassify()).getTempletName());
            }
            if (!MapUtils.isEmpty(classifyMap) && classifyMap.containsKey(vo.getThirdClassify())){
                vo.setThirdClassifyName(classifyMap.get(vo.getThirdClassify()).getTempletName());
            }
            if (!MapUtils.isEmpty(labelMap) && labelMap.containsKey(vo.getGradeLabelId())){
                vo.setGradeLabelName(labelMap.get(vo.getGradeLabelId()).getName());
            }
            if (!MapUtils.isEmpty(labelMap) && labelMap.containsKey(vo.getSubjectLabelId())){
                vo.setSubjectLabelName(labelMap.get(vo.getSubjectLabelId()).getName());
            }
        }
    }

    private void fillGroupUrl(List<BookGroupClassifyAnalysisVO> recordList) {
        // 链接
        for (BookGroupClassifyAnalysisVO vo : recordList) {
            try {
                if(vo.getGroupType() == 0){
                    vo.setWxArticleUrl(UrlUtils.getShortUrl4Own(bookGroupBiz.getGroupNewsMaterialById(null, vo.getId(), 0, null)));
                } else if(vo.getGroupType() == 1){
                    vo.setWxArticleUrl(UrlUtils.getShortUrl4Own(bookGroupBiz.getGroupNewsMaterialById(null, null, 1, vo.getId())));
                }
            } catch (Exception e){}
        }
    }

    private void fillStatistic(List<BookGroupClassifyAnalysisVO> recordList, Integer browseQty, Integer clickQty, DataTypeEnum dataTypeEnum) {
        if (ListUtils.isEmpty(recordList)) {
            return;
        }
        if (null != browseQty && browseQty.intValue()>1){  //等于1 值查询当天数据。大于1时，从昨天开始倒推7天，所以要+1
            browseQty += 1;
        }
        if (null != clickQty && clickQty.intValue() >1){
            clickQty += 1;
        }
        List<Long> newsIds = recordList.stream().filter(s -> s != null).map(x-> x.getId()).distinct().collect(Collectors.toList());
        Map<Long, PvuvDTO> clickMap = appletLinkClickDao.mapPVUV(dataTypeEnum.code, DataRecordTypeEnum.click.code, newsIds,clickQty);
        Map<Long, PvuvDTO> browseMap = appletLinkClickDao.mapPVUV(dataTypeEnum.code, DataRecordTypeEnum.browse.code, newsIds,browseQty);
        for (BookGroupClassifyAnalysisVO vo : recordList) {
            Long newsId = vo.getId();
            if (!MapUtils.isEmpty(clickMap) && clickMap.containsKey(newsId)) {
                PvuvDTO pvuvDTO = clickMap.get(newsId);
                vo.setClickPVUV(pvuvDTO.getPv() + "/" + pvuvDTO.getUv());
            } else {
                vo.setClickPVUV("0/0");
            }
            if (!MapUtils.isEmpty(browseMap) && browseMap.containsKey(newsId)) {
                PvuvDTO pvuvDTO = browseMap.get(newsId);
                vo.setBrowsePVUV(pvuvDTO.getPv() + "/" + pvuvDTO.getUv());
            } else {
                vo.setBrowsePVUV("0/0");
            }
        }
    }

    private void setLabel(List<BookGroupClassifyAnalysisVO> recordList) {
        // 组装标签名称
        List<Long> labelId = Lists.newArrayList();
        for (BookGroupClassifyAnalysisVO responseVO : recordList) {
            labelId.add(responseVO.getProLabelId());
            labelId.add(responseVO.getPurLabelId());
            labelId.add(responseVO.getDepLabelId());
        }
        Map<Long, String> labelName = labelConsr.getLabelName(labelId);
        for (BookGroupClassifyAnalysisVO responseVO : recordList) {
            responseVO.setPurLabelName(labelName.get(responseVO.getPurLabelId()));
            responseVO.setProLabelName(labelName.get(responseVO.getProLabelId()));
            responseVO.setDepLabelName(labelName.get(responseVO.getDepLabelId()));
        }
    }

    private void setCityNameByAnalysis(List<BookGroupClassifyAnalysisVO> recordList) {
        log.info("设置城市名称");
        if (ListUtils.isEmpty(recordList)){
            return;
        }
        List<String> cityCodes = recordList.stream().map(e -> e.getCityCode()).distinct().collect(Collectors.toList());
        if (ListUtils.isEmpty(cityCodes)) {
            return;
        }
        Map<String, RegionMap> regionMapMap = bookBrowseRecordBiz.getCitysByCodes(cityCodes);
        if (MapUtils.isNotEmpty(regionMapMap)){
            recordList.forEach(classifyVO -> {
                RegionMap regionMap = regionMapMap.get(classifyVO.getCityCode());
                if (regionMapMap.containsKey(classifyVO.getCityCode()) && null != regionMap){
                    classifyVO.setCityName(regionMap.getRegionName());
                }
            });
        }
    }
}
