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

import com.google.common.collect.Lists;

import com.pcloud.appcenter.assist.dto.AssistTempletDTO;
import com.pcloud.book.applet.biz.AppletUserBookcaseBiz;
import com.pcloud.book.applet.contants.AppletConstants;
import com.pcloud.book.applet.dao.AppletUserBookcaseDao;
import com.pcloud.book.applet.dto.AppletTaskDTO;
import com.pcloud.book.applet.dto.AppletUserBookcaseDTO;
import com.pcloud.book.applet.dto.BaseTempletClassifyDTO;
import com.pcloud.book.applet.dto.BookResourceExcelDTO;
import com.pcloud.book.applet.dto.UserLastBookReDTO;
import com.pcloud.book.applet.entity.AppletUserBookcase;
import com.pcloud.book.applet.entity.AppletUserClickRecord;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.biz.BookAdviserBiz;
import com.pcloud.book.book.biz.BookBiz;
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.dao.BookRaysClassifyDao;
import com.pcloud.book.book.dto.BookAdviserDto;
import com.pcloud.book.book.dto.BookDto;
import com.pcloud.book.book.entity.BookLabel;
import com.pcloud.book.book.entity.BookRaysClassify;
import com.pcloud.book.consumer.app.AssistTempletConsr;
import com.pcloud.book.consumer.common.ExportConsr;
import com.pcloud.book.consumer.reader.ReaderConsr;
import com.pcloud.book.consumer.user.AdviserConsr;
import com.pcloud.book.copyright.tools.ExcelUtil;
import com.pcloud.book.es.biz.ESBookAndAdviserBiz;
import com.pcloud.book.group.biz.BookGroupBiz;
import com.pcloud.book.group.biz.ResourcePageBiz;
import com.pcloud.book.group.dto.BookServeDTO;
import com.pcloud.book.group.enums.JoinGroupTypeEnum;
import com.pcloud.book.rightsSetting.biz.RightsSettingBiz;
import com.pcloud.book.rightsSetting.dao.RightsSettingDAO;
import com.pcloud.book.rightsSetting.dto.RightsSettingDto;
import com.pcloud.book.rightsSetting.entity.RightsReadType;
import com.pcloud.book.rightsSetting.entity.RightsSetting;
import com.pcloud.book.util.common.ThreadPoolUtils;
import com.pcloud.book.util.properties.BookProps;
import com.pcloud.channelcenter.base.exceptions.ChannelBizException;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.exceptions.BizException;
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.cache.redis.JedisClusterUtils;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.readercenter.rmall.constants.RmallContants;
import com.pcloud.readercenter.rmall.entity.RmallBookMoneyRecord;
import com.pcloud.readercenter.rmall.enums.MoneyReceiveTypeEnum;
import com.pcloud.readercenter.rmall.service.RmallBookMoneyRecordService;
import com.pcloud.readercenter.userlabel.dto.UserGradeLabelIdDTO;
import com.pcloud.usercenter.party.adviser.dto.AdviserBaseInfoDto;

import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Random;
import java.util.stream.Collectors;

import lombok.extern.slf4j.Slf4j;

import static com.pcloud.book.util.common.ThreadPoolUtils.RMALL_SIGN_IN;

/**
 * 小程序用户书架
 */
@Component
@Slf4j
public class AppletUserBookcaseBizImpl implements AppletUserBookcaseBiz {


    @Autowired
    private AppletUserBookcaseDao appletUserBookcaseDao;
    @Autowired
    private AssistTempletConsr assistTempletConsr;
    @Autowired
    private BookGroupBiz bookGroupBiz;
    @Autowired
    private BookRaysClassifyDao bookRaysClassifyDao;
    @Autowired
    private RightsSettingBiz rightsSettingBiz;
    @Autowired
    private ESBookAndAdviserBiz esBookAndAdviserBiz;
    @Autowired
    private RightsSettingDAO rightsSettingDAO;
    @Autowired
    private BookAdviserBiz bookAdviserBiz;
    @Autowired
    private ExportConsr exportConsr;
    @Autowired
    private BookBiz bookBiz;
    @Autowired
    private AdviserConsr adviserConsr;
    @Autowired
    private BookDao bookDao;
    @Autowired
    private RmallBookMoneyRecordService rmallBookMoneyRecordService;
    @Autowired
    private BookLabelDao bookLabelDao;
    @Autowired
    private ReaderConsr readerConsr;
    @Autowired
    private ResourcePageBiz resourcePageBiz;

