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

import com.google.common.collect.Maps;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.dao.BookDao;
import com.pcloud.book.book.dao.SearchRecordDao;
import com.pcloud.book.book.dto.AdviserBookInfoDTO;
import com.pcloud.book.consumer.content.ResourceConsr;
import com.pcloud.book.consumer.message.TemplateConsr;
import com.pcloud.book.consumer.reader.ReaderConsr;
import com.pcloud.book.consumer.user.AdviserConsr;
import com.pcloud.book.consumer.wechatgroup.WechatGroupConsr;
import com.pcloud.book.cultivate.biz.CultivateNotifyBiz;
import com.pcloud.book.cultivate.check.NotifyParamCheck;
import com.pcloud.book.cultivate.dao.CultivateNotifyDao;
import com.pcloud.book.cultivate.dao.CultivateNotifyItemDao;
import com.pcloud.book.cultivate.dao.CultivateNotifySendDao;
import com.pcloud.book.cultivate.dto.CultivateNotifyDTO;
import com.pcloud.book.cultivate.dto.CultivateNotifyPageDTO;
import com.pcloud.book.cultivate.dto.CultivateNotifyTypeDTO;
import com.pcloud.book.cultivate.dto.SearchNotifyDTO;
import com.pcloud.book.cultivate.dto.SearchSendUserDTO;
import com.pcloud.book.cultivate.dto.WechatUserDTO;
import com.pcloud.book.cultivate.entity.CultivateNotify;
import com.pcloud.book.cultivate.entity.CultivateNotifyItem;
import com.pcloud.book.cultivate.entity.CultivateNotifySend;
import com.pcloud.book.cultivate.enums.NotifySendTypeEnum;
import com.pcloud.book.util.common.ThreadPoolUtils;
import com.pcloud.common.core.dto.AppletTemplateMessageDto;
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.contentcenter.resource.dto.ResourceDTO;
import com.pcloud.readercenter.wechat.dto.MiniUserDto;
import com.pcloud.readercenter.wechat.dto.ReaderMessageDto;
import com.pcloud.usercenter.party.adviser.dto.AdviserBaseInfoDto;
import com.pcloud.wechatgroup.selfrobot.dto.SendMessageDTO;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

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.stream.Collectors;

@Component("cultivateNotifyBiz")
public class CultivateNotifyBizImpl implements CultivateNotifyBiz {

    @Autowired
    private NotifyParamCheck notifyParamCheck;
    @Autowired
    private CultivateNotifyDao cultivateNotifyDao;
    @Autowired
    private CultivateNotifyItemDao cultivateNotifyItemDao;
    @Autowired
    private CultivateNotifySendDao cultivateNotifySendDao;
    @Autowired
    private WechatGroupConsr wechatGroupConsr;
    @Autowired
    private ReaderConsr readerConsr;

    @Autowired
    private ResourceConsr resourceConsr;
    @Autowired
    private SearchRecordDao searchRecordDao;
    @Autowired
    private BookDao bookDao;
    @Autowired
    private AdviserConsr adviserConsr;
    @Autowired
    private TemplateConsr templateConsr;

    @Value("${mini.official.account.id}")
    private Long accountSettingId;

    private final Integer SEND_BATCH_NUM=100;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createNotify(CultivateNotifyDTO cultivateNotifyDTO) {
        notifyParamCheck.createNotifyCheck(cultivateNotifyDTO);
        CultivateNotify cultivateNotify=new CultivateNotify();
        cultivateNotify.setMessageType(cultivateNotifyDTO.getMessageType());
        cultivateNotify.setTitle(cultivateNotifyDTO.getTitle());
        cultivateNotify.setSendType(cultivateNotifyDTO.getSendType());
        cultivateNotifyDao.insert(cultivateNotify);
        cultivateNotifyDTO.getCultivateNotifyItems().forEach(a->a.setMessageId(cultivateNotify.getMessageId()));
        cultivateNotifyItemDao.insert(cultivateNotifyDTO.getCultivateNotifyItems());
        ThreadPoolUtils.SEND_NOTIFY_POOL.execute(()->{
            addSendNotify(cultivateNotifyDTO,cultivateNotify);
        });
    }

