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

import com.pcloud.book.consumer.wechatgroup.WechatGroupConsr;
import com.pcloud.book.group.dao.BookGroupCipherUserDao;
import com.pcloud.book.group.dao.BookGroupDao;
import com.pcloud.book.group.dao.WeixinQrcodeGenerationDao;
import com.pcloud.book.group.dto.BookGroupDTO;
import com.pcloud.book.group.dto.SelfRobotBookGroupDTO;
import com.pcloud.book.group.entity.WeixinQrcodeGeneration;
import com.pcloud.book.group.set.GroupSet;
import com.pcloud.book.group.tools.SendSelfMsgTools;
import com.pcloud.book.group.vo.UserBookInfoVO;
import com.pcloud.book.push.biz.SelfPushBiz;
import com.pcloud.book.push.constant.PushConstant;
import com.pcloud.book.push.dao.SelfPushDao;
import com.pcloud.book.push.dao.SelfPushItemDao;
import com.pcloud.book.push.dao.SelfPushUserDao;
import com.pcloud.book.push.dto.SelfPushAddParamDTO;
import com.pcloud.book.push.dto.SelfPushRecordDTO;
import com.pcloud.book.push.entity.SelfPush;
import com.pcloud.book.push.entity.SelfPushItem;
import com.pcloud.book.push.entity.SelfPushUser;
import com.pcloud.book.push.enums.ItemTypeEnum;
import com.pcloud.book.push.enums.PushStatusEnum;
import com.pcloud.book.util.common.ThreadPoolUtils;
import com.pcloud.common.core.constant.SystemCode;
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.string.StringUtil;
import com.pcloud.facade.quartz.entity.CallBackParam;
import com.pcloud.facade.quartz.entity.ScheduleJob;
import com.pcloud.facade.quartz.service.ScheduleService;
import com.pcloud.wechatgroup.group.dto.GroupRobotDTO;
import com.pcloud.wechatgroup.group.dto.GroupUserDTO;
import com.sdk.wxgroup.SendArticleMessageVO;
import com.sdk.wxgroup.SendMessageTypeEnum;
import com.sdk.wxgroup.SendPicMessageVO;
import com.sdk.wxgroup.SendTextMessageVO;
import com.sdk.wxgroup.WxGroupSDK;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.stream.Collectors;

import lombok.extern.slf4j.Slf4j;

/**
 * @描述：个人号群发
 * @作者：zhuyajie
 * @创建时间：11:00 2019/11/27
 * @版本：1.0
 */
@Slf4j
@Component("selfPushBiz")
public class SelfPushBizImpl implements SelfPushBiz {

    @Autowired
    private SelfPushDao selfPushDao;
    @Autowired
    private SelfPushItemDao selfPushItemDao;
    @Autowired
    private SelfPushUserDao selfPushUserDao;
    @Autowired
    private GroupSet groupSet;
    @Autowired
    private WechatGroupConsr wechatGroupConsr;
    @Autowired
    private WeixinQrcodeGenerationDao weixinQrcodeGenerationDao;
    @Autowired
    private ScheduleService scheduleService;
    @Autowired
    private BookGroupCipherUserDao bookGroupCipherUserDao;
    @Value("${system.env}")
    private String envStr;
    @Autowired
    private BookGroupDao bookGroupDao;

