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.consumer.user.AdviserConsr;
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.util.common.ThreadPoolUtils;
import com.pcloud.common.constant.CacheConstant;
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.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 AdviserConsr adviserConsr;
    @Autowired
    private AssistTempletConsr assistTempletConsr;
    @Autowired
    private BookGroupBiz bookGroupBiz;
    @Autowired
    private BookRaysClassifyDao bookRaysClassifyDao;
    @Autowired
    private RightsSettingBiz rightsSettingBiz;

    @Override
    public void addUserBook(AppletUserBookcase appletUserBookcase) {
        //数据库去重
        appletUserBookcaseDao.insert(appletUserBookcase);
        Long wechatUserId = appletUserBookcase.getWechatUserId();
        JedisClusterUtils.del(AppletConstants.USER_BOOK_CASE + wechatUserId);
        JedisClusterUtils.del(AppletConstants.USER_BOOK_CASE_COUNT + wechatUserId);
    }

    @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 (null == pageBeanNew || ListUtils.isEmpty(pageBeanNew.getRecordList())){
            return new PageBeanNew<>(currentPage,numPerPage,0,new ArrayList<>());
        }
        fillTempletName(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;
    }

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

}