    @Override
    public CultivateNotifyDTO getFirstNoReadNotify(Long wechatUserId) {
        Long messageId= cultivateNotifySendDao.getFirstNoReadNotify(wechatUserId);
        if(messageId==null){
            return new CultivateNotifyDTO();
        }
        CultivateNotifyDTO notifyDTO= new CultivateNotifyDTO();
        List<CultivateNotifyItem> list=cultivateNotifyItemDao.getNotifyItemsByMessageId(messageId);
        fillResource(list);
        notifyDTO.setCultivateNotifyItems(list);
        CultivateNotify byId = cultivateNotifyDao.getById(messageId);
        notifyDTO.setMessageType(byId.getMessageType());
        notifyDTO.setTitle(byId.getTitle());
        // cultivateNotifySendDao.updateIsRead(wechatUserId,messageId);
        // 更新之前的所有未读消息都不显示到主页
        cultivateNotifySendDao.updateShowHome(wechatUserId);
        return notifyDTO;
    }

    @Override
    public List<CultivateNotifyTypeDTO> getNotify4Type(Long wechatUserId) {
        return cultivateNotifySendDao.getNotify4Type(wechatUserId);
    }

    @Override
    public PageBeanNew<CultivateNotifyDTO> getNotifyListByType(Long wechatUserId, Integer messageType,Integer currentPage,Integer numPerPage) {
        Map<String,Object> map=new HashMap<>();
        map.put("wechatUserId",wechatUserId);
        map.put("messageType",messageType);
        PageBeanNew<CultivateNotifyDTO> pageBeanNew= cultivateNotifySendDao.listPageNew(new PageParam(currentPage, numPerPage), map, "getNotifyListByType");
        for (CultivateNotifyDTO cultivateNotifyDTO:pageBeanNew.getRecordList()) {
            List<CultivateNotifyItem> list1=cultivateNotifyItemDao.getNotifyItemsByMessageId(cultivateNotifyDTO.getMessageId());
            fillResource(list1);
            cultivateNotifyDTO.setCultivateNotifyItems(list1);

        }
        //批量更新消息已读未读
        List<CultivateNotifySend> notifySends=cultivateNotifySendDao.getNotifySendsByType(wechatUserId,messageType);
        for (CultivateNotifySend notifySend:notifySends) {
            notifySend.setIsRead(true);
            notifySend.setReadTime(new Date());
            notifySend.setUpdateTime(new Date());
            cultivateNotifySendDao.update(notifySend);
        }

        return pageBeanNew;
    }

    private void fillResource(List<CultivateNotifyItem> list){
        List<Long> resourceIds=new ArrayList<>();
        for (CultivateNotifyItem notifyItem : list){
            Integer type = notifyItem.getContentType();
            if (type==3){
                resourceIds.add(notifyItem.getResourceId());
            }
        }
        Map<Long, ResourceDTO> resourceDTOMap=new HashMap<>();
        if (!ListUtils.isEmpty(resourceIds)){
            resourceDTOMap = resourceConsr.mapByIds(resourceIds);
        }
        for (CultivateNotifyItem notifyItem : list) {
            Integer type = notifyItem.getContentType();
            if (type == 3) {
                ResourceDTO resourceDTO = resourceDTOMap.get(notifyItem.getResourceId());
                if (resourceDTO != null) {
                    notifyItem.setResourceName(resourceDTO.getResourceName());
                    notifyItem.setResourceUrl(resourceDTO.getFileUrl());
                    notifyItem.setResourceTypeCode(resourceDTO.getTypeCode());
                    notifyItem.setResourceTypeName(resourceDTO.getTypeName());
                    notifyItem.setFileType(resourceDTO.getFileType());
                    notifyItem.setFileSize(resourceDTO.getFileSize());
                    notifyItem.setResourcePdfItems(resourceDTO.getResourcePdfItems());
                    notifyItem.setResourceOfficeItemDTOs(resourceDTO.getResourceOfficeItemDTOs());
                    notifyItem.setDuration(resourceDTO.getDuration());
                }
            }
        }
    }