    @Override
    public void createSelfPush(Long partyId, SelfPushAddParamDTO addParamDTO) {
        Boolean sendNow = addParamDTO.getSendNow();
        //群发
        SelfPush selfPush = new SelfPush();
        selfPush.setCreateUser(partyId);
        selfPush.setUpdateUser(partyId);
        if (SystemCode.adviser.code.equalsIgnoreCase(addParamDTO.getSystemCode())){
            selfPush.setBookGroupId(addParamDTO.getBookGroupId());
        }
        if (SystemCode.pcloud.code.equalsIgnoreCase(addParamDTO.getSystemCode())){
            selfPush.setAltId(addParamDTO.getAltId());
        }
        selfPush.setSendNow(sendNow);
        if (sendNow) {
            selfPush.setSendTime(new Date());
        } else {
            selfPush.setSendTime(DateUtils.getDateByStr(addParamDTO.getSendTime()));
        }
        selfPushDao.insert(selfPush);
        Long pushId = selfPush.getId();
        //群发项
        List<SelfPushItem> itemList = addParamDTO.getPushItemList();
        setSelfPushItem(pushId, sendNow, partyId, itemList, selfPush.getSendTime());
        //群发用户
        List<String> userIdList = addParamDTO.getUserIdList();
        setSelfPushUser(userIdList, partyId, pushId);
        if (sendNow) {
            //微信立即发送
            msgPush(userIdList, itemList, pushId);
        } else {
            //定时任务
            addSendQuartzJob(pushId, addParamDTO.getSendTime());
        }
    }

    /**
     * 添加定时任务
     */
    private void addSendQuartzJob(Long pushId, String sendTime) {
        ScheduleJob scheduleJob = new ScheduleJob();
        CallBackParam callBackParam = new CallBackParam();
        Map<String, Object> map = new HashMap<>();
        map.put("pushId", pushId);
        scheduleJob.setJobGroup(PushConstant.JOB_GROUP_SELF_PUSH);
        scheduleJob.setJobName(PushConstant.JOB_NAME_SELF_PUSH + pushId);

        Long second = (DateUtils.StringToDateTime(sendTime).getTime() - System.currentTimeMillis()) / 1000;
        scheduleJob.setStartTime(second.intValue());
        scheduleJob.setStartTimeFormat("ss");
        scheduleJob.setRepeatCount(0);
        scheduleJob.setIntervalTime(0);
        scheduleJob.setIntervalTimeFormat("dd");

        callBackParam.setBeanName("selfPushService");
        callBackParam.setMethodName("sendSelfMsgQuartz");
        callBackParam.setParamMap(map);
        Map<String, Object> scheduleMap = new HashMap<>();
        scheduleMap.put("scheduleJob", scheduleJob);
        scheduleMap.put("callBackParam", callBackParam);
        try {
            scheduleService.addSimpleJob(scheduleMap);
        } catch (Exception e) {
            log.error("【个人号群发】添加定时任务失败" + e.getMessage(), e);
        }
    }

    /**
     * 微信群消息推送
     */
    private void msgPush(List<String> userIdList, List<SelfPushItem> itemList, Long pushId) {
        SelfPush selfPush = selfPushDao.getById(pushId);
        if (!StringUtil.isEmpty(selfPush.getAltId())){//平台端群发
            String altId = selfPush.getAltId();
            List<String> sendUserIds = new ArrayList<>();
            sendUserIds.addAll(userIdList);
            ThreadPoolUtils.SEND_MESSAGE_THREAD_POOL.execute(() -> {
                for (String userId : sendUserIds) {
                    for (SelfPushItem pushItem : itemList) {
                        sendSelfMsg(userId, altId, pushItem);
                    }
                }
                selfPushItemDao.updatePushStatusByPushId(PushStatusEnum.SUCCESS.value, pushId);
            });
        }else if ( null != selfPush.getBookGroupId()){//编辑端群发
            Long bookGroupId = selfPush.getBookGroupId();
            if ("pro".equals(envStr) && ArrayUtils.contains(PushConstant.pro_demo_book_group_id,bookGroupId)) {
                //生产环境特定社群书，发给所有好友
                userIdList = bookGroupCipherUserDao.getFriendIdsByBookGroupId(bookGroupId);
            } else if ("uat".equalsIgnoreCase(envStr) && ArrayUtils.contains(PushConstant.uat_demo_book_group_id, bookGroupId)){
                userIdList = bookGroupCipherUserDao.getFriendIdsByBookGroupId(bookGroupId);
            }
            List<String> sendUserIds = new ArrayList<>();
            sendUserIds.addAll(userIdList);
            ThreadPoolUtils.SEND_MESSAGE_THREAD_POOL.execute(() -> {
                for (String userId : sendUserIds) {
                    //查好友对应的小号
                    SelfRobotBookGroupDTO bookGroupDTO = bookGroupCipherUserDao.getSelfRobotBookGroupInfoByUser(userId, bookGroupId);
                    String altId = bookGroupDTO.getWxId();
                    for (SelfPushItem pushItem : itemList) {
                        sendSelfMsg(userId, altId, pushItem);
                    }
                }
                selfPushItemDao.updatePushStatusByPushId(PushStatusEnum.SUCCESS.value, pushId);
            });
        }

    }