    @Override
    @ParamLog("小程序用户添加书架")
    public AppletTaskDTO addUserBook(AppletUserBookcase appletUserBookcase) {
        AppletTaskDTO appletTaskDTO = new AppletTaskDTO();
        Integer isFinish = 0;
        Long wechatUserId = appletUserBookcase.getWechatUserId();
        if (BookConstant.visitorWechatUserId.equals(wechatUserId)) {
            return appletTaskDTO;
        }
        if (null != appletUserBookcase.getBookId() &&
                (null == appletUserBookcase.getChannelId() || null == appletUserBookcase.getAdviserId())) {
            return appletTaskDTO;
        }
        //小程序和H5公众号用户id
        List<Long> wechatUserIdList = readerConsr.getRelateUserIdList(wechatUserId, appletUserBookcase.getOfficialAccountsId());
        //查询这本书书架中有没有
        AppletUserBookcase userBook = appletUserBookcaseDao.getUserReadType(wechatUserIdList, appletUserBookcase.getBookId(), appletUserBookcase.getAdviserId(), appletUserBookcase.getChannelId());
        //小程序领取书币任务埋点
        if (null == userBook && appletUserBookcase.getOfficialAccountsId().equals(BookProps.getMiniOfficialAccountsId())) {
            Integer taskCount = readerConsr.getTaskCount(wechatUserId, MoneyReceiveTypeEnum.NEW_BOOK.key);
            Integer subtractTaskCount = RmallContants.NEW_BOOK_MONEY_TIMES - 1;
            if  (null != taskCount &&  subtractTaskCount.equals(taskCount)) {
                isFinish = 1;
            }
            RMALL_SIGN_IN.execute(()->{
                RmallBookMoneyRecord rmallBookMoneyRecord = new RmallBookMoneyRecord();
                rmallBookMoneyRecord.setWechatUserId(wechatUserId);
                rmallBookMoneyRecord.setRecordType(MoneyReceiveTypeEnum.NEW_BOOK.key);
                rmallBookMoneyRecordService.insert(rmallBookMoneyRecord);
            });
        }
        //保存书刊
        if (null == userBook) {
            appletUserBookcaseDao.insert(appletUserBookcase);
        } else {
            appletUserBookcaseDao.insert(userBook);
        }
        appletTaskDTO.setIsFinishTask(isFinish);
        //清除缓存
        delBookcaseRedis(wechatUserId, appletUserBookcase.getOfficialAccountsId());
        //更新用户年级标签
        updateUserGradeLabel(appletUserBookcase);
        return appletTaskDTO;
    }

    private void updateUserGradeLabel(AppletUserBookcase appletUserBookcase) {
        //用户没有标签，更新用户年级标签
        UserGradeLabelIdDTO labelIdDTO = readerConsr.getUserGrade(appletUserBookcase.getWechatUserId(), appletUserBookcase.getOfficialAccountsId());
        if (null != labelIdDTO && null != labelIdDTO.getLabelId()) {
            return;
        }
        BookAdviserDto bookAdviserDto = bookAdviserBiz.getBase(appletUserBookcase.getBookId(), appletUserBookcase.getChannelId(), appletUserBookcase.getAdviserId());
        if (null == bookAdviserDto) {
            return;
        }
        Long gradeId = null;
        if (null != bookAdviserDto.getGraLabelId()) {
            gradeId = resourcePageBiz.getGradeByGradeLabelId(bookAdviserDto.getGraLabelId());
        }
        if (null != bookAdviserDto.getDepLabelId()) {
            gradeId = resourcePageBiz.getGradeByDepLabelId(bookAdviserDto.getDepLabelId());
        }
        //匹配不到，取已工作年龄段
        gradeId = null == gradeId ? 29L : gradeId;
        readerConsr.addUserGradeLabel(appletUserBookcase.getWechatUserId(), appletUserBookcase.getOfficialAccountsId(), gradeId);
        //更新用户书籍标签
        if (null != bookAdviserDto.getTempletId()) {
            try {
                //更新用户年级标签
                readerConsr.updateUserClassify(appletUserBookcase.getWechatUserId(), bookAdviserDto.getTempletId(), bookAdviserDto.getSecondTempletId(), bookAdviserDto.getThirdTempletId());
            } catch (Exception e) {
                log.error("用户添加书籍时更新动态updateUserGradeLabel失败", e.getMessage());
            }
        }
    }

    private void delBookcaseRedis(Long wechatUserId, Long officialAccountsId) {
        List<Long> wechatUserIdList = readerConsr.getRelateUserIdList(wechatUserId, officialAccountsId);
        for (Long userId : wechatUserIdList) {
            JedisClusterUtils.del(AppletConstants.USER_BOOK_CASE + userId);
            JedisClusterUtils.del(AppletConstants.USER_BOOK_CASE_COUNT + userId);
        }
    }