    private void addSendNotify(CultivateNotifyDTO cultivateNotifyDTO,CultivateNotify cultivateNotify){
        List<CultivateNotifySend> list=new ArrayList<>();
        //指定用户发送
        if (NotifySendTypeEnum.APPOINT_USER.value.equals(cultivateNotifyDTO.getSendType())) {
            CultivateNotifySend cultivateNotifySend = null;
            for (WechatUserDTO wechatUserDTO : cultivateNotifyDTO.getWechatUserDTOS()) {
                cultivateNotifySend = new CultivateNotifySend();
                cultivateNotifySend.setMessageId(cultivateNotify.getMessageId());
                cultivateNotifySend.setMessageType(cultivateNotifyDTO.getMessageType());
                cultivateNotifySend.setSendType(cultivateNotifyDTO.getSendType());
                cultivateNotifySend.setWxUserId(wechatUserDTO.getWxUserId());
                cultivateNotifySend.setWechatUserId(wechatUserDTO.getWechatUserId());
                cultivateNotifySend.setTitle(cultivateNotify.getTitle());
                list.add(cultivateNotifySend);
            }
            cultivateNotifySendDao.insert(list);
            sendAppletTemplateMessage(list);
        }
        //分类用户发送
        if (NotifySendTypeEnum.CLASSIFY_USER.value.equals(cultivateNotifyDTO.getSendType())) {
            SendMessageDTO sendMessageDTO = new SendMessageDTO();
            sendMessageDTO.setClassifyId(cultivateNotifyDTO.getClassifyId());
            sendMessageDTO.setMessageId(cultivateNotify.getMessageId());
            sendMessageDTO.setMessageType(cultivateNotify.getMessageType());
            sendMessageDTO.setSendType(cultivateNotifyDTO.getSendType());
            sendMessageDTO.setWxId(cultivateNotifyDTO.getWxId());
            wechatGroupConsr.sendMessageToMiniUser(sendMessageDTO);
        }
        //书刊发送
        if(NotifySendTypeEnum.BOOK_USER.value.equals(cultivateNotifyDTO.getSendType())){
            List<Long> wechatUserIds = searchRecordDao.getWechatUserIds(cultivateNotifyDTO.getBookId());
            if(ListUtils.isEmpty(wechatUserIds)){
                return;
            }
            for (int i = 0; i <= wechatUserIds.size() / SEND_BATCH_NUM; i++) {
                int beginIndex = i * SEND_BATCH_NUM;
                int endIndex = beginIndex + SEND_BATCH_NUM;
                if (i == (wechatUserIds.size() - 1)/SEND_BATCH_NUM){
                    endIndex = wechatUserIds.size();
                }
                List<Long> subList = wechatUserIds.subList(beginIndex, endIndex);
                List<CultivateNotifySend> cultivateNotifySendList=new ArrayList<>();
                if(!ListUtils.isEmpty(subList)){
                    for (Long wechatUserId : subList) {
                        CultivateNotifySend cultivateNotifySend=new CultivateNotifySend();
                        cultivateNotifySend.setMessageId(cultivateNotify.getMessageId());
                        cultivateNotifySend.setMessageType(cultivateNotifyDTO.getMessageType());
                        cultivateNotifySend.setSendType(cultivateNotifyDTO.getSendType());
                        cultivateNotifySend.setWechatUserId(wechatUserId);
                        cultivateNotifySendList.add(cultivateNotifySend);
                    }
                    cultivateNotifySendDao.insert(cultivateNotifySendList);
                    sendAppletTemplateMessage(cultivateNotifySendList);
                }
            }
        }
        //全局发送
        if(NotifySendTypeEnum.ALL_USER.value.equals(cultivateNotifyDTO.getSendType())){
            ReaderMessageDto readerMessageDto=new ReaderMessageDto();
            readerMessageDto.setMessageId(cultivateNotify.getMessageId());
            readerMessageDto.setSendType(cultivateNotifyDTO.getSendType());
            readerMessageDto.setMessageType(cultivateNotifyDTO.getMessageType());
            readerConsr.sendNotifyMiniUser(readerMessageDto);
        }
    }

