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

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.channel.QrcodeSceneConsr;
import com.pcloud.book.consumer.content.ResourceConsr;
import com.pcloud.book.consumer.wechatgroup.WechatGroupConsr;
import com.pcloud.book.group.biz.WeixinQrcodeBiz;
import com.pcloud.book.group.enums.AppAndProductTypeEnum;
import com.pcloud.book.group.tools.SendWeixinRequestTools;
import com.pcloud.book.keywords.enums.ReplyTypeEnum;
import com.pcloud.book.pcloudkeyword.biz.PcloudKeywordBiz;
import com.pcloud.book.pcloudkeyword.enums.WelcomeReplyTypeEnum;
import com.pcloud.book.pcloudkeyword.set.PcloudRobotSet;
import com.pcloud.book.skill.biz.PcloudSkillBiz;
import com.pcloud.book.skill.check.PcloudSkillCheck;
import com.pcloud.book.skill.dao.PcloudGroupActivityDao;
import com.pcloud.book.skill.dao.PcloudResourceDao;
import com.pcloud.book.skill.dao.PcloudSkillDao;
import com.pcloud.book.skill.dao.PcloudSubReplyDao;
import com.pcloud.book.skill.entity.PcloudGroupActivity;
import com.pcloud.book.skill.entity.PcloudResource;
import com.pcloud.book.skill.entity.PcloudSkill;
import com.pcloud.book.skill.entity.PcloudSubReply;
import com.pcloud.book.skill.enums.SkillTypeEnum;
import com.pcloud.book.skill.enums.SubTypeEnum;
import com.pcloud.book.timecontrol.dto.TaskDto;
import com.pcloud.book.timecontrol.mapper.TimeControlTaskMapper;
import com.pcloud.book.util.common.ThreadPoolUtils;
import com.pcloud.channelcenter.wechat.dto.AccountSettingDto;
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.string.StringUtil;
import com.pcloud.common.utils.string.StringUtilParent;
import com.pcloud.contentcenter.resource.dto.ResourceDTO;
import com.pcloud.wechatgroup.group.dto.GroupRobotDTO;
import com.sdk.wxgroup.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Component("pcloudSkillBiz")
public class PcloudSkillBizImpl implements PcloudSkillBiz  {