    @Override
    public PageBeanNew<AppletUserBookcaseDTO> listByWechatUserId(Long wechatUserId, Integer currentPage, Integer numPerPage,
                                                                 Long officialAccountsId) {

        List<Long> wechatUserIdList = readerConsr.getRelateUserIdList(wechatUserId, officialAccountsId);
        //缓存中查
        String key = AppletConstants.USER_BOOK_CASE + wechatUserId;
        String field = currentPage + "-" + numPerPage;
        String countKey = AppletConstants.USER_BOOK_CASE_COUNT + wechatUserId;
        List<AppletUserBookcaseDTO> bookcaseDTOS = JedisClusterUtils.hgetJson2List(key, field, AppletUserBookcaseDTO.class);
        Integer count = 0;
        String countStr = JedisClusterUtils.get(countKey);
        if (!StringUtil.isEmpty(countStr)) {
            count = Integer.valueOf(countStr);
        }
        if (!ListUtils.isEmpty(bookcaseDTOS) && count > 0) {
            return new PageBeanNew<>(currentPage, numPerPage, count, bookcaseDTOS);
        }
        //数据库查询
        Map<String, Object> map = new HashMap<>();
        map.put("wechatUserIdList", wechatUserIdList);
        PageBeanNew<AppletUserBookcaseDTO> pageBeanNew = appletUserBookcaseDao.listPageNew(
                new PageParam(currentPage, numPerPage), map, "listByWechatUserId");
        if (ListUtils.isEmpty(pageBeanNew.getRecordList())) {
            return new PageBeanNew<>(currentPage, numPerPage, pageBeanNew.getTotalCount(), new ArrayList<>());
        }
        //fillTempletName(pageBeanNew.getRecordList());
        fillLabelNames(pageBeanNew.getRecordList());
        //fillRightsSettingAndResourceCount(pageBeanNew.getRecordList());
        JedisClusterUtils.hset2Json(key, field, pageBeanNew.getRecordList());
        JedisClusterUtils.set(countKey, String.valueOf(pageBeanNew.getTotalCount()));
        JedisClusterUtils.expire(key, 60);
        JedisClusterUtils.expire(countKey, 60);
        return pageBeanNew;
    }

    private void fillLabelNames(List<AppletUserBookcaseDTO> recordList) {
        if (ListUtils.isEmpty(recordList)) {
            return;
        }
        List<Long> bookLabelIds = new ArrayList<>();
        recordList.stream().forEach(appletUserBookcaseDTO -> {

            if (null != appletUserBookcaseDTO.getGradeLabelId()) {
                bookLabelIds.add(appletUserBookcaseDTO.getGradeLabelId());
            }
            if (null != appletUserBookcaseDTO.getSubjectLabelId()) {
                bookLabelIds.add(appletUserBookcaseDTO.getSubjectLabelId());
            }
            if (null != appletUserBookcaseDTO.getVolLabelId()) {
                bookLabelIds.add(appletUserBookcaseDTO.getVolLabelId());
            }
            if (null != appletUserBookcaseDTO.getVerLabelId()){
                bookLabelIds.add(appletUserBookcaseDTO.getVerLabelId());
            }
            if (null != appletUserBookcaseDTO.getAreaLabelId()) {
                bookLabelIds.add(appletUserBookcaseDTO.getAreaLabelId());
            }
        });
        Map<Long, BookLabel> bookLabelMap = new HashMap<>();

        if (!ListUtils.isEmpty(bookLabelIds)) {
            bookLabelMap = bookLabelDao.getMapByIds(bookLabelIds);
        }

        for (AppletUserBookcaseDTO appletUserBookcaseDTO : recordList) {
            if (!MapUtils.isEmpty(bookLabelMap) && bookLabelMap.containsKey(appletUserBookcaseDTO.getGradeLabelId())) {
                appletUserBookcaseDTO.setGraLabelName(bookLabelMap.get(appletUserBookcaseDTO.getGradeLabelId()).getName());
            }
            if (!MapUtils.isEmpty(bookLabelMap) && bookLabelMap.containsKey(appletUserBookcaseDTO.getSubjectLabelId())) {
                appletUserBookcaseDTO.setSubLabelName(bookLabelMap.get(appletUserBookcaseDTO.getSubjectLabelId()).getName());
            }
            if (!MapUtils.isEmpty(bookLabelMap) && bookLabelMap.containsKey(appletUserBookcaseDTO.getVolLabelId())) {
                appletUserBookcaseDTO.setVolLabelName(bookLabelMap.get(appletUserBookcaseDTO.getVolLabelId()).getName());
            }
            if (!MapUtils.isEmpty(bookLabelMap) && bookLabelMap.containsKey(appletUserBookcaseDTO.getVerLabelId())) {
                appletUserBookcaseDTO.setVerLabelName(bookLabelMap.get(appletUserBookcaseDTO.getVerLabelId()).getName());
            }
            if (!MapUtils.isEmpty(bookLabelMap) && bookLabelMap.containsKey(appletUserBookcaseDTO.getAreaLabelId())) {
                appletUserBookcaseDTO.setAreaLabelName(bookLabelMap.get(appletUserBookcaseDTO.getAreaLabelId()).getName());
            }
        }

    }

