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

import com.alibaba.fastjson.JSON;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.consumer.promotion.PromotionConsr;
import com.pcloud.book.consumer.wechatgroup.WechatGroupConsr;
import com.pcloud.book.group.biz.WeixinQrcodeBiz;
import com.pcloud.book.group.dao.GroupQrcodeDao;
import com.pcloud.book.group.dao.WeixinQrcodeDao;
import com.pcloud.book.group.dao.WeixinQrcodeGenerationDao;
import com.pcloud.book.group.dto.BookWxQrcodeDTO;
import com.pcloud.book.group.dto.ChangeGroupNameDTO;
import com.pcloud.book.group.dto.SyncWeixinGroupIdRequestDTO;
import com.pcloud.book.group.dto.UpdateQrDTO;
import com.pcloud.book.group.dto.WeixinQrcodeCountDTO;
import com.pcloud.book.group.dto.WeixinQrcodeDTO;
import com.pcloud.book.group.entity.WeixinQrcode;
import com.pcloud.book.group.entity.WeixinQrcodeGeneration;
import com.pcloud.book.group.enums.JoinGroupTypeEnum;
import com.pcloud.book.group.enums.UpdateStatusEnum;
import com.pcloud.book.group.tools.Kit;
import com.pcloud.book.group.tools.QrcodeTools;
import com.pcloud.book.group.tools.SendWeixinRequestTools;
import com.pcloud.book.group.vo.QrStatisticsVO;
import com.pcloud.book.group.vo.WeixinQrcodeVO;
import com.pcloud.book.util.common.ThreadPoolUtils;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.core.biz.MessageBiz;
import com.pcloud.common.core.dto.SendEmailDto;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.QrcodeUtils;
import com.pcloud.common.utils.cache.redis.JedisClusterUtils;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.wechatgroup.group.dto.GroupRobotDTO;
import com.sdk.wxgroup.AddToGroupVO;
import com.sdk.wxgroup.QrcodeVO;
import com.sdk.wxgroup.WxGroupSDK;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author lily
 * @date 2019/4/17 16:10
 */
@Component("weixinQrcodeBiz")
public class WeixinQrcodeBizImpl implements WeixinQrcodeBiz {
    private static final Logger LOGGER = LoggerFactory.getLogger(WeixinQrcodeBizImpl.class);
    @Autowired
    private WeixinQrcodeDao weixinQrcodeDao;
    @Value("${fission.use.email}")
    private String fissionUseEmail;
    @Autowired
    private GroupQrcodeDao groupQrcodeDao;
    @Autowired
    private MessageBiz messageBiz;
    @Autowired
    private PromotionConsr promotionConsr;
    @Autowired
    private WechatGroupConsr wechatGroupConsr;
    @Autowired
    private WeixinQrcodeBiz weixinQrcodeBiz;
    @Autowired
    private WeixinQrcodeGenerationDao weixinQrcodeGenerationDao;


    @Override
    public Long countWechatGroup(){
        return weixinQrcodeDao.countWechatGroup();
    }