    /**
     * 群发项设置
     */
    private void setSelfPushItem(Long pushId, Boolean sendNow, Long partyId, List<SelfPushItem> itemList, Date sendTime) {
        Integer status;
        if (sendNow) {
            status = PushStatusEnum.PUSHING.value;
        } else {
            status = PushStatusEnum.WAIT.value;
        }
        itemList.forEach(selfPushItem -> {
            selfPushItem.setCreateUser(partyId);
            selfPushItem.setUpdateUser(partyId);
            selfPushItem.setPushId(pushId);
            selfPushItem.setPushStatus(status);
            selfPushItem.setSendTime(sendTime);
        });
        selfPushItemDao.insert(itemList);
    }
    /**
     * 群发用户设置
     */
    private void setSelfPushUser(List<String> userIdList, Long partyId, Long pushId) {
        List<SelfPushUser> userList = new ArrayList<>();
        for (String userId : userIdList) {
            SelfPushUser user = new SelfPushUser();
            user.setWxUserId(userId);
            userList.add(user);
        }
        userList.forEach(selfPushUser -> {
            selfPushUser.setCreateUser(partyId);
            selfPushUser.setPushId(pushId);
        });
        selfPushUserDao.insert(userList);
    }

    /**
     * 消息群发
     * @param userWxId
     * @param altId
     * @param selfPushItem
     */
    public void sendSelfMsg(String userWxId, String altId, SelfPushItem selfPushItem) {
        if (StringUtil.isEmpty(userWxId) || StringUtil.isEmpty(altId)){
            return;
        }
        Integer code = SendMessageTypeEnum.SELF.getCode();
        Integer itemType = selfPushItem.getItemType();
        if (ItemTypeEnum.TEXT.value.equals(itemType)) {
            SendTextMessageVO sendTextMessageVO = new SendTextMessageVO();
            sendTextMessageVO.setContent(selfPushItem.getTextContent());
            sendTextMessageVO.setCode(code);
            sendTextMessageVO.setWxId(altId);
            sendTextMessageVO.setAltId(altId);
            sendTextMessageVO.setWxGroupId(userWxId);
            sendTextMessageVO.setIp(getIpByRobot(altId));
            SendSelfMsgTools.sendTextMessage(sendTextMessageVO);
            return;
        }
        if (ItemTypeEnum.LINK.value.equals(itemType)) {
            SendArticleMessageVO sendArticleMessageVO = new SendArticleMessageVO();
            sendArticleMessageVO.setCode(code);
            sendArticleMessageVO.setAltId(altId);
            sendArticleMessageVO.setDescription(selfPushItem.getLinkDescription());
            sendArticleMessageVO.setWxGroupId(userWxId);
            String url = selfPushItem.getLinkUrl();
            sendArticleMessageVO.setLinkUrl(url);
            sendArticleMessageVO.setPicUrl(selfPushItem.getLinkImageUrl());
            sendArticleMessageVO.setTitle(selfPushItem.getLinkTitle());
            sendArticleMessageVO.setIp(getIpByRobot(altId));
            SendSelfMsgTools.sendArticleMessage(sendArticleMessageVO);
            return;
        }
        if (ItemTypeEnum.APP.value.equals(itemType)) {
            return;//应用类型不参与群发C1002029
        }
        if (ItemTypeEnum.IMAGE.value.equals(itemType)) {
            SendPicMessageVO sendPicMessageVO = new SendPicMessageVO();
            sendPicMessageVO.setCode(code);
            sendPicMessageVO.setAltId(altId);
            sendPicMessageVO.setWxGroupId(userWxId);
            sendPicMessageVO.setPicUrl(selfPushItem.getImageUrl());
            sendPicMessageVO.setIp(getIpByRobot(altId));
            SendSelfMsgTools.sendPicMessage(sendPicMessageVO);
            return;
        }
    }