    private void fillRightsSettingAndResourceCount(List<AppletUserBookcaseDTO> recordList) {
        if (ListUtils.isEmpty(recordList)) {
            return;
        }
        for (AppletUserBookcaseDTO bookcaseDTO : recordList) {
            //权益
            if (JoinGroupTypeEnum.XIAORUI.getCode().equals(bookcaseDTO.getJoinGroupType()) && null == bookcaseDTO.getRightsSettingId()) {
                RightsSettingDto rightsSettingDto = rightsSettingBiz.getRightsSettingByBookId4AppletHome(bookcaseDTO.getBookId(), bookcaseDTO.getAdviserId(), bookcaseDTO.getChannelId());
                if (null == rightsSettingDto) {
                    continue;
                }
                bookcaseDTO.setRightsSettingId(rightsSettingDto.getId());
                bookcaseDTO.setRightsSettingCount(rightsSettingDto.getCount());
                ThreadPoolUtils.OTHER_THREAD_POOL.execute(() -> {
                    appletUserBookcaseDao.updateRightsSettingId(rightsSettingDto.getId(), bookcaseDTO.getBookId(), bookcaseDTO.getAdviserId(), bookcaseDTO.getChannelId());
                });
            }
            //资源数量
            List<BookServeDTO> serveDTOList = bookGroupBiz.getBookAndBookGroupServeIds(bookcaseDTO.getAdviserId(), bookcaseDTO.getBookId(), bookcaseDTO.getChannelId());
            bookGroupBiz.removeCanNotBuy(serveDTOList);
            bookcaseDTO.setResourceCount(serveDTOList.size());
        }
    }

    @Override
    public void addUserClickRecord(AppletUserClickRecord appletUserClickRecord) {
        appletUserBookcaseDao.insertClickRecord(appletUserClickRecord);
    }

    @Override
    public Map<String, Object> getUserClickStatistic(Long wechatUserId, Long bookId, Long channelId, Long adviserId) {
        //社群书和现代纸书下资源
        List<BookServeDTO> serveDTOList = bookGroupBiz.getBookAndBookGroupServeIds(adviserId, bookId, channelId);
        if (ListUtils.isEmpty(serveDTOList)) {
            return new HashMap<>();
        }
        Integer clickCount = 0;
        String startDate = DateUtils.formatDate(new Date(), DateUtils.DATE_FORMAT_DATEONLY);
        List<Long> appIds = serveDTOList.stream().filter(s -> s.getServeType().equalsIgnoreCase("APP")).
                map(BookServeDTO::getServeId).distinct().collect(Collectors.toList());
        List<Long> productIds = serveDTOList.stream().filter(s -> s.getServeType().equalsIgnoreCase("PRODUCT")).
                map(BookServeDTO::getServeId).distinct().collect(Collectors.toList());
        if (!ListUtils.isEmpty(appIds)) {
            Integer appCount = appletUserBookcaseDao.getUserClickServerCount(wechatUserId, bookId, channelId, adviserId, appIds, "APP");
            if (appCount > 0) {
                clickCount = clickCount + appCount;
                startDate = appletUserBookcaseDao.getMinClickTime(wechatUserId, bookId, channelId, adviserId, appIds, "APP");
            }
        }
        if (!ListUtils.isEmpty(productIds)) {
            Integer productCount = appletUserBookcaseDao.getUserClickServerCount(wechatUserId, bookId, channelId, adviserId, productIds, "PRODUCT");
            if (productCount > 0) {
                clickCount = clickCount + productCount;
                String dateStr = appletUserBookcaseDao.getMinClickTime(wechatUserId, bookId, channelId, adviserId, productIds, "PRODUCT");
                if (!StringUtil.isEmpty(dateStr) && DateUtils.getDateByStr(dateStr).before(DateUtils.getDateByStr(startDate))) {
                    startDate = dateStr;
                }
            }
        }
        Map<String, Object> map = new HashMap<>();
        map.put("startDate", startDate);
        map.put("clickCount", clickCount);
        return map;
    }