    @Override
    @ParamLog("从二维码库获取一个二维码")
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public WeixinQrcodeDTO getOneQrcode(Integer joinGroupType, String altId) {
        Integer generation = null;
        if (JoinGroupTypeEnum.ROBOT.getCode().equals(joinGroupType) && !StringUtil.isEmpty(altId)) {
            //个人号模式获取群，根据小号是第几套获取是第几个套群
            GroupRobotDTO groupRobotDTO = wechatGroupConsr.getGroupRobotByWxId(altId);
            if (groupRobotDTO != null) {
                generation = groupRobotDTO.getVersion();
            }
        }
        WeixinQrcodeDTO qrcodeVO = weixinQrcodeDao.getOneWechatGroup(generation);
        if (qrcodeVO == null) {
            return null;
        }
        //更新二维码
        Integer number = weixinQrcodeDao.setIsUseById(qrcodeVO.getId());
        if (number > 0) {
            ThreadPoolUtils.OTHER_THREAD_POOL.execute(()->{
                wechatGroupConsr.addGroupManagers(qrcodeVO.getWeixinGroupId(), qrcodeVO.getRobotWxId());
            });
            //获取当前群人数
            try {
                final String weixinGroupId = qrcodeVO.getWeixinGroupId();
                final Map<String, BookWxQrcodeDTO> groupVersion = weixinQrcodeBiz.getGroupVersion(Collections.singletonList(weixinGroupId));
                Integer peopleCounts = WxGroupSDK.getPeopleCounts(weixinGroupId, qrcodeVO.getRobotWxId(), Optional.ofNullable(groupVersion.get(weixinGroupId)).orElse(new BookWxQrcodeDTO()).getWechatGroupIp());
                qrcodeVO.setUserNumber(peopleCounts);
            } catch (Exception e) {
                qrcodeVO.setUserNumber(0);
            }
//            if(qrcodeVO.getUserNumber() == 0){
//                return getOneQrcode();
//            }
            return qrcodeVO;
        } else {
            return null;
        }
    }

    @Override
    @ParamLog("不足100个发送邮件")
    public void sendMsgByQrCount() {
        QrStatisticsVO qrStatistics = weixinQrcodeDao.getQrStatistics();
        if (qrStatistics != null && qrStatistics.getNotUseCount() < 100) {
            SendEmailDto sendEmailDto = new SendEmailDto();
            sendEmailDto.setToEmail(fissionUseEmail);
            sendEmailDto.setTypeCode("qrcode_add_email");
            sendEmailDto.setContent(new HashMap<>());
            messageBiz.sendEmail(sendEmailDto);
        }
    }

    @Override
    public void setUpdateQrUrlByQuartz() {
        ThreadPoolUtils.OTHER_THREAD_POOL.execute(() -> {
            setUpdateQrUrl();
            //setUpdateQr4Error(null);
        });
    }

    @Override
    @ParamLog("发起更新二维码地址请求")
    public void setUpdateQrUrl() {
        Integer totalCount = JedisClusterUtils.getJson("BOOK:UPDATEQR", Integer.class);
        if (totalCount == null) {
            totalCount = 3000;
            JedisClusterUtils.setJson("BOOK:UPDATEQR", totalCount);
        }
        //将处理中的二维码改为处理失败（3）
        weixinQrcodeDao.updateStatusToError();
        Integer numPerPage = 50;
        for (int i = 0, size = (totalCount - 1) / numPerPage + 1; i < size; i++) {
            List<UpdateQrDTO> updateQrs = weixinQrcodeDao.getInitialQr(0, numPerPage);
            if (ListUtils.isEmpty(updateQrs)) {
                break;
            }
            //将二维码更新未正在处理
            List<Long> qrIds = updateQrs.stream()
                    .map(UpdateQrDTO::getId).distinct()
                    .collect(Collectors.toList());
            weixinQrcodeDao.setOnUpdate(qrIds);
            //SendWeixinRequestTools.updateQrUrl(updateQrs);
        }
    }

    @Override
    @ParamLog("更新二维码状态")
    @Transactional(rollbackFor = Exception.class)
    public void updateQrUrl(UpdateQrDTO updateQrDTO) {
        String qrcodeUrl = updateQrDTO.getUrl();
        if (UpdateStatusEnum.FIAL.value.equals(updateQrDTO.getUpdateState())) {
            updateQrDTO.setUrl(null);
        } else if (UpdateStatusEnum.SUCCESS.value.equals(updateQrDTO.getUpdateState())) {
            if (!StringUtil.isEmpty(qrcodeUrl)) {
                String url = QrcodeUtils.create(qrcodeUrl);
                //url = QrcodeTools.ossToFile(url);
                updateQrDTO.setUrl(StringUtil.isEmpty(url) ? null : url);
            } else {
                updateQrDTO.setUrl(null);
            }
        }
        weixinQrcodeDao.updateQrUrl(updateQrDTO);
        //如果是更新成功，更群二维码信息
        if (UpdateStatusEnum.SUCCESS.value.equals(updateQrDTO.getUpdateState()) && !StringUtil.isEmpty(updateQrDTO.getUrl())) {
            groupQrcodeDao.updateQrUrl(updateQrDTO);
            com.pcloud.promotion.fission.dto.UpdateQrDTO updateQr = new com.pcloud.promotion.fission.dto.UpdateQrDTO();
            BeanUtils.copyProperties(updateQrDTO, updateQr);
            promotionConsr.updateQrUrl(updateQr);
        }
    }