    @Autowired
    private PcloudSkillDao pcloudSkillDao;
    @Autowired
    private PcloudSubReplyDao pcloudSubReplyDao;
    @Autowired
    private PcloudSkillCheck pcloudSkillCheck;
    @Autowired
    private AppConsr appConsr;
    @Autowired
    private ResourceConsr resourceConsr;
    @Autowired
    private WechatGroupConsr wechatGroupConsr;
    @Autowired
    private WeixinQrcodeBiz weixinQrcodeBiz;
    @Autowired
    private QrcodeSceneConsr qrcodeSceneConsr;
    @Autowired
    private TimeControlTaskMapper taskMapper;
    @Autowired
    private PcloudResourceDao pcloudResourceDao;
    @Autowired
    private PcloudGroupActivityDao pcloudGroupActivityDao;
    @Autowired
    private PcloudKeywordBiz pcloudKeywordBiz;
    @Autowired
    private PcloudRobotSet pcloudRobotSet;

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("新增技能")
    @Override
    public void createPcloudSkill(PcloudSkill pcloudSkill) {
        pcloudSkillCheck.createPcloudSkillCheck(pcloudSkill);
        //获取最大排序值
        Integer maxSeqNum = pcloudSkillDao.getMaxSeqNum();
        Integer seqNum=maxSeqNum+1;
        pcloudSkill.setSeqNum(seqNum);
        pcloudSkillDao.insert(pcloudSkill);
        addSuccessReplies(pcloudSkill);
        addCancelReplies(pcloudSkill);
        addNoReplies(pcloudSkill);
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("修改技能")
    @Override
    public void updatePcloudSkill(PcloudSkill pcloudSkill) {
        pcloudSkillCheck.updatePcloudSkill(pcloudSkill);
        pcloudSkillDao.update(pcloudSkill);
        //根据技能id删除订阅
        pcloudSubReplyDao.deleteByPcloudSkillId(pcloudSkill.getId());
        //新增订阅回复
        addSuccessReplies(pcloudSkill);
        addCancelReplies(pcloudSkill);
        addNoReplies(pcloudSkill);
    }

    @ParamLog("获取技能")
    @Override
    public PcloudSkill getPcloudSkill(Long id) {
        PcloudSkill pcloudSkill = pcloudSkillDao.getById(id);
        if (pcloudSkill==null){
            throw new BookBizException(BookBizException.PARAM_IS_NULL,"没找到该技能！");
        }
        List<PcloudSubReply> replies=pcloudSubReplyDao.getListByPcloudSkillId(id);
        fillRelies(replies);
        pcloudSkill.setSuccessSubReplies(replies.stream().filter(s->s!=null&& SubTypeEnum.SUCCESS.value.equals(s.getSubType())).collect(Collectors.toList()));
        pcloudSkill.setCancelSubReplies(replies.stream().filter(s->s!=null&& SubTypeEnum.CANCEL.value.equals(s.getSubType())).collect(Collectors.toList()));
        pcloudSkill.setNoSubReplies(replies.stream().filter(s->s!=null&& SubTypeEnum.NOSUBSCRIBE.value.equals(s.getSubType())).collect(Collectors.toList()));
        fillTitleAndDetail(pcloudSkill);
        return pcloudSkill;
    }

    @ParamLog("获取技能列表")
    @Override
    public PageBeanNew<PcloudSkill> getPcloudSkillList(Integer skillType, Integer currentPage, Integer numPerPage, String name) {
        if (currentPage == null || currentPage < 0) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "当前页不能为空且不能小于0！");
        }
        if (numPerPage == null || numPerPage <= 0) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "每页条数不能为空且必须大于0！");
        }
        Map<String ,Object> map=new HashMap<>();
        map.put("skillType",skillType);
        map.put("name", name);
        PageBeanNew<PcloudSkill> page = pcloudSkillDao.listPageNew(new PageParam(currentPage, numPerPage), map, "getPcloudSkillList");
        if (ListUtils.isEmpty(page.getRecordList())){
            return page;
        }
        List<Long> skillIds=page.getRecordList().stream().map(PcloudSkill::getId).collect(Collectors.toList());
        List<PcloudSubReply> replies=pcloudSubReplyDao.getListByPcloudSkillIds(skillIds);
        fillRelies(replies);
        Map<Long,List<PcloudSubReply>> replyMap=replies.stream().collect(Collectors.groupingBy(PcloudSubReply::getPcloudSkillId));
        for (PcloudSkill pcloudSkill:page.getRecordList()){
            List<PcloudSubReply> replyList=replyMap.get(pcloudSkill.getId());
            if (!ListUtils.isEmpty(replyList)){
                pcloudSkill.setSuccessSubReplies(replyList.stream().filter(s->SubTypeEnum.SUCCESS.value.equals(s.getSubType())).collect(Collectors.toList()));
                pcloudSkill.setCancelSubReplies(replyList.stream().filter(s->SubTypeEnum.CANCEL.value.equals(s.getSubType())).collect(Collectors.toList()));
                pcloudSkill.setNoSubReplies(replyList.stream().filter(s->SubTypeEnum.NOSUBSCRIBE.value.equals(s.getSubType())).collect(Collectors.toList()));
            }
        }
        fillTitleAndDetailList(page.getRecordList());
        return page;
    }

    @ParamLog("填充标题简介集合")
    private void fillTitleAndDetailList(List<PcloudSkill> list) {
        if (ListUtils.isEmpty(list)){
            return;
        }
        List<Integer> timeManageIds=new ArrayList<>();
        List<Long> readingIds=new ArrayList<>();
        List<Long> resourceIds=new ArrayList<>();
        for (PcloudSkill pcloudSkill:list){
            if (SkillTypeEnum.TIME_MANAGE.value.equals(pcloudSkill.getSkillType())){
                timeManageIds.add(pcloudSkill.getRelSkillId().intValue());
            }
            if (SkillTypeEnum.READING.value.equals(pcloudSkill.getSkillType())){
                readingIds.add(pcloudSkill.getRelSkillId());
            }
            if (SkillTypeEnum.RESOURCE.value.equals(pcloudSkill.getSkillType())){
                resourceIds.add(pcloudSkill.getRelSkillId());
            }
        }
        Map<Integer, TaskDto> taskDtoMap=new HashMap<>();
        Map<Long, PcloudGroupActivity> readingMap=new HashMap<>();
        Map<Long, PcloudResource> resourceMap=new HashMap<>();
        if (!ListUtils.isEmpty(timeManageIds)){
            taskDtoMap = taskMapper.mapByIds(timeManageIds);
        }
        if (!ListUtils.isEmpty(readingIds)){
            readingMap = pcloudGroupActivityDao.mayByIds(readingIds);
        }
        if (!ListUtils.isEmpty(resourceIds)){
            resourceMap = pcloudResourceDao.mayByIds(resourceIds);
        }
        for (PcloudSkill pcloudSkill:list){
            if (SkillTypeEnum.TIME_MANAGE.value.equals(pcloudSkill.getSkillType())){
                TaskDto taskDto = taskDtoMap.get(pcloudSkill.getRelSkillId().intValue());
                if (taskDto!=null){
                    pcloudSkill.setTitle(taskDto.getTaskName());
                    pcloudSkill.setDetail(taskDto.getTaskIntroduce());
                }
            }
            if (SkillTypeEnum.READING.value.equals(pcloudSkill.getSkillType())){
                PcloudGroupActivity pcloudGroupActivity = readingMap.get(pcloudSkill.getRelSkillId());
                if (pcloudGroupActivity!=null){
                    pcloudSkill.setTitle(pcloudGroupActivity.getName());
                    pcloudSkill.setDetail(pcloudGroupActivity.getDesc());
                }
            }
            if (SkillTypeEnum.RESOURCE.value.equals(pcloudSkill.getSkillType())){
                PcloudResource pcloudResource = resourceMap.get(pcloudSkill.getRelSkillId());
                if (pcloudResource!=null){
                    pcloudSkill.setTitle(pcloudResource.getName());
                    pcloudSkill.setDetail(pcloudResource.getDescription());
                }
            }
            if(null != pcloudSkill){
                String filterStr = StringUtilParent.replaceHtml(pcloudSkill.getDetail());
                //String subStr = filterStr.length() > 100 ? filterStr.substring(0, 100) + "..." : filterStr;
                pcloudSkill.setDetailString(filterStr);
            }
        }
    }

    @ParamLog("填充标题简介集合")
    private void fillTitleAndDetail(PcloudSkill pcloudSkill) {

        if (SkillTypeEnum.TIME_MANAGE.value.equals(pcloudSkill.getSkillType())){
            Map<Integer, TaskDto> taskDtoMap = taskMapper.mapByIds(Arrays.asList(pcloudSkill.getRelSkillId().intValue()));
            TaskDto taskDto=taskDtoMap.get(pcloudSkill.getRelSkillId().intValue());
            if (taskDto!=null){
                pcloudSkill.setTitle(taskDto.getTaskName());
                pcloudSkill.setDetail(taskDto.getTaskIntroduce());
            }
        }
        if (SkillTypeEnum.READING.value.equals(pcloudSkill.getSkillType())){
            Map<Long, PcloudGroupActivity> activityMap = pcloudGroupActivityDao.mayByIds(Arrays.asList(pcloudSkill.getRelSkillId()));
            PcloudGroupActivity groupActivity = activityMap.get(pcloudSkill.getRelSkillId());
            if (groupActivity!=null){
                pcloudSkill.setTitle(groupActivity.getName());
                pcloudSkill.setDetail(groupActivity.getDesc());
            }
        }
        if (SkillTypeEnum.RESOURCE.value.equals(pcloudSkill.getSkillType())){
            Map<Long, PcloudResource> resourceMap = pcloudResourceDao.mayByIds(Arrays.asList(pcloudSkill.getRelSkillId()));
            PcloudResource pcloudResource=resourceMap.get(pcloudSkill.getRelSkillId());
            if (pcloudResource!=null){
                pcloudSkill.setTitle(pcloudResource.getName());
                pcloudSkill.setDetail(pcloudResource.getDescription());
            }
        }
        if(null != pcloudSkill){
            String filterStr = StringUtilParent.replaceHtml(pcloudSkill.getDetail());
            //String subStr = filterStr.length() > 100 ? filterStr.substring(0, 100) + "..." : filterStr;
            pcloudSkill.setDetailString(filterStr);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("删除技能")
    @Override
    public void deletePcloudSkill(Long id) {
        if (id==null){
            throw new BookBizException(BookBizException.PARAM_IS_NULL,"参数为空！");
        }
        //判断是否被关键词引用
        Boolean hasKeyword = pcloudKeywordBiz.skillExist(id);
        if (hasKeyword){
            throw new BookBizException(BookBizException.PARAM_IS_NULL,"该技能已被关键词引用！");
        }
        pcloudSkillDao.deleteById(id);
        pcloudSubReplyDao.deleteByPcloudSkillId(id);
    }

    @Override
    @ParamLog("订阅或取消订阅")
    public String setSubscribeState(Long skillId, Integer taskId, String robotWxId, String userWxId, Boolean subState) {
        PcloudSkill skill = pcloudSkillDao.getById(skillId);
        if(skill == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "技能不存在，订阅失败!");
        }
        ThreadPoolUtils.OTHER_THREAD_POOL.execute(() -> {
            // TODO 时间管理任务添加订阅或取消

            // 发送订阅回复信息
            List<PcloudSubReply> replyList = pcloudSubReplyDao.getListByPcloudSkillId(skillId);
            List<PcloudSubReply> subReplyList;
            if(subState) {
                subReplyList = replyList.stream().filter(s->SubTypeEnum.SUCCESS.value.equals(s.getSubType())).collect(Collectors.toList());
            } else {
                subReplyList = replyList.stream().filter(s->SubTypeEnum.CANCEL.value.equals(s.getSubType())).collect(Collectors.toList());
            }
            this.sendSubReplyMessage(subReplyList, robotWxId, userWxId);
        });

        return skill.getSkillFuseReply();
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("修改排序值")
    @Override
    public void updateSeqNum(PcloudSkill pcloudSkill) {
        if (pcloudSkill.getId()==null||pcloudSkill.getSeqNum()==null){
            throw new BookBizException(BookBizException.PARAM_IS_NULL,"id和排序值不能为空！");
        }
        pcloudSkillDao.updateSeqNum(pcloudSkill.getId(),pcloudSkill.getSeqNum());
    }

    @Override
    public void sendResource(Integer id, String wxUserId, String robotId, Integer relSkillId) {
        PcloudSkill skill = pcloudSkillDao.getById(id);
        if(skill == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "技能不存在，订阅失败!");
        }
        ThreadPoolUtils.OTHER_THREAD_POOL.execute(() -> {
            // 发送订阅回复信息
            List<PcloudSubReply> replyList = pcloudSubReplyDao.getListByPcloudSkillId(skill.getId());
            List<PcloudSubReply> subReplyList;
             subReplyList = replyList.stream().filter(s->SubTypeEnum.SUCCESS.value.equals(s.getSubType())).collect(Collectors.toList());
            this.sendSubReplyMessage(subReplyList, robotId, wxUserId);
        });
    }

    @Override
    public  PageBeanNew<PcloudSkill> getPcloudSkillList4Select(
            Integer skillType, Integer currentPage, Integer numPerPage, String name,
            Long depLabelId, Long proLabelId, Long purLabelId) {
        if (currentPage == null || currentPage < 0) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "当前页不能为空且不能小于0！");
        }
        if (numPerPage == null || numPerPage <= 0) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "每页条数不能为空且必须大于0！");
        }
        Map<String ,Object> map=new HashMap<>();
        map.put("skillType",skillType);
        map.put("name", name);
        map.put("depLabelId", depLabelId);
        map.put("proLabelId", proLabelId);
        map.put("purLabelId", purLabelId);
        PageBeanNew<PcloudSkill> page = pcloudSkillDao.listPageNew(new PageParam(currentPage, numPerPage), map, "getPcloudSkillList4Select");
        if (ListUtils.isEmpty(page.getRecordList())){
            return page;
        }
        fillTitleAndDetailList(page.getRecordList());
        return page;
    }

    @Override
    public PcloudSkill getPcloudSkillBaseInfoById(Long id) {
        return pcloudSkillDao.getById(id);
    }

    @ParamLog("填充订阅回复")
    private void fillRelies(List<PcloudSubReply> replies) {
        if (ListUtils.isEmpty(replies)){
            return;
        }
        List<Long> appIds=new ArrayList<>();
        List<Long> resourceIds=new ArrayList<>();
        for (PcloudSubReply reply:replies){
            Integer type=reply.getType();
            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 (PcloudSubReply reply:replies){
            Integer type=reply.getType();
            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());
                }
            }
        }


    }

    @ParamLog("新增订阅回复")
    private void addSuccessReplies(PcloudSkill pcloudSkill){
        List<PcloudSubReply> successReplies = pcloudSkill.getSuccessSubReplies();
        if (ListUtils.isEmpty(successReplies)){
            return;
        }
        for (PcloudSubReply reply:successReplies){
            reply.setPcloudSkillId(pcloudSkill.getId());
        }
        pcloudSubReplyDao.batchInsert(successReplies);
    }
    @ParamLog("新增取消订阅回复")
    private void addCancelReplies(PcloudSkill pcloudSkill){
        List<PcloudSubReply> cancelReplies = pcloudSkill.getCancelSubReplies();
        if (ListUtils.isEmpty(cancelReplies)){
            return;
        }
        for (PcloudSubReply reply:cancelReplies){
            reply.setPcloudSkillId(pcloudSkill.getId());
        }
        pcloudSubReplyDao.batchInsert(cancelReplies);
    }
    @ParamLog("新增未订阅回复")
    private void addNoReplies(PcloudSkill pcloudSkill){
        List<PcloudSubReply> noSubReplies = pcloudSkill.getNoSubReplies();
        if (ListUtils.isEmpty(noSubReplies)){
            return;
        }
        for (PcloudSubReply reply:noSubReplies){
            reply.setPcloudSkillId(pcloudSkill.getId());
        }
        pcloudSubReplyDao.batchInsert(noSubReplies);
    }
    private void sendSubReplyMessage(List<PcloudSubReply> subReplyList, String robotWxId, String userWxId) {
        this.fillRelies(subReplyList);
        for(PcloudSubReply reply : subReplyList) {
            Integer type = reply.getType();
            GroupRobotDTO groupRobotDTO = wechatGroupConsr.getGroupRobotByWxId(robotWxId);
            String ip = weixinQrcodeBiz.getRobotIpByGeneration(groupRobotDTO.getVersion());
            if(WelcomeReplyTypeEnum.TEXT.value.equals(type)) {
                SendTextMessageVO sendTextMessageVO = new SendTextMessageVO();
                sendTextMessageVO.setContent(reply.getContent());
                sendTextMessageVO.setAltId(robotWxId);
                sendTextMessageVO.setWxGroupId(userWxId);
                sendTextMessageVO.setIp(ip);
                sendTextMessageVO.setCode(SendMessageTypeEnum.SELF.getCode());
                WxGroupSDK.sendTextMessage(sendTextMessageVO);
            } else if(WelcomeReplyTypeEnum.IMAGE.value.equals(type)) {
                SendPicMessageVO sendPicMessageVO = new SendPicMessageVO();
                sendPicMessageVO.setWxGroupId(userWxId);
                sendPicMessageVO.setAltId(robotWxId);
                sendPicMessageVO.setPicUrl(reply.getPicUrl());
                sendPicMessageVO.setIp(ip);
                sendPicMessageVO.setCode(SendMessageTypeEnum.SELF.getCode());
                WxGroupSDK.sendPicMessage(sendPicMessageVO);
            } else if(WelcomeReplyTypeEnum.RESOURCE.value.equals(type)) {
                SendFileVO sendFileVO = new SendFileVO();
                sendFileVO.setFileUrl(reply.getResourceUrl());
                if (!StringUtil.isEmpty(reply.getResourceName())){
                    sendFileVO.setFileName(reply.getResourceName().substring(0,reply.getResourceName().lastIndexOf(".")));
                }
                sendFileVO.setIp(ip);
                sendFileVO.setAltId(robotWxId);
                sendFileVO.setWxId(userWxId);
                sendFileVO.setCode(SendMessageTypeEnum.SELF.getCode());
                WxGroupSDK.sendFile(sendFileVO);
            } else if(ReplyTypeEnum.APP.value.equals(type)) {
                pcloudRobotSet.sendAppOrProductReply(reply.getServeType(), reply.getServeId(),
                        reply.getLinkUrl(), robotWxId,userWxId, ip, SendMessageTypeEnum.SELF.getCode());
            }
        }
    }

}