    private void fillTempletName(List<AppletUserBookcaseDTO> recordList) {
        List<Long> templetIds = new ArrayList<>();
        recordList.forEach(dto -> {
            if (Objects.nonNull(dto.getTempletId())) {
                templetIds.add(dto.getTempletId());
            }
            if (Objects.nonNull(dto.getSecondTempletId())) {
                templetIds.add(dto.getSecondTempletId());
            }
            if (Objects.nonNull(dto.getThirdTempletId())) {
                templetIds.add(dto.getThirdTempletId());
            }
        });
        List<Long> classifyTempletIds = recordList.stream().filter(s -> s.getJoinGroupType() != null && JoinGroupTypeEnum.XIAORUI.getCode().equals(s.getJoinGroupType())).map(s -> s.getTempletId()).distinct().collect(Collectors.toList());
        Map<Integer, Integer> classifyMap = new HashMap<>();
        if (!ListUtils.isEmpty(classifyTempletIds)) {
            List<BookRaysClassify> listByIds = bookRaysClassifyDao.getClassifyListByIds(classifyTempletIds);
            if (!ListUtils.isEmpty(listByIds)) {
                classifyMap = listByIds.stream().collect(Collectors.toMap(a -> a.getBookTemplateId(), a -> a.getRaysClassifyId(), (k1, k2) -> k2));
            }
        }
        Map<Long, AssistTempletDTO> assistTempletDTOMap = assistTempletConsr.mapByIds4Classify(templetIds);
        for (AppletUserBookcaseDTO bookcaseDTO : recordList) {
            Long secondTempletId = bookcaseDTO.getSecondTempletId();
            Long templetId = bookcaseDTO.getTempletId();
            Long thirdTempletId = bookcaseDTO.getThirdTempletId();
            if (secondTempletId != null && assistTempletDTOMap != null) {
                AssistTempletDTO templetDTO = assistTempletDTOMap.get(secondTempletId);
                bookcaseDTO.setSecondTempletName(Optional.ofNullable(templetDTO).map(AssistTempletDTO::getTempletName).orElse(null));
            }
            if (templetId != null && assistTempletDTOMap != null) {
                AssistTempletDTO templetDTO = assistTempletDTOMap.get(templetId);
                bookcaseDTO.setTempletName(Optional.ofNullable(templetDTO).map(AssistTempletDTO::getTempletName).orElse(null));
            }
            if (thirdTempletId != null && assistTempletDTOMap != null) {
                AssistTempletDTO templetDTO = assistTempletDTOMap.get(thirdTempletId);
                bookcaseDTO.setThirdTempletName(Optional.ofNullable(templetDTO).map(AssistTempletDTO::getTempletName).orElse(null));
            }
            if (!MapUtils.isEmpty(classifyMap) && null != bookcaseDTO.getTempletId() && classifyMap.containsKey(bookcaseDTO.getTempletId().intValue())) {
                bookcaseDTO.setClassifyId(classifyMap.get(bookcaseDTO.getTempletId().intValue()));
            }
        }
    }