    /**
     * 获取ip
     * @param altId
     * @return
     */
    private String getIpByRobot(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;
    }

    @Override
    public PageBeanNew<UserBookInfoVO> listSelfPushUser(Long pushId, Integer currentPage, Integer numPerPage) {
        Map<String, Object> map = new HashMap<>();
        map.put("pushId", pushId);
        PageBeanNew<UserBookInfoVO> pageBeanNew = selfPushUserDao.listPageNew(new PageParam(currentPage, numPerPage), map, "listByPushId");
        if (null == pageBeanNew || ListUtils.isEmpty(pageBeanNew.getRecordList())) {
            return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
        }
        groupSet.setUserBookInfo4SelfPush(pageBeanNew.getRecordList());
        return pageBeanNew;
    }

    @Override
    public PageBeanNew<SelfPushRecordDTO> listSelfPushRecord(Integer currentPage, Integer numPerPage, String startTime, String endTime, Integer status,Long partyId) {
        Map<String, Object> map = new HashMap<>();
        map.put("startTime", startTime);
        map.put("endTime", endTime);
        map.put("pushStatus", status);
        map.put("partyId", partyId);
        PageBeanNew<SelfPushRecordDTO> pageBeanNew = selfPushItemDao.listPageNew(new PageParam(currentPage, numPerPage), map, "listSelfPushRecord");
        if (null == pageBeanNew || ListUtils.isEmpty(pageBeanNew.getRecordList())) {
            return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
        }
        List<String> wxIds = pageBeanNew.getRecordList().stream().filter(s -> s != null).map(SelfPushRecordDTO::getAltId).distinct().collect(Collectors.toList());
        Map<String, GroupUserDTO> robotMap = new HashMap<>();
        if (!ListUtils.isEmpty(wxIds)){
            robotMap = wechatGroupConsr.mapRobotInfoByIdList(wxIds);
        }
        for (SelfPushRecordDTO dto : pageBeanNew.getRecordList()) {
            Integer userCount = selfPushUserDao.getCountByPushId(dto.getPushId());
            dto.setUserCount(userCount);
            if (!MapUtils.isEmpty(robotMap) && !StringUtil.isEmpty(dto.getAltId()) && robotMap.containsKey(dto.getAltId())) {
                GroupUserDTO userDTO = robotMap.get(dto.getAltId());
                dto.setRobotName(userDTO.getNickName());
            }
            if (null != dto.getBookGroupId()){
                BookGroupDTO bookGroupDTO = bookGroupDao.getBookBaseInfoById(dto.getBookGroupId());
                dto.setBookName(bookGroupDTO.getBookName());
            }
        }
        return pageBeanNew;
    }

    @Override
    public void sendSelfMsgQuartz(Long pushId) {
        SelfPush selfPush = selfPushDao.getById(pushId);
        if (null == selfPush) {
            return;
        }
        List<String> userIdList = selfPushUserDao.getUserIdListByPushId(pushId);
        List<SelfPushItem> itemList = selfPushItemDao.getByPushId(pushId);
        if (ListUtils.isEmpty(userIdList) || ListUtils.isEmpty(itemList)) {
            return;
        }
        selfPushItemDao.updatePushStatusByPushId(PushStatusEnum.PUSHING.value, pushId);
        msgPush(userIdList, itemList, pushId);
    }
}