    @Override
    @ParamLog("发起未处理的二维码更新请求")
    public void setUpdateQr4Error(List<Long> ids) {
        int numPerPage = 50;
        Integer counts = 0;
        if (!ListUtils.isEmpty(ids)) {
            counts = ids.size();
        } else {
            ids = null;
            counts = weixinQrcodeDao.getQrOnHandleCount();
        }
        if (counts > 0) {
            for (int i = 0, size = (counts - 1) / numPerPage + 1; i < size; i++) {
                List<UpdateQrDTO> updateQrs = weixinQrcodeDao.getQrOnHandle(i * numPerPage, numPerPage, ids);
                if (ListUtils.isEmpty(updateQrs)) {
                    break;
                }
                updateQrUrlVIP(updateQrs);
            }
        }
    }

    @Override
    @ParamLog("发送更新群名称请求")
    public void sendChangeGroupNameRequest(List<Long> ids) {
        if (ListUtils.isEmpty(ids)) {
            return;
        }
        //获取对应群信息
        List<ChangeGroupNameDTO> changeGroupNameDTOS = groupQrcodeDao.getWechatGroupInfo(ids);
        if (ListUtils.isEmpty(changeGroupNameDTOS)) {
            return;
        }
        for (ChangeGroupNameDTO changeGroupNameDTO : changeGroupNameDTOS) {
            String robotId = wechatGroupConsr.getRobotIdByGroupId(changeGroupNameDTO.getWxGroupId());
            final String wechatGroupId = changeGroupNameDTO.getWxGroupId();
            Map<String, BookWxQrcodeDTO> groupVersion = weixinQrcodeBiz.getGroupVersion(Collections.singletonList(wechatGroupId));
            String ip = Optional.ofNullable(groupVersion.get(wechatGroupId)).orElse(new BookWxQrcodeDTO()).getWechatGroupIp();
            SendWeixinRequestTools.changeGroupName(robotId, changeGroupNameDTO.getWxGroupId(), changeGroupNameDTO.getWxGroupName(), ip);
        }
    }

    @Override
    @ParamLog("同步更新微信群标识")
    public void syncWeixinGroupId(Long weixinQrcodeId, String weixinGroupId) {
        if (weixinQrcodeId == null || weixinGroupId == null) {
            return;
        }
//        //获取群二维码基本信息
//        WeixinQrcode weixinQrcode = weixinQrcodeDao.getById(weixinQrcodeId);
//        if (weixinQrcode == null) return;
//        if (StringUtil.isEmpty(weixinQrcode.getWeixinGroupId())) {
//            wechatGroupConsr.addGroupManagers(weixinGroupId, weixinQrcode.getRobotWxId());
//        }
        Boolean isExist = weixinQrcodeDao.checkExist(weixinGroupId);
        if (isExist) {
            weixinQrcodeDao.updateState(weixinQrcodeId, 5);
            return;
        }
        weixinQrcodeDao.updateWeixinGroupId(weixinQrcodeId, weixinGroupId);
        groupQrcodeDao.syncWeixinGroupId(weixinQrcodeId, weixinGroupId);
    }

