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

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.pcloud.appcenter.app.dto.AppDto;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.consumer.app.AppConsr;
import com.pcloud.book.consumer.content.ResourceConsr;
import com.pcloud.book.consumer.wechatgroup.WechatGroupConsr;
import com.pcloud.book.custom.biz.CustomTimeControlBiz;
import com.pcloud.book.custom.check.CustomCheck;
import com.pcloud.book.custom.dao.CustomTimeControlDao;
import com.pcloud.book.custom.dto.CustomTimeControlDTO;
import com.pcloud.book.custom.dto.CustomTimeControlPageDTO;
import com.pcloud.book.custom.entity.CustomTimeControl;
import com.pcloud.book.custom.entity.CustomTimeControlBook;
import com.pcloud.book.custom.entity.CustomTimeControlReply;
import com.pcloud.book.custom.entity.CustomTimeControlUser;
import com.pcloud.book.custom.mapper.CustomTimeControlBookMapper;
import com.pcloud.book.custom.mapper.CustomTimeControlReplyMapper;
import com.pcloud.book.custom.mapper.CustomTimeControlUserMapper;
import com.pcloud.book.group.dao.WeixinQrcodeGenerationDao;
import com.pcloud.book.group.entity.WeixinQrcodeGeneration;
import com.pcloud.book.group.enums.AppAndProductTypeEnum;
import com.pcloud.book.keywords.enums.ReplyTypeEnum;
import com.pcloud.book.pcloudkeyword.set.PcloudRobotSet;
import com.pcloud.book.skill.dto.AppOrProductReplyDTO;
import com.pcloud.book.skill.entity.PcloudSubReply;
import com.pcloud.book.timecontrol.biz.TaskSubscribeBiz;
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.ListUtils;
import com.pcloud.common.utils.ResponseHandleUtil;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.common.utils.string.StringUtilParent;
import com.pcloud.contentcenter.resource.dto.ResourceDTO;
import com.pcloud.erp.project.dto.ProjectInfoDTO;
import com.pcloud.erp.project.service.ProjectService;

import com.pcloud.wechatgroup.group.dto.GroupRobotDTO;
import com.sdk.wxgroup.RobotProcessTypeEnum;
import com.sdk.wxgroup.SendFileVO;
import com.sdk.wxgroup.SendMessageTypeEnum;
import com.sdk.wxgroup.SendPicMessageVO;
import com.sdk.wxgroup.SendTextMessageVO;
import com.sdk.wxgroup.im.mimc.BusinessConstant;
import com.sdk.wxgroup.im.mimc.dto.SendMomentsDTO;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
public class CustomTimeControlBizImpl implements CustomTimeControlBiz {
    @Autowired
    private CustomTimeControlDao customTimeControlMapper;
    @Autowired
    private CustomTimeControlBookMapper customTimeControlBookMapper;
    @Autowired
    private CustomTimeControlReplyMapper customTimeControlReplyMapper;
    @Autowired
    private CustomCheck customCheck;
    @Autowired
    private ProjectService projectService;
    @Autowired
    private AppConsr appConsr;
    @Autowired
    private ResourceConsr resourceConsr;
    @Autowired
    private TaskSubscribeBiz taskSubscribeBiz;
    @Autowired
    private WechatGroupConsr wechatGroupConsr;
    @Autowired
    private PcloudRobotSet pcloudRobotSet;
    @Autowired
    private WeixinQrcodeGenerationDao weixinQrcodeGenerationDao;
    @Autowired
    private CustomTimeControlUserMapper customTimeControlUserMapper;

