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

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.AppletUserBookcaseDTO;
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.dao.BookRaysClassifyDao;
import com.pcloud.book.book.entity.BookRaysClassify;
import com.pcloud.book.consumer.app.AssistTempletConsr;
import com.pcloud.book.es.biz.ESBookAndAdviserBiz;
import com.pcloud.book.group.biz.BookGroupBiz;
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.dto.RightsSettingDto;
import com.pcloud.book.rightsSetting.entity.RightsReadType;
import com.pcloud.book.util.common.ThreadPoolUtils;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.page.PageBeanNew;
import com.pcloud.common.page.PageParam;
import com.pcloud.common.utils.DateUtils;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.cache.redis.JedisClusterUtils;
import com.pcloud.common.utils.string.StringUtil;

import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

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.Random;
import java.util.stream.Collectors;

/**
 * 小程序用户书架
 */
@Component
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;

    @Override
    public void addUserBook(AppletUserBookcase appletUserBookcase) {
        Long wechatUserId = appletUserBookcase.getWechatUserId();
        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(appletUserBookcase);
        JedisClusterUtils.del(AppletConstants.USER_BOOK_CASE + wechatUserId);
        JedisClusterUtils.del(AppletConstants.USER_BOOK_CASE_COUNT + wechatUserId);
        esBookAndAdviserBiz.updateBookAndAdviserToES(Collections.singletonList(appletUserBookcase.getBookId()));
    }

    @Override
    public PageBeanNew<AppletUserBookcaseDTO> listByWechatUserId(Long wechatUserId, Integer currentPage, Integer numPerPage) {
        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("wechatUserId", wechatUserId);
        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());
        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 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());
            }
        });
        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.mapByIds(templetIds);
        for (AppletUserBookcaseDTO bookcaseDTO : recordList) {
            Long secondTempletId = bookcaseDTO.getSecondTempletId();
            Long templetId = bookcaseDTO.getTempletId();
            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 (!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) {
        if (wechatUserId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        //查询最后一本社群书
        UserLastBookReDTO lastBookRe = appletUserBookcaseDao.getUserLastGroupBookRe(wechatUserId);
        if (lastBookRe != null) {
            lastBookRe.setHasBook(true);
            lastBookRe.setBookGroup(true);
            RightsSettingDto rightsSettingDto = rightsSettingBiz.getRightsSettingByBookId4AppletHome(lastBookRe.getBookId(), lastBookRe.getAdviserId(), lastBookRe.getChannelId());
            if (rightsSettingDto != null) {
                lastBookRe.setRightSettingId(rightsSettingDto.getId());
            }
            return lastBookRe;
        } else {
            //查询最后一本书
            UserLastBookReDTO userLastRe = appletUserBookcaseDao.getUserLastRe(wechatUserId);
            if (userLastRe != null) {
                userLastRe.setBookGroup(false);
                userLastRe.setHasBook(true);
                RightsSettingDto rightsSettingDto = rightsSettingBiz.getRightsSettingByBookId4AppletHome(userLastRe.getBookId(), userLastRe.getAdviserId(), userLastRe.getChannelId());
                if (rightsSettingDto != null) {
                    userLastRe.setRightSettingId(rightsSettingDto.getId());
                }
                return userLastRe;
            } else {
                lastBookRe = new UserLastBookReDTO();
                lastBookRe.setHasBook(false);
                return lastBookRe;
            }
        }
    }

    @Override
    public void deleteByIds(List<Long> ids, Long wechatUserId) {
        if (ListUtils.isEmpty(ids)) {
            return;
        }
        esBookAndAdviserBiz.updateBookAndAdviserToES(appletUserBookcaseDao.getBookIdsByIds(ids));
        appletUserBookcaseDao.deleteByIds(ids);
        JedisClusterUtils.del(AppletConstants.USER_BOOK_CASE + wechatUserId);
        JedisClusterUtils.del(AppletConstants.USER_BOOK_CASE_COUNT + wechatUserId);
    }

    @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(wechatUserId, bookId, adviserId, channelId);
        return appletUserBookcase;
    }

    @Override
    public void randomChangeBook(Long wechatUserId) {
        List<AppletUserBookcase> bookcaseList = appletUserBookcaseDao.getListByUserId(wechatUserId);
        //无书或只有一本不处理
        if (ListUtils.isEmpty(bookcaseList) || bookcaseList.size() == 1) {
            return;
        }
        //去除最近一本书
        bookcaseList.remove(0);
        //随机取一本书埋点
        AppletUserBookcase appletUserBookcase = bookcaseList.get(new Random().nextInt(bookcaseList.size()));
        this.addUserBook(appletUserBookcase);
        ThreadPoolUtils.OTHER_THREAD_POOL.execute(() -> {
            this.listByWechatUserId(wechatUserId, 0, 1);
        });
    }

    @Override
    public List<Long> getBookcaseIdListByUser(Long wechatUserId) {
        return appletUserBookcaseDao.getBookcaseIdListByUser(wechatUserId);
    }

    @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) {
        AppletUserBookcaseDTO userBookInfoByWechatUserId = appletUserBookcaseDao.getUserBookInfoByWechatUserId(bookId,channelId,adviserId);
        if (userBookInfoByWechatUserId == null){
            return new AppletUserBookcaseDTO();
        }
        List<AppletUserBookcaseDTO> appletUserBookcaseDTOS = Collections.singletonList(userBookInfoByWechatUserId);
        fillTempletName(appletUserBookcaseDTOS);
        fillRightsSettingAndResourceCount(appletUserBookcaseDTOS);
        return appletUserBookcaseDTOS.get(0);
    }

}