    /**
     * 发送小程序模板消息
     * @param list
     */
    public void sendAppletTemplateMessage(List<CultivateNotifySend> list) {
        AppletTemplateMessageDto appletTemplateMessage;
        Map<String, String> tempMap;
        for (CultivateNotifySend cultivateNotifySend : list) {
            if(cultivateNotifySend.getMessageType() == 1){ continue;}
            appletTemplateMessage = new AppletTemplateMessageDto();
            appletTemplateMessage.setAccountSettingId(accountSettingId);
            appletTemplateMessage.setWechatUserId(cultivateNotifySend.getWechatUserId());
            appletTemplateMessage.setTempalteTypeCode("xiaorui_unread_message_remind");
            appletTemplateMessage.setPage("pages/index/index");
            tempMap = Maps.newHashMap();
            tempMap.put("thing2", cultivateNotifySend.getTitle());
            tempMap.put("time3", DateUtils.getLongDateStr());
            tempMap.put("thing7", "小睿有1条新通知提醒一下小主");
            appletTemplateMessage.setData(tempMap);
            templateConsr.sendAppletMessageQueue(appletTemplateMessage);
        }
    }


    @Override
    public PageBeanNew<CultivateNotifyPageDTO> listPage4CultivateNotify(SearchNotifyDTO searchNotifyDTO) {
        if(null==searchNotifyDTO || Objects.isNull(searchNotifyDTO.getNumPerPage()) || Objects.isNull(searchNotifyDTO.getPageNum())){
            throw new BookBizException(BookBizException.PARAM_IS_NULL,"分页参数有误！");
        }
        Map<String,Object> map=new HashMap<>();
        map.put("keyword",searchNotifyDTO.getKeyword());
        map.put("sendType",searchNotifyDTO.getSendType());
        map.put("messageType",searchNotifyDTO.getMessageType());
        PageBeanNew<CultivateNotifyPageDTO> pageBeanNew= cultivateNotifySendDao.listPageNew(new PageParam(searchNotifyDTO.getPageNum(), searchNotifyDTO.getNumPerPage()), map, "listPage4CultivateNotify");
        if(null==pageBeanNew || ListUtils.isEmpty(pageBeanNew.getRecordList())){
            return new PageBeanNew<>(searchNotifyDTO.getPageNum(), searchNotifyDTO.getNumPerPage(),pageBeanNew.getTotalCount(), new ArrayList<>());
        }
        buildSendInfo(pageBeanNew.getRecordList());
        return pageBeanNew;
    }

    private void buildSendInfo(List<CultivateNotifyPageDTO> list) {
        List<Long> messageIds = list.stream().filter(a -> null != a.getMessageId()).map(a -> a.getMessageId()).distinct().collect(Collectors.toList());
        Map<Long, String> titleMap=new HashMap<>();
        Map<Long, List<CultivateNotifyItem>> itemMap=new HashMap<>();
        if(!ListUtils.isEmpty(messageIds)){
           /* List<CultivateNotify> cultivateNotifies = cultivateNotifyDao.getByIds(messageIds);
            titleMap= cultivateNotifies.stream().collect(Collectors.toMap(a -> a.getMessageId(), a -> a.getTitle(), (k1, k2) -> k2));*/
            List<CultivateNotifyItem> cultivateNotifyItems = cultivateNotifyItemDao.getByMessageIds(messageIds);
            itemMap= cultivateNotifyItems.stream().collect(Collectors.groupingBy(a -> a.getMessageId()));
        }
        for (CultivateNotifyPageDTO cultivateNotifyPageDTO : list) {
         /*   if(MapUtils.isNotEmpty(titleMap) && titleMap.containsKey(cultivateNotifyPageDTO.getMessageId())){
                cultivateNotifyPageDTO.setTitle(titleMap.get(cultivateNotifyPageDTO.getMessageId()));
            }*/
            if(MapUtils.isNotEmpty(itemMap) && itemMap.containsKey(cultivateNotifyPageDTO.getMessageId())){
                cultivateNotifyPageDTO.setCultivateNotifyItems(itemMap.get(cultivateNotifyPageDTO.getMessageId()));
            }
            if(!ListUtils.isEmpty(cultivateNotifyPageDTO.getCultivateNotifyItems())){
                fillResource(cultivateNotifyPageDTO.getCultivateNotifyItems());
            }
        }
    }