    @Override
    @Transactional
    @ParamLog("新增定制服务读书计划")
    public Integer createCustomTimeControl(CustomTimeControlDTO customTimeControlDTO) {
        customCheck.createCustomTimeControlCheck(customTimeControlDTO);
        Integer id = insertCustomTimeControl(customTimeControlDTO.getTimeControlTaskId());
        if (null == id){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"定制读书计划id不能为空！");
        }
        insertCustomTimeControlReply(id,customTimeControlDTO.getReplyList4Subscribe(),customTimeControlDTO.getReplyList4Unsubscribe());
        insertCustomTimeControlBook(id,customTimeControlDTO.getRelatedBooks());
        return id;
    }



    private void insertCustomTimeControlBook(Integer id, List<CustomTimeControlBook> relatedBooks) {
        if (!ListUtils.isEmpty(relatedBooks)){
            relatedBooks.forEach(e -> e.setCustomTimeControlId(id));
            customTimeControlBookMapper.batchInsert(relatedBooks);
        }
    }


    private void insertCustomTimeControlReply(Integer id, List<CustomTimeControlReply> replyList4Subscribe, List<CustomTimeControlReply> replyList4Unsubscribe) {
        List<CustomTimeControlReply> customTimeControlReplies = new ArrayList<>();
        if (!ListUtils.isEmpty(replyList4Subscribe)){
            customTimeControlReplies.addAll(replyList4Subscribe);
        }
        if (!ListUtils.isEmpty(replyList4Unsubscribe)){
            customTimeControlReplies.addAll(replyList4Unsubscribe);
        }
        if (!ListUtils.isEmpty(customTimeControlReplies)){
            customTimeControlReplies.forEach(e ->e.setCustomTimeControlId(id));
            customTimeControlReplyMapper.batchInsert(customTimeControlReplies);
        }
    }

    private Integer insertCustomTimeControl(Integer timeControlTaskId) {
        CustomTimeControl customTimeControl = new CustomTimeControl();
        customTimeControl.setTimeControlTaskId(timeControlTaskId);
        customTimeControl.setCreateTime(new Date());
        customTimeControlMapper.insert(customTimeControl);
        return  Integer.valueOf(customTimeControl.getId().toString());
    }

    @Override
    @Transactional
    @ParamLog("更新定制服务读书计划")
    public void updateCustomTimeControl(CustomTimeControlDTO customTimeControlDTO) {
        customCheck.updateCustomTimeControlCheck(customTimeControlDTO);
        Integer id = customTimeControlDTO.getId();
        updateCustomTimeControl(id,customTimeControlDTO.getTimeControlTaskId());
        updateCustomTimeControlReply(id, customTimeControlDTO.getReplyList4Subscribe(), customTimeControlDTO.getReplyList4Unsubscribe());
        updateCustomTimeControlBook(id, customTimeControlDTO.getRelatedBooks());
    }

    @Override
    @ParamLog("获取定制服务读书计划分页列表")
    public PageBeanNew<CustomTimeControlPageDTO> getCustomTimeControlPage(String taskName, Integer currentPage, Integer numPerPage) {
        Map<String, Object> paramMap =  new HashMap<>();
        paramMap.put("taskName",taskName);
        PageBeanNew<CustomTimeControlPageDTO> customTimeControlPage = customTimeControlMapper.
                listPageNew(new PageParam(currentPage,numPerPage),paramMap,"getCustomTimeControlPage");
        if (null != customTimeControlPage && !ListUtils.isEmpty(customTimeControlPage.getRecordList())){
            List<Integer> customTimeControlIds = customTimeControlPage.getRecordList().stream().map(e -> e.getId()).collect(Collectors.toList());
            List<CustomTimeControlPageDTO> customTimeControlPageDTOS = customTimeControlBookMapper.getBooKCountList(customTimeControlIds);
            Map<Integer,Integer> booKCountMap =
                    customTimeControlPageDTOS.stream().collect(Collectors.toMap(CustomTimeControlPageDTO::getId, CustomTimeControlPageDTO::getRelatedBookCount));
            if (MapUtils.isNotEmpty(booKCountMap)){
                customTimeControlPage.getRecordList().stream().forEach(e -> {
                    e.setRelatedBookCount(null == booKCountMap.get(e.getId()) ? 0 : booKCountMap.get(e.getId()));
                });
            }
            customTimeControlPage.getRecordList().stream().forEach(e -> {
                e.setShortTaskIntroduce(StringUtilParent.replaceHtml(e.getTaskIntroduce()));
            });
        }
        return customTimeControlPage;
    }

    @Override
    @ParamLog(value = "通过id获取定制服务读书推送计划",isAfterReturn = false)
    public CustomTimeControlDTO getCustomTimeControlById(Integer id) {
        CustomTimeControlDTO customTimeControlDTO = customTimeControlMapper.getCustomTimeControlById(id);
        if (null == customTimeControlDTO){
            throw new BookBizException(BookBizException.PARAM_IS_EXIST,"通过id获取定制服务读书推送计划为null");
        }
        List<CustomTimeControlBook> customTimeControlBooks = customTimeControlDTO.getRelatedBooks();
        fillRelies(customTimeControlDTO.getReplyList4Subscribe(),customTimeControlDTO.getReplyList4Unsubscribe());
        if (!ListUtils.isEmpty(customTimeControlBooks)){
            List<String> bookIds = customTimeControlBooks.stream().map(e -> e.getBookId()).collect(Collectors.toList());
            Map<String, ProjectInfoDTO>  projectMap = null;
            try {
                projectMap = ResponseHandleUtil.parseMap(projectService.getProjectInfoBySerialNumbers(bookIds),String.class, ProjectInfoDTO.class);
            } catch (Exception e) {
                log.error("获取erp书籍信息失败");
            }
            if (MapUtils.isNotEmpty(projectMap)){
                for (CustomTimeControlBook e : customTimeControlBooks) {
                    e.setBookName(null == projectMap.get(e.getBookId()) ? "" : projectMap.get(e.getBookId()).getBookName());
                    e.setErpBookId(null == projectMap.get(e.getBookId()) ? null : Integer.valueOf(projectMap.get(e.getBookId()).getProjectId().toString()));
                }
            }
        }
        return customTimeControlDTO;
    }

    private void fillRelies(List<CustomTimeControlReply> replyList4Subscribe, List<CustomTimeControlReply> replyList4Unsubscribe) {
        log.info("填充资源");
        List<CustomTimeControlReply> customTimeControlReplies = new ArrayList<>();
        if (!ListUtils.isEmpty(replyList4Subscribe)){
            customTimeControlReplies.addAll(replyList4Subscribe);
        }
        if (!ListUtils.isEmpty(replyList4Unsubscribe)){
            customTimeControlReplies.addAll(replyList4Unsubscribe);
        }
        if (ListUtils.isEmpty(customTimeControlReplies)){
            return;
        }
        List<Long> appIds=new ArrayList<>();
        List<Long> resourceIds=new ArrayList<>();
        for (CustomTimeControlReply reply:customTimeControlReplies){
            Integer type=reply.getReplyType();
            if (ReplyTypeEnum.APP.value.equals(type)){
                if (AppAndProductTypeEnum.APP.value.equals(reply.getServeType())){
                    appIds.add(reply.getServeId());
                }
            }
            if (ReplyTypeEnum.RESOURCE.value.equals(type)){
                resourceIds.add(reply.getResourceId());
            }
        }
        Map<Long, AppDto> appDtoMap=new HashMap<>();
        Map<Long, ResourceDTO> resourceDTOMap=new HashMap<>();
        if (!ListUtils.isEmpty(appIds)){
            appDtoMap = appConsr.getBaseByIds(appIds);
        }

        if (!ListUtils.isEmpty(resourceIds)){
            resourceDTOMap = resourceConsr.mapByIds(resourceIds);
        }
        for (CustomTimeControlReply reply:customTimeControlReplies){
            Integer type=reply.getReplyType();
            if (ReplyTypeEnum.APP.value.equals(type)){
                Long serveId=reply.getServeId();
                if (AppAndProductTypeEnum.APP.value.equals(reply.getServeType())){
                    AppDto appDto=appDtoMap.get(serveId);
                    if (appDto!=null){
                        reply.setServePic(appDto.getSquareImg());
                        reply.setServeName(appDto.getTitle());
                        reply.setServeTypeCode(appDto.getTypeCode());
                        reply.setServeTypeName(appDto.getTypeName());
                    }
                }
            }
            if (ReplyTypeEnum.RESOURCE.value.equals(type)){
                ResourceDTO resourceDTO = resourceDTOMap.get(reply.getResourceId());
                if (resourceDTO!=null){
                    reply.setResourceName(resourceDTO.getResourceName());
                    reply.setResourceUrl(resourceDTO.getFileUrl());
                    reply.setResourceTypeCode(resourceDTO.getTypeCode());
                    reply.setResourceTypeName(resourceDTO.getTypeName());
                    reply.setFileType(resourceDTO.getFileType());
                    reply.setResourcePdfItems(resourceDTO.getResourcePdfItems());
                    reply.setResourceOfficeItemDTOs(resourceDTO.getResourceOfficeItemDTOs());
                    reply.setFileSize(resourceDTO.getFileSize());
                }
            }
        }

    }

    @Override
    @Transactional
    public void deleteCustomTimeControlById(Integer id) {
        customTimeControlMapper.deleteByPrimaryKey(id);
        customTimeControlReplyMapper.deleteByCustomTimeControlId(id);
        customTimeControlBookMapper.deleteByCustomTimeControlId(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("订阅读书计划")
    @Override
    public void subCustomTimeControlById(Integer id,String wxUserId,String robotWxId) {
        if(id==null|| StringUtil.isEmpty(wxUserId)||StringUtil.isEmpty(robotWxId)){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"参数有误！");
        }
        CustomTimeControlDTO customTimeControlDTO = customTimeControlMapper.getCustomTimeControlById(id);
        if (null == customTimeControlDTO){
            throw new BookBizException(BookBizException.PARAM_IS_EXIST,"通过id获取定制服务读书推送计划为null");
        }
        if (customTimeControlDTO.getTimeControlTaskId()==null){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"读书计划推送id为空！");
        }
        CustomTimeControlUser controlUser = customTimeControlUserMapper.getByWxIdAndControlId(wxUserId, id);
        if (controlUser!=null){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"该用户已经订阅过！");
        }
        //发送订阅成功回复
        List<CustomTimeControlReply> replyList = customTimeControlReplyMapper.getSubscribeReplyList(id);
        ThreadPoolUtils.OTHER_THREAD_POOL.execute(() -> {
            sendSubscribeReply(replyList,wxUserId,robotWxId);
        });
        //订阅时间管理
        taskSubscribeBiz.subscribeTimeControlTask(wxUserId,null,customTimeControlDTO.getTimeControlTaskId(),robotWxId);
        CustomTimeControlUser customTimeControlUser=new CustomTimeControlUser();
        customTimeControlUser.setCustomTimeControlId(id);
        customTimeControlUser.setRobotId(robotWxId);
        customTimeControlUser.setWxId(wxUserId);
        customTimeControlUserMapper.insert(customTimeControlUser);
    }

    @ParamLog("获取用户是否订阅过读书计划")
    @Override
    public Boolean getUserSub(Integer customTimeControlId, String wxUserId) {
        if(customTimeControlId==null|| StringUtil.isEmpty(wxUserId)){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"参数有误！");
        }
        CustomTimeControlUser controlUser = customTimeControlUserMapper.getByWxIdAndControlId(wxUserId, customTimeControlId);
        if (controlUser!=null){
            return true;
        }
        return false;
    }

    @ParamLog("发送订阅成功回复")
    private void sendSubscribeReply(List<CustomTimeControlReply> replyList, String userWxId, String robotId) {
        if (ListUtils.isEmpty(replyList)){
            return;
        }
        String uuid= UUID.randomUUID().toString();
        int count=replyList.size();
        RobotProcessTypeEnum robotProcessType=RobotProcessTypeEnum.CUSTOM_TIME_CONTROL_REPLY;
        String ip=getIpByRobotId(robotId);
        for (CustomTimeControlReply item:replyList){
            Integer type=item.getReplyType();
            int index=replyList.indexOf(item);
            if (ReplyTypeEnum.TEXT.value.equals(type)) {
                SendTextMessageVO sendTextMessageVO = new SendTextMessageVO();
                sendTextMessageVO.setContent(item.getContent());
                sendTextMessageVO.setAltId(robotId);
                sendTextMessageVO.setWxGroupId(userWxId);
                sendTextMessageVO.setIp(ip);
                sendTextMessageVO.setCode(SendMessageTypeEnum.SELF.getCode());
                sendTextMessageVO.setMessageGroupId(uuid);
                sendTextMessageVO.setRobotProcessType(robotProcessType);
                sendTextMessageVO.setIndex(index);
                sendTextMessageVO.setCounts(replyList.size());
                wechatGroupConsr.sendMessage(JSON.toJSONString(sendTextMessageVO));
            }
            if (ReplyTypeEnum.IMAGE.value.equals(type)) {
                SendPicMessageVO sendPicMessageVO = new SendPicMessageVO();
                sendPicMessageVO.setWxGroupId(userWxId);
                sendPicMessageVO.setAltId(robotId);
                sendPicMessageVO.setPicUrl(item.getPicUrl());
                sendPicMessageVO.setIp(ip);
                sendPicMessageVO.setCode(SendMessageTypeEnum.SELF.getCode());
                sendPicMessageVO.setMessageGroupId(uuid);
                sendPicMessageVO.setRobotProcessType(robotProcessType);
                sendPicMessageVO.setIndex(index);
                sendPicMessageVO.setCounts(replyList.size());
                wechatGroupConsr.sendMessage(JSON.toJSONString(sendPicMessageVO));
            }
            if (ReplyTypeEnum.APP.value.equals(type)) {
                AppOrProductReplyDTO appOrProductReplyDTO  = new AppOrProductReplyDTO();
                appOrProductReplyDTO.setCounts(count);
                appOrProductReplyDTO.setIndex(index);
                appOrProductReplyDTO.setIp(ip);
                appOrProductReplyDTO.setLinkUrl(item.getLinkUrl());
                appOrProductReplyDTO.setMessageGroupId(uuid);
                appOrProductReplyDTO.setRobotWxId(robotId);
                appOrProductReplyDTO.setRobotProcessTypeEnum(robotProcessType);
                appOrProductReplyDTO.setServeId(item.getServeId());
                appOrProductReplyDTO.setServeType(item.getServeType());
                appOrProductReplyDTO.setUserWxId(userWxId);
                appOrProductReplyDTO.setSendMessageType(SendMessageTypeEnum.SELF.getCode());
                pcloudRobotSet.sendAppOrProductReply(appOrProductReplyDTO);
            }
            if (ReplyTypeEnum.RESOURCE.value.equals(type)) {
                SendFileVO sendFileVO = new SendFileVO();
                Map<Long, ResourceDTO> map = resourceConsr.mapByIds(Arrays.asList(item.getResourceId()));
                ResourceDTO resourceDTO = map.get(item.getResourceId());
                if (resourceDTO != null) {
                    sendFileVO.setFileUrl(resourceDTO.getFileUrl());
                    String fileName = resourceDTO.getResourceName();
                    String fileType = resourceDTO.getFileType();
                    if (fileName.contains(fileType)){//去掉后缀
                        fileName = fileName.substring(0, fileName.indexOf(fileType)-1);
                    }
                    sendFileVO.setFileName(fileName);
                }
                sendFileVO.setIp(ip);
                sendFileVO.setAltId(robotId);
                sendFileVO.setWxId(userWxId);
                sendFileVO.setMessageGroupId(uuid);
                sendFileVO.setRobotProcessType(robotProcessType);
                sendFileVO.setIndex(index);
                sendFileVO.setCounts(replyList.size());
                wechatGroupConsr.sendMessage(JSON.toJSONString(sendFileVO));
            }
            if (ReplyTypeEnum.AUDIO.value.equals(type)) {
                SendMomentsDTO sendMomentsDTO=new SendMomentsDTO();
                Map<Long, ResourceDTO> map = resourceConsr.mapByIds(Arrays.asList(item.getResourceId()));
                ResourceDTO resourceDTO = map.get(item.getResourceId());
                if (resourceDTO != null) {
                    GroupRobotDTO info = wechatGroupConsr.getGroupRobotByRobotId(robotId);
                    if (info!=null){
                        sendMomentsDTO.setIsMasterWx(info.getMasterWx());
                        sendMomentsDTO.setReceiveAccount(info.getMac());
                    }
                    sendMomentsDTO.setMomentType(BusinessConstant.MomentTypeEnum.SEND_WX_RECORD);
                    sendMomentsDTO.setContent(userWxId);
                    sendMomentsDTO.setLink(resourceDTO.getFileUrl());
                    sendMomentsDTO.setIp(ip);
                    sendMomentsDTO.setAltId(robotId);
                    sendMomentsDTO.setWxId(userWxId);
                    sendMomentsDTO.setMessageGroupId(uuid);
                    sendMomentsDTO.setRobotProcessType(robotProcessType);
                    sendMomentsDTO.setIndex(index);
                    sendMomentsDTO.setCounts(replyList.size());
                    wechatGroupConsr.sendMessage(JSON.toJSONString(sendMomentsDTO));
                }
            }
        }
    }

    @ParamLog("获取ip")
    private String getIpByRobotId(String altId) {
        String ip = null;
        GroupRobotDTO groupRobotDTO = wechatGroupConsr.getGroupRobotByWxId(altId);
        if (null != groupRobotDTO) {
            WeixinQrcodeGeneration weixinQrcodeGeneration = weixinQrcodeGenerationDao.getByGeneration(groupRobotDTO.getVersion());
            if (null != weixinQrcodeGeneration) {
                ip = weixinQrcodeGeneration.getWechatGroupIp();
            }
        }
        return ip;
    }

    private void updateCustomTimeControl(Integer id, Integer timeControlTaskId) {
        CustomTimeControl customTimeControl = new CustomTimeControl();
        customTimeControl.setId(Long.valueOf(id.toString()));
        customTimeControl.setTimeControlTaskId(timeControlTaskId);
        customTimeControl.setUpdateTime(new Date());
        customTimeControlMapper.updateByPrimaryKeySelective(customTimeControl);

    }

    private void updateCustomTimeControlReply(Integer id, List<CustomTimeControlReply> replyList4Subscribe, List<CustomTimeControlReply> replyList4Unsubscribe) {
        customTimeControlReplyMapper.deleteByCustomTimeControlId(id);
        List<CustomTimeControlReply> customTimeControlReplies = new ArrayList<>();
        if (!ListUtils.isEmpty(replyList4Subscribe)){
            customTimeControlReplies.addAll(replyList4Subscribe);
        }
        if (!ListUtils.isEmpty(replyList4Unsubscribe)){
            customTimeControlReplies.addAll(replyList4Unsubscribe);
        }
        if (!ListUtils.isEmpty(customTimeControlReplies)){
            customTimeControlReplies.forEach(e ->e.setCustomTimeControlId(id));
            customTimeControlReplyMapper.batchInsert(customTimeControlReplies);
        }
    }

    private void updateCustomTimeControlBook(Integer id, List<CustomTimeControlBook> relatedBooks) {
        customTimeControlBookMapper.deleteByCustomTimeControlId(id);
        if (!ListUtils.isEmpty(relatedBooks)){
            relatedBooks.forEach(e -> e.setCustomTimeControlId(id));
            customTimeControlBookMapper.batchInsert(relatedBooks);
        }
    }

}