    @ParamLog("发送同步微信id请求")
    @Override
    public void sendSyncWeixinGroupIdRequest(List<Long> ids) {
        ids = ListUtils.isEmpty(ids) ? null : ids;
        List<SyncWeixinGroupIdRequestDTO> weixinGroupIdDTOS = weixinQrcodeDao.listNoIdQrcode(ids);
        SendWeixinRequestTools.syncWeixinGroupIds(weixinGroupIdDTOS);
    }

    @ParamLog("新增二维码")
    @Override
    public void addQrcode(WeixinQrcodeVO weixinQrcodeVO, Long partyId) {
        if (null == weixinQrcodeVO.getGeneration()){
            throw new BookBizException(BookBizException.ERROR, "请选择微信群版本！");
        }
        WeixinQrcode weixinQrcode = new WeixinQrcode();
        BeanUtils.copyProperties(weixinQrcodeVO, weixinQrcode);
        weixinQrcode.setCreateUser(partyId);
        if (weixinQrcodeVO.getQrcodeUrl() == null) {
            throw new BookBizException(BookBizException.ERROR, "请上传微信群二维码！");
        }
        String newUrl = "";
        if(!StringUtil.isEmpty(weixinQrcodeVO.getWeixinGroupId())){
            Boolean isExist = weixinQrcodeDao.checkExist(weixinQrcodeVO.getWeixinGroupId());
            if (isExist){
                return;
            }
            newUrl = QrcodeUtils.create(weixinQrcodeVO.getQrcodeUrl());
            if(Objects.isNull(weixinQrcodeVO.getRobotId())) {
                LOGGER.info("[新增二维码] robotId is null");
                GroupRobotDTO groupRobotDTO = wechatGroupConsr.getRobotInfoByWxUserId(weixinQrcodeVO.getRobotWxId());
                if(groupRobotDTO != null){
                    weixinQrcode.setRobotId(Long.valueOf(groupRobotDTO.getId()));
                }
            } else {
                weixinQrcode.setRobotId(weixinQrcodeVO.getRobotId());
            }
            weixinQrcode.setUpdateState(0);
        }else {
            weixinQrcode.setWeixinGroupId("");
            weixinQrcode.setUpdateState(4);
            newUrl = QrcodeTools.reCreateQrcode(weixinQrcodeVO.getQrcodeUrl());
        }
        if (weixinQrcodeVO.getQrcodeUrl().equalsIgnoreCase(newUrl)) {
            throw new BookBizException(BookBizException.ERROR, "二维码无法识别，请重新上传！");
        }
        weixinQrcode.setQrcodeUrl(newUrl);
        weixinQrcode.setGeneration(weixinQrcodeVO.getGeneration());
        Long qrcodeId = weixinQrcodeDao.insert(weixinQrcode);
        //若需要同步微信群id 则同步微信群
        if(StringUtil.isEmpty(weixinQrcodeVO.getWeixinGroupId())){
            SendWeixinRequestTools.syncOneWeixinGroupId(qrcodeId, newUrl, weixinQrcodeVO.getRobotWxId());
        }
    }

    @Override
    @ParamLog("获取机器人二维码分配情况")
    public Map<Long, WeixinQrcodeCountDTO> listWeixinQrcodeCountByRobot(List<Long> robotIds) {
        if (ListUtils.isEmpty(robotIds)) {
            return null;
        }
        Map<Long, WeixinQrcodeCountDTO> robotQrCountMap = weixinQrcodeDao.listWeixinQrcodeCountByRobot(robotIds);
        return robotQrCountMap;
    }

    @Override
    public void updateUseState(Long weixinQrcodeId, Integer useState) {
        weixinQrcodeDao.updateUseState(weixinQrcodeId, useState);
    }

    @Override
    @ParamLog("获取平台端统计数据")
    public QrStatisticsVO getQrStatistics() {
        QrStatisticsVO qrStatistics = weixinQrcodeDao.getQrStatistics();
        if (qrStatistics == null) {
            qrStatistics = new QrStatisticsVO();
            qrStatistics.setInUseCount(0);
            qrStatistics.setNotUseCount(0);
        }
        Integer count = weixinQrcodeDao.getQrcodeCount();
        qrStatistics.setAllCount(count);
        return qrStatistics;
    }

