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

import com.google.common.util.concurrent.ThreadFactoryBuilder;
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.resource.ProductConsr;
import com.pcloud.book.consumer.wechatgroup.WechatGroupConsr;
import com.pcloud.book.group.biz.WeixinQrcodeBiz;
import com.pcloud.book.keywords.entity.RobotSkillDetail;
import com.pcloud.book.keywords.enums.ReplyTypeEnum;
import com.pcloud.book.pcloudkeyword.set.PcloudRobotSet;
import com.pcloud.book.personal.dao.PcloudSkillRecordDao;
import com.pcloud.book.skill.biz.PcloudSubRemindBiz;
import com.pcloud.book.skill.dao.PcloudSkillDao;
import com.pcloud.book.skill.dao.PcloudSubReplyDao;
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.biz.TaskBiz;
import com.pcloud.book.timecontrol.biz.TaskSubscribeBiz;
import com.pcloud.book.timecontrol.dto.ReplyMessageBaseDto;
import com.pcloud.book.timecontrol.dto.TaskSendDto;
import com.pcloud.book.timecontrol.entity.TimeControlReplyMessage;
import com.pcloud.book.timecontrol.entity.TimeControlTask;
import com.pcloud.book.timecontrol.entity.TimeControlTaskItem;
import com.pcloud.book.timecontrol.entity.TimeControlTaskSend;
import com.pcloud.book.timecontrol.entity.TimeControlTaskSubscribe;
import com.pcloud.book.timecontrol.enums.TaskSendStateEnum;
import com.pcloud.book.timecontrol.enums.TaskSubscribeStateEnum;
import com.pcloud.book.timecontrol.mapper.TimeControlReplyMessageMapper;
import com.pcloud.book.timecontrol.mapper.TimeControlTaskItemMapper;
import com.pcloud.book.timecontrol.mapper.TimeControlTaskMapper;
import com.pcloud.book.timecontrol.mapper.TimeControlTaskSendMapper;
import com.pcloud.book.timecontrol.mapper.TimeControlTaskSubscribeMapper;
import com.pcloud.book.util.common.YesOrNoEnums;
import com.pcloud.channelcenter.base.constants.ChannelConstants;
import com.pcloud.channelcenter.wechat.dto.AccountSettingDto;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.page.PageBeanNew;
import com.pcloud.common.utils.DateUtils;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.httpclient.UrlUtils;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.contentcenter.resource.dto.ResourceDTO;
import com.pcloud.wechatgroup.group.dto.GroupRobotDTO;
import com.sdk.wxgroup.SendArticleMessageVO;
import com.sdk.wxgroup.SendFileVO;
import com.sdk.wxgroup.SendMessageTypeEnum;
import com.sdk.wxgroup.SendPicMessageVO;
import com.sdk.wxgroup.SendTextMessageVO;
import com.sdk.wxgroup.WxGroupSDK;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @date: 2020年01月31日 20:12
 * @Author: Zcy
 * @Descprition
 */
@Component("taskSubscribeBiz")
public class TaskSubscribeBizImpl implements TaskSubscribeBiz {

    private final static Logger LOGGER = LoggerFactory.getLogger(TaskSubscribeBizImpl.class);

    private static final ThreadFactory NAMED_THREAD_FACTORY = new ThreadFactoryBuilder()
            .setNameFormat("attendancetask-cashbak-pool-%d").build();

    private static final ExecutorService EXECUTOR_SERVICE = new ThreadPoolExecutor(5, 10, 0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(1024), NAMED_THREAD_FACTORY, new ThreadPoolExecutor.CallerRunsPolicy());

    @Autowired
    private TimeControlTaskSubscribeMapper taskSubscribeMapper;
    @Autowired
    private TimeControlTaskItemMapper taskItemMapper;
    @Autowired
    private TimeControlReplyMessageMapper replyMessageMapper;
    @Autowired
    private TimeControlTaskSendMapper timeControlTaskSendMapper;
    @Autowired
    private WechatGroupConsr wechatGroupConsr;
    @Autowired
    private AppConsr appConsr;
    @Autowired
    private QrcodeSceneConsr qrcodeSceneConsr;
    @Autowired
    private TimeControlTaskMapper taskMapper;
    @Autowired
    private ProductConsr productConsr;
    @Autowired
    private WeixinQrcodeBiz weixinQrcodeBiz;
    @Autowired
    private PcloudSkillDao pcloudSkillDao;
    @Autowired
    private PcloudSubReplyDao pcloudSubReplyDao;
    @Autowired
    private ResourceConsr resourceConsr;
    @Autowired
    private PcloudSubRemindBiz pcloudSubRemindBiz;
    @Value("${wechat.group.link.prefix}")
    private String wechatGroupLinkPrefix;
    @Autowired
    private PcloudRobotSet pcloudRobotSet;
    @Autowired
    private PcloudSkillRecordDao pcloudSkillRecordDao;
    @Autowired
    private TaskBiz taskBiz;