    @Override
    public PageBeanNew<MiniUserDto> listPage4SendUser(SearchSendUserDTO searchSendUserDTO) {
        if(null==searchSendUserDTO || null==searchSendUserDTO.getMessageId() || null==searchSendUserDTO.getCurrentPage() || null==searchSendUserDTO.getNumPerPage()){
            throw new BookBizException(BookBizException.PARAM_IS_NULL,"参数有误！");
        }
        Integer count = cultivateNotifySendDao.getSendUserCount(searchSendUserDTO.getMessageId());
        if(count<=0){
            return new PageBeanNew<>(searchSendUserDTO.getCurrentPage(), searchSendUserDTO.getNumPerPage(), new ArrayList<>());
        }
        List<Long> sendUserIds = cultivateNotifySendDao.getSendUserIds(searchSendUserDTO.getMessageId(), searchSendUserDTO.getCurrentPage(), searchSendUserDTO.getNumPerPage());
        List<MiniUserDto> list = readerConsr.getSendUserRobotInfo(sendUserIds);
        return new PageBeanNew<>(searchSendUserDTO.getCurrentPage(), searchSendUserDTO.getNumPerPage(),count,list);
    }

    @Override
    public PageBeanNew<AdviserBookInfoDTO> listPage4SearchBook(SearchSendUserDTO searchSendUserDTO) {
        if(null==searchSendUserDTO  || null==searchSendUserDTO.getCurrentPage() || null==searchSendUserDTO.getNumPerPage()){
            throw new BookBizException(BookBizException.PARAM_IS_NULL,"参数有误！");
        }
        Integer count = searchRecordDao.getBookSearchCount(searchSendUserDTO.getKeyword());
        if(count<=0){
            return new PageBeanNew<>(searchSendUserDTO.getCurrentPage(), searchSendUserDTO.getNumPerPage(), new ArrayList<>());
        }
        List<AdviserBookInfoDTO> infos = searchRecordDao.getBookSearchIds(searchSendUserDTO.getKeyword(),searchSendUserDTO.getCurrentPage(), searchSendUserDTO.getNumPerPage());
        //Map<Long, AdviserBookInfoDTO> adviserBookInfoDTOMap = infos.stream().collect(Collectors.toMap(a -> a.getBookId(), a -> a, (k1, k2) -> k2));
        List<Long> adviserIds = infos.stream().filter(s -> s.getAdviserId() != null).map(AdviserBookInfoDTO::getAdviserId).distinct().collect(Collectors.toList());
        Map<Long, AdviserBaseInfoDto> adviserMap = adviserConsr.getAdviserId2AdviserInfoDtoMap(adviserIds);
        for (AdviserBookInfoDTO dto : infos) {
            if (!MapUtils.isEmpty(adviserMap) && null != dto.getAdviserId() && adviserMap.containsKey(dto.getAdviserId())) {
                AdviserBaseInfoDto adviserBaseInfoDto = adviserMap.get(dto.getAdviserId());
                if (null != adviserBaseInfoDto){
                    dto.setAdviserName(adviserBaseInfoDto.getPartyName());
                    dto.setAgentName(adviserBaseInfoDto.getAgentName());
                }
            }
        }
        return  new PageBeanNew<>(searchSendUserDTO.getCurrentPage(), searchSendUserDTO.getNumPerPage(),count, infos);
    }
}