    @ParamLog("获取用户最后一次点击的书")
    @Override
    public UserLastBookReDTO getUserLastBookRe(Long wechatUserId, Long officialAccountsId) {
        if (wechatUserId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        List<Long> wechatUserIdList = readerConsr.getRelateUserIdList(wechatUserId, officialAccountsId);
        UserLastBookReDTO lastBookRe;
        //查询最后开启小睿的一本书或者馆配书
        Long bookId = null;
        Long adviserId = null;
        if ("pro".equals(BookProps.getSystemEnv())) {
            adviserId = 1000027204L;
        } else if ("uat".equalsIgnoreCase(BookProps.getSystemEnv())) {
            bookId = 1398300L;
        } else if ("test".equalsIgnoreCase(BookProps.getSystemEnv())) {
            bookId = 5210703L;
        }
        lastBookRe = appletUserBookcaseDao.getUserLastRe(wechatUserIdList, adviserId, bookId);
        if (Objects.nonNull(lastBookRe)) {
            lastBookRe.setHasBook(true);
            //判断是否是馆配图书
            lastBookRe.setIsLibraryBook(bookBiz.checkIsLibraryBook(lastBookRe.getAdviserId(), lastBookRe.getBookId()) ? 1 : 0);
        } else {
            lastBookRe = new UserLastBookReDTO();
            lastBookRe.setHasBook(false);
        }
        return lastBookRe;
    }

    @Override
    public void deleteByIds(List<Long> ids, Long wechatUserId, Long officialAccountsId) {
        if (ListUtils.isEmpty(ids)) {
            return;
        }
        appletUserBookcaseDao.deleteByIds(ids);
        delBookcaseRedis(wechatUserId, officialAccountsId);
        ThreadPoolUtils.OTHER_THREAD_POOL.execute(()->{
            esBookAndAdviserBiz.updateBookAndAdviserToES(appletUserBookcaseDao.getBookIdsByIds(ids));
        });
    }

    @Override
    @ParamLog("更新读者关于本书的阅读方式")
    public void updateUserReadType(AppletUserBookcase appletUserBookcase) {
        appletUserBookcaseDao.updateUserReadType(appletUserBookcase);
    }

    @Override
    @ParamLog("获取用户当前本书的阅读方式")
    public AppletUserBookcase getUserReadType(Long wechatUserId, Long bookId, Long adviserId, Long channelId) {
        AppletUserBookcase appletUserBookcase = appletUserBookcaseDao.getUserReadType(Arrays.asList(wechatUserId), bookId, adviserId, channelId);
        return appletUserBookcase;
    }

    @Override
    public void randomChangeBook(Long wechatUserId) {
        Long officialAccountsId = BookProps.getMiniOfficialAccountsId();
        List<AppletUserBookcase> bookcaseList = appletUserBookcaseDao.getListByUserId(wechatUserId);
        //无书或只有3本不处理
        if (ListUtils.isEmpty(bookcaseList) || bookcaseList.size() < BookConstant.HOME_BOOK_PAGE) {
            return;
        }
        Integer removeCount = bookcaseList.size() - BookConstant.HOME_BOOK_PAGE;
        removeCount = removeCount >= BookConstant.HOME_BOOK_PAGE ? BookConstant.HOME_BOOK_PAGE : removeCount;
        //去除最近3本书
        for (int i = 0; i < removeCount; i++) {
            bookcaseList.remove(0);
        }

        //随机取一本书埋点
        if (bookcaseList.size() > BookConstant.HOME_BOOK_PAGE) {
            bookcaseList = getRandomList(bookcaseList, BookConstant.HOME_BOOK_PAGE);
        }
        bookcaseList.stream().forEach(e -> e.setBookGroupId(null == e.getBookGroupId() ? 0L :  e.getBookGroupId()));
        //升序排序
        bookcaseList = bookcaseList.stream().sorted(Comparator.comparing(AppletUserBookcase::getBookGroupId)).collect(Collectors.toList());
        addUserBooks(bookcaseList, wechatUserId, officialAccountsId);
        ThreadPoolUtils.OTHER_THREAD_POOL.execute(() -> {
            this.listByWechatUserId(wechatUserId, 0, BookConstant.HOME_BOOK_PAGE, officialAccountsId);
        });
    }

    private void addUserBooks(List<AppletUserBookcase> bookcaseList, Long wechatUserId, Long officialAccountsId) {
        if (ListUtils.isEmpty(bookcaseList)) {
            return;
        }
        bookcaseList.stream().forEach(appletUserBookcase -> {
            appletUserBookcase.setOfficialAccountsId(officialAccountsId);
            if (null == appletUserBookcase.getRightsSettingId()) {//书刊对应的权益
                RightsSettingDto rightsSettingDto = rightsSettingBiz.getReadType4Book(wechatUserId, appletUserBookcase.getBookId(), appletUserBookcase.getChannelId(), appletUserBookcase.getAdviserId());
                appletUserBookcase.setRightsSettingId(rightsSettingDto == null ? null : rightsSettingDto.getId());
                if (null == appletUserBookcase.getReadType()) {//取书刊第一种阅读方式
                    if (null != rightsSettingDto && !ListUtils.isEmpty(rightsSettingDto.getRightsReadTypes())) {
                        for (RightsReadType rightsReadType : rightsSettingDto.getRightsReadTypes()) {
                            if (null != rightsReadType && null != rightsReadType.getRightsCount() && rightsReadType.getRightsCount() > 0) {
                                appletUserBookcase.setReadType(rightsReadType.getReadType());
                                break;
                            }
                        }
                    }
                }
            }
        });
        //数据库去重
        appletUserBookcaseDao.insert(bookcaseList);
        delBookcaseRedis(wechatUserId, officialAccountsId);
        List<Long> bookIds = bookcaseList.stream().map(e -> e.getBookId()).collect(Collectors.toList());
        if (!ListUtils.isEmpty(bookIds)) {
            esBookAndAdviserBiz.updateBookAndAdviserToES(bookIds);
        }
    }

    private List<AppletUserBookcase> getRandomList(List<AppletUserBookcase> paramList, int count) {
        if (paramList.size() < count) {
            return paramList;
        }
        Random random = new Random();
        List<Integer> tempList = new ArrayList<Integer>();
        List<AppletUserBookcase> newList = new ArrayList<AppletUserBookcase>();
        int temp = 0;
        for (int i = 0; i < count; i++) {
            temp = random.nextInt(paramList.size());//将产生的随机数作为被抽list的索引
            if (!tempList.contains(temp)) {
                tempList.add(temp);
                newList.add(paramList.get(temp));
            } else {
                i--;
            }
        }
        return newList;
    }

    @Override
    public List<Long> getBookcaseIdListByUser(Long wechatUserId, Long officialAccountsId) {
        List<Long> wechatUserIdList = readerConsr.getRelateUserIdList(wechatUserId, officialAccountsId);
        return appletUserBookcaseDao.getBookcaseIdListByUser(wechatUserIdList);
    }

    @Override
    public Map<String, Integer> mapBookUserCountList(List<Long> bookIds) {
        List<AppletUserBookcaseDTO> list = appletUserBookcaseDao.getBookUserCountList(bookIds);
        if (ListUtils.isEmpty(list)) {
            return new HashMap<>();
        }
        Map<String, Integer> map = new HashMap<>();
        for (AppletUserBookcaseDTO bookcaseDTO : list) {
            String key = bookcaseDTO.getBookId() + "-" + bookcaseDTO.getAdviserId() + "-" + bookcaseDTO.getChannelId();
            map.put(key, bookcaseDTO.getBookUserCount());
        }
        return map;
    }

    @Override
    public AppletUserBookcaseDTO getUserBookInfoByWechatUserId(Long bookId, Long channelId, Long adviserId,Long rightsSettingId) {
        AppletUserBookcaseDTO userBookInfoByWechatUserId = appletUserBookcaseDao.getUserBookInfoByWechatUserId(bookId,channelId,adviserId);

        if (userBookInfoByWechatUserId == null){
            return new AppletUserBookcaseDTO();
        }
        if(StringUtil.isEmpty(userBookInfoByWechatUserId.getPublish()) && null != adviserId) {
            Map<Long, AdviserBaseInfoDto> adviserId2AdviserInfoDtoMap = adviserConsr.getAdviserId2AdviserInfoDtoMap(Lists.newArrayList(adviserId));
            if (MapUtils.isNotEmpty(adviserId2AdviserInfoDtoMap) && null != adviserId2AdviserInfoDtoMap.get(adviserId)) {
                userBookInfoByWechatUserId.setAgentName(adviserId2AdviserInfoDtoMap.get(adviserId).getAgentName());
            }
        }
        List<AppletUserBookcaseDTO> appletUserBookcaseDTOS = Collections.singletonList(userBookInfoByWechatUserId);
        fillTempletName(appletUserBookcaseDTOS);
        fillRightsSettingAndResourceCount(appletUserBookcaseDTOS);

        fillReadGuide(appletUserBookcaseDTOS.get(0),rightsSettingId);
        fillLabelNames(appletUserBookcaseDTOS);
        return appletUserBookcaseDTOS.get(0);
    }

    @Override
    public String getResources4Books(MultipartHttpServletRequest request) {
        String excelUrl = null;
        List<BookResourceExcelDTO> bookResourceDTOList4BookExcel =   getBookResourceList(request);
        if (ListUtils.isEmpty(bookResourceDTOList4BookExcel)) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL,"bookResourceDTOList4Book");
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
        List<BookResourceExcelDTO> bookResourceDTOList4ResourceExcel = new ArrayList<>(1000);
        bookResourceDTOList4BookExcel.forEach(e -> {
            Long bookId = e.getBookId();
            if (null == bookId) {
                return;
            }
            Integer isRui = getIsRui(e.getAdviserId(), e.getBookId(), e.getChannelId());
            List<BookServeDTO> serveDTOList = bookGroupBiz.getBookAndBookGroupServeIds4Price(
                    e.getAdviserId(), e.getBookId(), e.getChannelId());
            if (ListUtils.isEmpty(serveDTOList)) {
                return;
            }
            serveDTOList.forEach(m -> {
                BookResourceExcelDTO bookResourceExcelDTO = new BookResourceExcelDTO();
                bookResourceExcelDTO.setBookId(e.getBookId());
                bookResourceExcelDTO.setAdviserId(e.getAdviserId());
                bookResourceExcelDTO.setChannelId(e.getChannelId());
                bookResourceExcelDTO.setBookName(e.getBookName());
                bookResourceExcelDTO.setUrl(e.getUrl());
                bookResourceExcelDTO.setResourceId(m.getServeId());
                bookResourceExcelDTO.setResourceName(m.getServeName());
                bookResourceExcelDTO.setResourceType(m.getServeType());
                bookResourceExcelDTO.setFromType(m.getFromType());
                bookResourceExcelDTO.setFromTypeName(m.getFromTypeName());
                bookResourceExcelDTO.setPrice(m.getPrice());
                bookResourceExcelDTO.setIsRui(isRui);
                bookResourceDTOList4ResourceExcel.add(bookResourceExcelDTO);
            });
        });
        String fileName ="书籍相关资源-研发-" + simpleDateFormat.format(new Date());
        excelUrl =  getExcelUrl4Resource(bookResourceDTOList4ResourceExcel, fileName);
        return excelUrl;
    }