    @Override
    @ParamLog("任务订阅")
    public void subscribeTask(String wxUserId, Long bookId, Integer taskId, String robotWxId) {
        //更新技能记录列表状态
        List<Long> skillIds = pcloudSkillDao.getListByRelId(taskId);
        if (!ListUtils.isEmpty(skillIds)){
            pcloudSkillRecordDao.batchUpdateState4ResourceAndActivity(wxUserId,skillIds,1);
        }
        TimeControlTask timeControlTask = taskMapper.selectByPrimaryKey(taskId);
        if (null == timeControlTask) {
            return;
        }
        TimeControlTaskSubscribe taskSubscribe = taskSubscribeMapper.getSubscribe(wxUserId, bookId, taskId);
        if (null != taskSubscribe) {
            if (TaskSubscribeStateEnum.FINISH.getState().equals(taskSubscribe.getState())) {
                LOGGER.info("任务已完成，直接返回");
                return;
            } else if (TaskSubscribeStateEnum.SUBSCRIBE.getState().equals(taskSubscribe.getState())) {
                LOGGER.info("任务已订阅，直接返回");
                return;
            } else {
                //1.改状态
                taskSubscribeMapper.subscribeTaskExist(taskSubscribe);
            }
        } else {
            taskSubscribe = new TimeControlTaskSubscribe();
            taskSubscribe.setWxUserId(wxUserId);
            taskSubscribe.setBookId(bookId);
            taskSubscribe.setTaskId(taskId);
            taskSubscribe.setState(TaskSubscribeStateEnum.SUBSCRIBE.getState());
            taskSubscribe.setRobotWxId(robotWxId);
            taskSubscribeMapper.subscribeTask(taskSubscribe);
        }
        //插入待发送记录
        List<ReplyMessageBaseDto> dayList = taskItemMapper.listTaskItemDay(taskId);
        List<TimeControlTaskSend> taskSendList = new ArrayList<>();
        if (!ListUtils.isEmpty(dayList)) {
            for (ReplyMessageBaseDto item : dayList) {
                TimeControlTaskSend taskSend = new TimeControlTaskSend();
                taskSend.setWxUserId(wxUserId);
                taskSend.setBookId(bookId);
                taskSend.setTaskId(taskId);
                taskSend.setSubscribeId(taskSubscribe.getId());
                taskSend.setSendState(TaskSendStateEnum.WAIT_SEND.state);
                taskSend.setTaskItemId(item.getId());
                taskSend.setSendDay(DateUtils.getShortDateStr(DateUtils.addDay(new Date(), item.getStartDay())));
                taskSend.setSendHour(item.getSendHour());
                taskSendList.add(taskSend);
            }
            LOGGER.info("111");
            timeControlTaskSendMapper.batchInsert(taskSendList);
        }
        //订阅成功个人号回复消息
        EXECUTOR_SERVICE.execute(() -> {
            PcloudSkill pcloudSkill = pcloudSkillDao.getByRelId(taskId, SkillTypeEnum.TIME_MANAGE.value);
            if (null == pcloudSkill) {
                return;
            }
            List<PcloudSubReply> bySkillIdAndType = pcloudSubReplyDao.getBySkillIdAndType(pcloudSkill.getId(), SubTypeEnum.SUCCESS.value);
            GroupRobotDTO groupRobotDTO = wechatGroupConsr.getGroupRobotByWxId(robotWxId);
            String ip = weixinQrcodeBiz.getRobotIpByGeneration(groupRobotDTO.getVersion());
            if (!ListUtils.isEmpty(bySkillIdAndType)) {
                bySkillIdAndType.forEach(pcloudSubReply -> {
                    sendReply(pcloudSubReply, wxUserId, robotWxId, ip);
                });
            }
        });
        //修改pcloud_sub_remind表状态
        pcloudSubRemindBiz.updateSubState(taskId,SkillTypeEnum.TIME_MANAGE.value,wxUserId,null);
        LOGGER.info("222");
    }