    @Override
    @ParamLog("按照版本分类获取平台端统计数据")
    public List<QrStatisticsVO> getQrStatisticsByVersion() {
        List<QrStatisticsVO> qrStatistics = weixinQrcodeDao.getQrStatisticsByVersion();
        List<QrStatisticsVO> counts = weixinQrcodeDao.getQrcodeCountByVersion();
        if (ListUtils.isEmpty(qrStatistics)) {
            qrStatistics = new ArrayList<>();
            QrStatisticsVO qr = new QrStatisticsVO();
            qr.setAllCount(0);
            qr.setInUseCount(0);
            qr.setNotUseCount(0);
            qr.setVersion(0);
            qrStatistics.add(qr);
            return qrStatistics;
        }

        // 组合两部分数据
        for(QrStatisticsVO qr:qrStatistics){
            List<Integer> list = Arrays.asList(1, 2, 4);
            //社群吗需要过滤过期的群，个人码不需要
            if (list.contains(qr.getVersion())) {
                qr.setCanUseCount(weixinQrcodeDao.getCanUseCount(qr.getVersion()));
            }else {
                qr.setCanUseCount(qr.getNotUseCount());
            }
            for(QrStatisticsVO c: counts){
                if(qr.getVersion().equals(c.getVersion())){
                    qr.setAllCount(c.getAllCount());
                    break;
                }
            }
        }

        return qrStatistics;
    }