    @Override
    public BaseTempletClassifyDTO getLastReadBookInfo(List<Long> wechatUserIds) {
        return appletUserBookcaseDao.getLastReadBookInfoByUsers(wechatUserIds);
    }

    @Override
    public List<Long> getSameClassifyUserIds(List<Long> wechatUserIds) {
        if (ListUtils.isEmpty(wechatUserIds)) {
            return new ArrayList<>();
        }
        BaseTempletClassifyDTO baseTempletClassifyDTO = appletUserBookcaseDao.getLastReadBookInfoByUsers(wechatUserIds);
        if (null == baseTempletClassifyDTO || null == baseTempletClassifyDTO.getFirstClassify()) {
            return new ArrayList<>();
        }
        List<Long> wechatUserId = appletUserBookcaseDao.getSameClassifyUserIds(baseTempletClassifyDTO);
        return wechatUserId;
    }

    private String getExcelUrl4Resource(List<BookResourceExcelDTO> bookResourceDTOList4ResourceExcel, String fileName) {
        // 字段名
        String[] rowsName = {"书籍id", "编辑id", "渠道id", "书籍名称", "书籍二维码","资源id", "资源名称", "资源类型", "资源具体类型", "资源类型名称", "资源价格", "是否小睿书"};
        List<Object[]> dataList = new ArrayList<>();
        Object[] objs;
        for (int i = 0; i < bookResourceDTOList4ResourceExcel.size(); i++) {
            BookResourceExcelDTO bookResourceExcelDTO = bookResourceDTOList4ResourceExcel.get(i);
            objs = new Object[rowsName.length];
            objs[0] = bookResourceExcelDTO.getBookId();
            objs[1] = bookResourceExcelDTO.getAdviserId();
            objs[2] = bookResourceExcelDTO.getChannelId();
            objs[3] = bookResourceExcelDTO.getBookName();
            objs[4] = bookResourceExcelDTO.getUrl();
            objs[5] = bookResourceExcelDTO.getResourceId();
            objs[6] = bookResourceExcelDTO.getResourceName();
            objs[7] = bookResourceExcelDTO.getResourceType();
            objs[8] = bookResourceExcelDTO.getFromType();
            objs[9] = bookResourceExcelDTO.getFromTypeName();
            objs[10] = bookResourceExcelDTO.getPrice();
            objs[11] = bookResourceExcelDTO.getIsRui();
            dataList.add(objs);
        }
        String fileUrl = exportConsr.exportExcel(fileName, rowsName, dataList);
        return fileUrl;
    }