    @ParamLog
    private void sendReply(PcloudSubReply pcloudSubReply, String userWxId, String robotWxId, String ip) {
        Integer type = pcloudSubReply.getType();
        if (ReplyTypeEnum.TEXT.value.equals(type)) {
            SendTextMessageVO sendTextMessageVO = new SendTextMessageVO();
            sendTextMessageVO.setContent(pcloudSubReply.getContent());
            sendTextMessageVO.setAltId(robotWxId);
            sendTextMessageVO.setWxGroupId(userWxId);
            sendTextMessageVO.setIp(ip);
            sendTextMessageVO.setCode(1);
            WxGroupSDK.sendTextMessage(sendTextMessageVO);
        }
        if (ReplyTypeEnum.IMAGE.value.equals(type)) {
            SendPicMessageVO sendPicMessageVO = new SendPicMessageVO();
            sendPicMessageVO.setWxGroupId(userWxId);
            sendPicMessageVO.setAltId(robotWxId);
            sendPicMessageVO.setPicUrl(pcloudSubReply.getPicUrl());
            sendPicMessageVO.setIp(ip);
            sendPicMessageVO.setCode(1);
            WxGroupSDK.sendPicMessage(sendPicMessageVO);
        }
        if (ReplyTypeEnum.APP.value.equals(type)) {
            pcloudRobotSet.sendAppOrProductReply(pcloudSubReply.getServeType(), pcloudSubReply.getServeId(),
                    pcloudSubReply.getLinkUrl(), robotWxId, userWxId, ip, 1);
        }
        if (ReplyTypeEnum.LINK.value.equals(type)) {
            SendArticleMessageVO sendArticleMessageVO = new SendArticleMessageVO();
            sendArticleMessageVO.setCode(1);
            sendArticleMessageVO.setAltId(robotWxId);
            sendArticleMessageVO.setDescription(pcloudSubReply.getDescription());
            sendArticleMessageVO.setWxGroupId(userWxId);
            sendArticleMessageVO.setLinkUrl(pcloudSubReply.getLinkUrl());
            sendArticleMessageVO.setPicUrl(pcloudSubReply.getPicUrl());
            sendArticleMessageVO.setTitle(pcloudSubReply.getContent());
            sendArticleMessageVO.setIp(ip);
            WxGroupSDK.sendArticleMessage(sendArticleMessageVO);
        }
        if (ReplyTypeEnum.RESOURCE.value.equals(type)) {
            SendFileVO sendFileVO = new SendFileVO();
            Map<Long, ResourceDTO> map = resourceConsr.mapByIds(Arrays.asList(pcloudSubReply.getResourceId()));
            ResourceDTO resourceDTO = map.get(pcloudSubReply.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(robotWxId);
            sendFileVO.setWxId(userWxId);
            WxGroupSDK.sendFile(sendFileVO);
        }
    }

    @Override
    @ParamLog("取消订阅")
    public void unSubscribeTask(String wxUserId, Long bookId, Integer taskId) {
        //更新技能记录列表状态
        List<Long> skillIds = pcloudSkillDao.getListByRelId(taskId);
        if (!ListUtils.isEmpty(skillIds)){
            pcloudSkillRecordDao.batchUpdateState4ResourceAndActivity(wxUserId,skillIds,2);
        }
        TimeControlTask timeControlTask = taskMapper.selectByPrimaryKey(taskId);
        if (null == timeControlTask) {
            return;
        }
        TimeControlTaskSubscribe taskSubscribe = taskSubscribeMapper.getSubscribe(wxUserId, bookId, taskId);
        LOGGER.info("taskSubscribe = " + taskSubscribe);
        if (null != taskSubscribe && TaskSubscribeStateEnum.SUBSCRIBE.getState().equals(taskSubscribe.getState())) {
            taskSubscribe.setState(TaskSubscribeStateEnum.UNSUBSCRIBE.getState());
            taskSubscribeMapper.unSubscribeTask(taskSubscribe);
            //取消订阅的同时需要取消待发送的任务
            timeControlTaskSendMapper.cancelSend(taskSubscribe.getId(), TaskSendStateEnum.CANCEL.getState());
            //取消订阅个人号回复消息
            EXECUTOR_SERVICE.execute(() -> {
                PcloudSkill pcloudSkill = pcloudSkillDao.getByRelId(taskId, SkillTypeEnum.TIME_MANAGE.value);
                if (null == pcloudSkill) {
                    return;
                }
                List<PcloudSubReply> bySkillIdAndType = pcloudSubReplyDao.getBySkillIdAndType(pcloudSkill.getId(), SubTypeEnum.CANCEL.value);
                GroupRobotDTO groupRobotDTO = wechatGroupConsr.getGroupRobotByWxId(taskSubscribe.getRobotWxId());
                String ip = weixinQrcodeBiz.getRobotIpByGeneration(groupRobotDTO.getVersion());
                if (!ListUtils.isEmpty(bySkillIdAndType)) {
                    bySkillIdAndType.forEach(pcloudSubReply -> {
                        sendReply(pcloudSubReply, wxUserId, taskSubscribe.getRobotWxId(), ip);
                    });
                }
            });
        }
    }

    @Override
    public void listTodayTask() {

    }

    @Override
    public void sendTimeTaskMessage() {
        List<TaskSendDto> taskSendList = timeControlTaskSendMapper.listTodayTask();
        if(ListUtils.isEmpty(taskSendList)){
            return;
        }
        Map<String, List<TaskSendDto>> collect = taskSendList.stream().collect(Collectors.groupingBy(taskSendDto -> taskSendDto.getWxUserId() + "_" + taskSendDto.getTaskId()));
        for (String s : collect.keySet()) {
            sendTaskMsg(collect.get(s));
        }
    }

    private void sendTaskMsg(List<TaskSendDto> taskSendList) {
        // 判断是否处理过
        boolean success = false;
        int count = 0;
        for(TaskSendDto sendDto : taskSendList) {
            count++;
            Integer taskItemId = sendDto.getTaskItemId();
            TimeControlTaskItem timeControlTaskItem = taskItemMapper.selectByPrimaryKey(taskItemId);
            if (null == timeControlTaskItem) {
                continue;
            }
            List<TimeControlReplyMessage> replyMessages = replyMessageMapper.list4TaskItem(sendDto.getTaskItemId(), 0);
            String robotWxId = sendDto.getRobotWxId();
            String wxUserId = sendDto.getWxUserId();
            GroupRobotDTO groupRobotDTO = wechatGroupConsr.getGroupRobotByWxId(robotWxId);
            String ip = weixinQrcodeBiz.getRobotIpByGeneration(groupRobotDTO.getVersion());
            Integer taskSendId = sendDto.getId();
            TimeControlTaskSend timeControlTaskSend = timeControlTaskSendMapper.getById(taskSendId);
            taskBiz.sendReplyMessage(replyMessages, wxUserId, robotWxId, ip);
            if(YesOrNoEnums.YES.getValue().equals(timeControlTaskItem.getAddSendTime())){
                //封装退订提醒
                SendTextMessageVO sendTextMessageVO = new SendTextMessageVO();
                sendTextMessageVO.setCode(SendMessageTypeEnum.SELF.getCode());
                sendTextMessageVO.setWxId(robotWxId);
                sendTextMessageVO.setAltId(robotWxId);
                sendTextMessageVO.setWxGroupId(wxUserId);
                sendTextMessageVO.setIp(ip);
                String content = "消息发送时间(" + DateUtils.formatDate(new Date())+")";
                sendTextMessageVO.setContent(content);
                WxGroupSDK.sendTextMessage(sendTextMessageVO);
            }
            if (YesOrNoEnums.YES.getValue().equals(timeControlTaskItem.getFinishConfirm()) || YesOrNoEnums.YES.getValue().equals(timeControlTaskItem.getTdConfirm())){
                //封装退订提醒
                SendTextMessageVO sendTextMessageVO = new SendTextMessageVO();
                sendTextMessageVO.setCode(SendMessageTypeEnum.SELF.getCode());
                sendTextMessageVO.setWxId(robotWxId);
                sendTextMessageVO.setAltId(robotWxId);
                sendTextMessageVO.setWxGroupId(wxUserId);
                sendTextMessageVO.setIp(ip);
                String content = "";
                if (YesOrNoEnums.YES.getValue().equals(timeControlTaskItem.getFinishConfirm())) {
                    String finishLinkUrl = timeControlTaskItem.getFinishLinkUrl();
                    if (finishLinkUrl != null) {
                        String baseUrl = wechatGroupLinkPrefix + "/link?";
                        finishLinkUrl = baseUrl + "wxId=" +wxUserId+"&taskSendId=" +taskSendId+"&url=" + URLEncoder.encode(finishLinkUrl);
                        String resultUrl = UrlUtils.getShortUrl4Own(finishLinkUrl);
                         content = content + timeControlTaskItem.getFinishLinkIntroduce() + "\n" + resultUrl;
                    }
                }
                if (YesOrNoEnums.YES.getValue().equals(timeControlTaskItem.getTdConfirm())) {
                    if (StringUtil.isEmpty(content)) {
                        content = content + "如需退订，请回复 TD" + sendDto.getTaskId();
                    }else {
                        content = content + "\n如需退订，请回复 TD" + sendDto.getTaskId();
                    }
                }
                sendTextMessageVO.setContent(content);
                WxGroupSDK.sendTextMessage(sendTextMessageVO);
            }
            if (YesOrNoEnums.YES.getValue().equals(timeControlTaskItem.getProgressGuidance())) {
                //封装任务进度
                SendTextMessageVO sendTextMessageVO = new SendTextMessageVO();
                sendTextMessageVO.setCode(SendMessageTypeEnum.SELF.getCode());
                sendTextMessageVO.setWxId(robotWxId);
                sendTextMessageVO.setAltId(robotWxId);
                sendTextMessageVO.setWxGroupId(wxUserId);
                sendTextMessageVO.setIp(ip);
                String link = wechatGroupLinkPrefix + "/time/task?taskId=" + timeControlTaskItem.getTaskId()
                        + "&taskItemId=" + taskItemId + "&wxUserId=" + wxUserId;
                String content = "当前任务进度→\n" + UrlUtils.getShortUrl4Own(link) + "";
                sendTextMessageVO.setContent(content);
                WxGroupSDK.sendTextMessage(sendTextMessageVO);
            }
            //更新发送状态
            Integer completeState = null;
            if (!YesOrNoEnums.YES.getValue().equals(timeControlTaskItem.getFinishConfirm())) {
                completeState = 1;
            }
            timeControlTaskSendMapper.updateSendState(sendDto.getId(), TaskSendStateEnum.FINISH_SEND.getState(), completeState);

            //每次都要判断一下是否所有单项任务都完成。完成之后需要同步修改关注表里面完成状态
            if(count==taskSendList.size()) {
                Integer noCompletedItem = timeControlTaskSendMapper.getNoCompletedCount(timeControlTaskSend.getSubscribeId());
                if (noCompletedItem == 0) {
                    taskSubscribeMapper.completedTaskById(timeControlTaskSend.getSubscribeId());
                }
            }
        }
    }

    @Override
    public TimeControlTaskSubscribe getSubscribeState(String wxUserId, Integer taskId) {
        TimeControlTaskSubscribe timeControlTaskSubscribe = taskSubscribeMapper.getSubscribe(wxUserId, null, taskId);
        if (null == timeControlTaskSubscribe) {
            timeControlTaskSubscribe = new TimeControlTaskSubscribe();
            timeControlTaskSubscribe.setTaskId(taskId);
            timeControlTaskSubscribe.setState(TaskSubscribeStateEnum.UNSUBSCRIBE.getState());
            timeControlTaskSubscribe.setWxUserId(wxUserId);
        }
        return timeControlTaskSubscribe;
    }

    private String splitUrl(AccountSettingDto accountSettingDto, String url) {
        String protocol = accountSettingDto.getProtocol();
        if (StringUtils.isEmpty(protocol)) {
            protocol = ChannelConstants.HTTP;
        }
        String resultUrl = "";
        if (!StringUtils.isEmpty(url)) {
            if (url.startsWith("http")) {
                return url;
            }
            if (url.startsWith("*")) {
                String endUrl = url.substring(url.indexOf("/"));
                if (accountSettingDto.getRandom() == null) {
                    resultUrl = protocol + "app." + accountSettingDto.getFirstDomain() + "/" + url.substring(1, url.indexOf("/")) + "/W"
                            + accountSettingDto.getAccountSettingId() + endUrl;
                } else {
                    resultUrl = protocol + "app" + accountSettingDto.getRandom() + "." + accountSettingDto.getFirstDomain() + "/" + url.substring(1, url.indexOf("/")) + "/W"
                            + accountSettingDto.getAccountSettingId() + endUrl;
                }
            } else {
                resultUrl = protocol + accountSettingDto.getDomain() + "/W" + accountSettingDto.getAccountSettingId() + url;
            }
        }
        return resultUrl;
    }
}