    @Override
    @ParamLog("分页获取可用微信群")
    public List<BookWxQrcodeDTO> listAvailableGroupByPage(Integer currentPage, Integer numPerPage) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("currentPage", currentPage);
        paramMap.put("numPerPage", numPerPage);
        List<BookWxQrcodeDTO> wxQrcodeDTOS = weixinQrcodeDao.listAvailableGroupByPage(paramMap);
        return wxQrcodeDTOS;
    }

    @Override
    @ParamLog("分页获取人数超过10人的可用微信群")
    public List<BookWxQrcodeDTO> listOver10AvailableGroupByPage(Integer currentPage, Integer numPerPage) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("currentPage", currentPage);
        paramMap.put("numPerPage", numPerPage);
        return weixinQrcodeDao.listOver10AvailableGroupByPage(paramMap);
    }

    @Override
    @ParamLog("所有群邀请新的机器人小号")
    public void inviteNewRobot(String wxUserId) {
        for(int i = 0; true ; i++) {
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("currentPage", i * 100);
            paramMap.put("numPerPage", 100);
            List<BookWxQrcodeDTO> wxQrcodeDTOS = weixinQrcodeDao.listAvailableGroupByPage(paramMap);
            for(BookWxQrcodeDTO wxQrcodeDTO: wxQrcodeDTOS) {
                if(null != wxQrcodeDTO) {
                    String weixinGroupId = wxQrcodeDTO.getWeixinGroupId();
                    String robotWxId = wxQrcodeDTO.getRobotWxId();
                   /* GroupInfoVO groupInfoVO = WxGroupSDK.getGroupInfo(weixinGroupId, robotWxId);
                    if(null != groupInfoVO) {
                        List<String> memberIds = groupInfoVO.getIdList();
                        if(!memberIds.contains(wxUserId)) {
                        }
                    }*/
                    try {
                        Thread.sleep(10000);
                        LOGGER.info("邀请新的机器人==线程休眠5秒！！！");
                    } catch (InterruptedException e) {
                        LOGGER.error("线程休眠失败" + e.getMessage());
                    }

                    AddToGroupVO addToGroupVO = new AddToGroupVO();
                    addToGroupVO.setWxGroupId(weixinGroupId);
                    addToGroupVO.setAltId(robotWxId);
                    addToGroupVO.setWxId(wxUserId);
                    WxGroupSDK.addToGroup(addToGroupVO);

                }
            }

            if(wxQrcodeDTOS.size() < 100) {
                break;
            }
        }
    }

    @Override
    public Map<String, BookWxQrcodeDTO> getGroupVersion(List<String> wxGroupIds) {
        if (ListUtils.isEmpty(wxGroupIds)) {
            return new HashMap<>();
        }
        Map<String, BookWxQrcodeDTO> dtoMap = weixinQrcodeDao.listByWxGroupIds(wxGroupIds);
        return dtoMap == null ? new HashMap<>() : dtoMap;
    }

    @Override
    public void updateGenerationMachineIp(Integer generation, String machineIp) {
        if (null == generation || StringUtil.isEmpty(machineIp)) {
            return;
        }
        weixinQrcodeDao.updateGenerationMachineIp(generation, machineIp);
    }

    @ParamLog("根据版本号获取机器人ip")
    @Override
    public Map<Integer, String> getRobotWxGroupIpByGeneration(List<Integer> generations) {
        Map<Integer, String> map = new HashMap<>();
        if (ListUtils.isEmpty(generations)) {
            return map;
        }
        List<WeixinQrcodeGeneration> weixinQrcodeGenerations = weixinQrcodeGenerationDao.getListByGenerations(generations);
        if (!ListUtils.isEmpty(weixinQrcodeGenerations)) {
            for (WeixinQrcodeGeneration weixinQrcodeGeneration : weixinQrcodeGenerations) {
                map.put(weixinQrcodeGeneration.getGeneration(), weixinQrcodeGeneration.getWechatGroupIp());
            }
        }
        return map;
    }

    @ParamLog("根据版本号获取机器人ip")
    @Override
    public String getRobotIpByGeneration(Integer generation) {
        String ip = null;
        WeixinQrcodeGeneration weixinQrcodeGeneration = weixinQrcodeGenerationDao.getByGeneration(generation);
        if (null != weixinQrcodeGeneration) {
            ip = weixinQrcodeGeneration.getWechatGroupIp();
        }
        return ip;
    }

    private void updateQrUrlVIP(List<UpdateQrDTO> updateQrs) {
        if (ListUtils.isEmpty(updateQrs)) {
            return;
        }
        List<Integer> generations = updateQrs.stream().map(UpdateQrDTO::getGeneration).collect(Collectors.toList());
        Map<Integer, List<QrcodeVO>> map = new HashMap<>();
        generations.forEach(item -> map.put(item, new ArrayList<>()));
        for (UpdateQrDTO updateQrDTO : updateQrs) {
            QrcodeVO qrcodeVO = new QrcodeVO();
            qrcodeVO.setPriority(2);
            qrcodeVO.setId(updateQrDTO.getId());
            qrcodeVO.setOperation(0);
            qrcodeVO.setAltId(updateQrDTO.getRobotWxId());
            String url = updateQrDTO.getUrl();
            if (url.contains("https://oss")) {
                url = url.replace("//oss", "//file");
            }
            qrcodeVO.setUrl(url);
            qrcodeVO.setRequestUrl("/book/v1.0/weixinQrcodeService/updateQrUrl");
            Integer generation = updateQrDTO.getGeneration();
            List<QrcodeVO> list = map.get(generation);
            list.add(qrcodeVO);
        }
        for (Map.Entry<Integer, List<QrcodeVO>> entry : map.entrySet()) {
            Integer generation = entry.getKey();
            List<QrcodeVO> qrcodeList = entry.getValue();
            String virtualMachineIp = weixinQrcodeDao.getVirtualIp(generation);
            try {
                Kit.post("http://" + virtualMachineIp + ":8080/autoGroup", JSON.toJSONString(qrcodeList));
            } catch (Exception e) {
                LOGGER.error("更新二维码地址（7天过期更新VIP插队）失败", e);
            }
        }
    }

}