    private Integer getIsRui(Long adviserId, Long bookId, Long channelId) {
        return  bookAdviserBiz.getIsRui(adviserId, bookId, channelId);
    }

    private List<BookResourceExcelDTO> getBookResourceList(MultipartHttpServletRequest request) {
        List<BookResourceExcelDTO> bookResourceExcelDTOList = new ArrayList<>();
        List<MultipartFile> files = request.getFiles("file");
        if (files == null || files.size() == 0) {
            throw new ChannelBizException(ChannelBizException.BOOK_ID_IS_NULL, "未发现上传内容，请检查！");
        }
        MultipartFile multipartFile = files.get(0);
        String suffix = getfileSuffix(multipartFile);
        String fileName = multipartFile.getOriginalFilename();

        File temp = null;
        try {
            temp = File.createTempFile("temp", suffix);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            multipartFile.transferTo(temp);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String[][] data;
        try {

            data = ExcelUtil.getData(temp, 1);
        } catch (BizException e) {
            log.warn("导入出错" + e, e.getMessage());
            throw new ChannelBizException(e.getCode(), e.getMsg());
        } catch (Exception e) {
            log.warn("导入出错" + e, e.getMessage());
            throw new ChannelBizException(BookBizException.PARAM_IS_NULL, "错误的文件或者未按模板格式导入！");
        }
        int num = 0;
        for (int i = 0; i < data.length; i++) {
            BookResourceExcelDTO bookResourceExcelDTO = new BookResourceExcelDTO();
            num = i + 2;
            bookResourceExcelDTO.setRowNo(Long.valueOf(num));
            bookResourceExcelDTO.setBookId(StringUtil.isEmpty(data[i][1]) ? null : Long.valueOf(data[i][1]));
            bookResourceExcelDTO.setBookName(StringUtil.isEmpty(data[i][2]) ? "" : data[i][2]);
            bookResourceExcelDTO.setAdviserId(StringUtil.isEmpty(data[i][3]) ? null :  Long.valueOf(data[i][3]));
            bookResourceExcelDTO.setChannelId(StringUtil.isEmpty(data[i][5]) ? null : Long.valueOf(data[i][5]));
            bookResourceExcelDTO.setUrl(StringUtil.isEmpty(data[i][6]) ? "" : data[i][6]);
            bookResourceExcelDTOList.add(bookResourceExcelDTO);
        }
        return bookResourceExcelDTOList;
    }

    private String getfileSuffix(MultipartFile multipartFile) {
        String originalFilename = multipartFile.getOriginalFilename();
        return originalFilename.substring(originalFilename.lastIndexOf('.'), originalFilename.length());
    }

    private void fillReadGuide(AppletUserBookcaseDTO appletUserBookcaseDTO,Long rightsSettingId){
        if (null == rightsSettingId) {
            return;
        }
        RightsSetting rightsSetting = rightsSettingDAO.selectByPrimaryKey(rightsSettingId);
        if (null == rightsSetting) {
            return;
        }
        if (rightsSetting != null){
            appletUserBookcaseDTO.setBannerType(rightsSetting.getBannerType());
            appletUserBookcaseDTO.setGuideIsOpen(rightsSetting.getGuideIsOpen());
        }
        if (ListUtils.isEmpty(rightsSetting.getRightsSettingBanners())) {
            return;
        }
        rightsSettingBiz.fillReadGuide(rightsSetting.getRightsSettingBanners());
        appletUserBookcaseDTO.setRightsSettingBanners(rightsSetting.getRightsSettingBanners());
    }

    @Override
    public List<BookDto> getLatest10Books4Clock(Long wechatUserId, Long officialAccountsId) {
        List<Long> wechatUserIdList = readerConsr.getRelateUserIdList(wechatUserId, officialAccountsId);
        return appletUserBookcaseDao.getLatest10Books4Clock(wechatUserIdList);
    }
}
